From 34c361cfb2e7aa3efffe8783d2c31afc9e43f040 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 11 Nov 2016 18:22:41 -0500 Subject: when creating an AssociatedItem, read data from impl, not impl item Before, when we created an AssociatedItem for impl item X, we would read the impl item itself. Now we instead load up the impl I that contains X and read the data from the `ImplItemRef` for X; actually, we do it for all impl items in I pre-emptively. This kills the last source of edges between a method X and a call to a method Y defined in the same impl. Fixes #37121 --- .../change_private_impl_method/struct_point.rs | 11 ++++----- .../change_private_impl_method_cc/struct_point.rs | 26 +++++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) (limited to 'src/test/incremental') diff --git a/src/test/incremental/change_private_impl_method/struct_point.rs b/src/test/incremental/change_private_impl_method/struct_point.rs index 8fa34bde170..46e5a88eef9 100644 --- a/src/test/incremental/change_private_impl_method/struct_point.rs +++ b/src/test/incremental/change_private_impl_method/struct_point.rs @@ -20,9 +20,8 @@ #![rustc_partition_translated(module="struct_point-point", cfg="rpass2")] -// FIXME(#37121) -- the following two modules *should* be reused but are not -#![rustc_partition_translated(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")] -#![rustc_partition_translated(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] @@ -60,8 +59,7 @@ mod point { mod fn_calls_methods_in_same_impl { use point::Point; - // FIXME(#37121) -- we should not need to typeck this again - #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] pub fn check() { let x = Point { x: 2.0, y: 2.0 }; x.distance_from_origin(); @@ -72,8 +70,7 @@ mod fn_calls_methods_in_same_impl { mod fn_calls_methods_in_another_impl { use point::Point; - // FIXME(#37121) -- we should not need to typeck this again - #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] pub fn check() { let mut x = Point { x: 2.0, y: 2.0 }; x.translate(3.0, 3.0); diff --git a/src/test/incremental/change_private_impl_method_cc/struct_point.rs b/src/test/incremental/change_private_impl_method_cc/struct_point.rs index d8e5fbadad8..a8779e3f92d 100644 --- a/src/test/incremental/change_private_impl_method_cc/struct_point.rs +++ b/src/test/incremental/change_private_impl_method_cc/struct_point.rs @@ -19,12 +19,15 @@ #![feature(stmt_expr_attributes)] #![allow(dead_code)] -// FIXME(#37333) -- the following modules *should* be reused but are not +#![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] + +// FIXME(#37333) the struct fields get entangled with inherent methods +#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="rpass2")] + +// FIXME(#37720) these two should be reused, but data gets entangled across crates #![rustc_partition_translated(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")] #![rustc_partition_translated(module="struct_point-fn_calls_methods_in_another_impl", cfg="rpass2")] -#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="rpass2")] -#![rustc_partition_translated(module="struct_point-fn_read_field", cfg="rpass2")] -#![rustc_partition_translated(module="struct_point-fn_write_field", cfg="rpass2")] extern crate point; @@ -32,7 +35,7 @@ extern crate point; mod fn_calls_methods_in_same_impl { use point::Point; - // FIXME(#37333) -- we should not need to typeck this again + // FIXME(#37720) data gets entangled across crates #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] pub fn check() { let x = Point { x: 2.0, y: 2.0 }; @@ -44,9 +47,9 @@ mod fn_calls_methods_in_same_impl { mod fn_calls_methods_in_another_impl { use point::Point; - // FIXME(#37333) -- we should not need to typeck this again + // FIXME(#37720) data gets entangled across crates #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] - pub fn check() { + pub fn dirty() { let mut x = Point { x: 2.0, y: 2.0 }; x.translate(3.0, 3.0); } @@ -56,8 +59,7 @@ mod fn_calls_methods_in_another_impl { mod fn_make_struct { use point::Point; - // FIXME(#37333) -- we should not need to typeck this again - #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] pub fn make_origin() -> Point { Point { x: 2.0, y: 2.0 } } @@ -67,8 +69,7 @@ mod fn_make_struct { mod fn_read_field { use point::Point; - // FIXME(#37333) -- we should not need to typeck this again - #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] pub fn get_x(p: Point) -> f32 { p.x } @@ -78,8 +79,7 @@ mod fn_read_field { mod fn_write_field { use point::Point; - // FIXME(#37333) -- we should not need to typeck this again - #[rustc_dirty(label="TypeckItemBody", cfg="rpass2")] + #[rustc_clean(label="TypeckItemBody", cfg="rpass2")] pub fn inc_x(p: &mut Point) { p.x += 1.0; } -- cgit 1.4.1-3-g733a5 From b10b98169ff7350236e96f99ddb2f5d4cbef732b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 14 Nov 2016 11:00:02 -0500 Subject: hash the contents of impl-item-ref by adding them to visitor Also simplify some of the `ty::AssociatedItem` representation, in particular by folding `has_value` into `hir::Defaultness` --- src/librustc/hir/intravisit.rs | 39 ++++++- src/librustc/hir/lowering.rs | 19 +-- src/librustc/hir/mod.rs | 15 ++- src/librustc/hir/print.rs | 5 +- src/librustc/traits/project.rs | 4 +- src/librustc/ty/mod.rs | 7 +- .../calculate_svh/svh_visitor.rs | 14 +++ src/librustc_metadata/decoder.rs | 3 - src/librustc_metadata/encoder.rs | 17 ++- src/librustc_metadata/schema.rs | 19 ++- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/impl_wf_check.rs | 2 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 5 +- src/test/incremental/hashes/inherent_impls.rs | 128 +++++++++++++++++++++ 17 files changed, 234 insertions(+), 55 deletions(-) create mode 100644 src/test/incremental/hashes/inherent_impls.rs (limited to 'src/test/incremental') diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 887b1febf65..4cfa889ec56 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -267,6 +267,12 @@ pub trait Visitor<'v> : Sized { fn visit_vis(&mut self, vis: &'v Visibility) { walk_vis(self, vis) } + fn visit_associated_item_kind(&mut self, kind: &'v AssociatedItemKind) { + walk_associated_item_kind(self, kind); + } + fn visit_defaultness(&mut self, defaultness: &'v Defaultness) { + walk_defaultness(self, defaultness); + } } pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option) { @@ -740,10 +746,14 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { - visitor.visit_vis(&impl_item.vis); - visitor.visit_name(impl_item.span, impl_item.name); - walk_list!(visitor, visit_attribute, &impl_item.attrs); - match impl_item.node { + // NB: Deliberately force a compilation error if/when new fields are added. + let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item; + + visitor.visit_name(span, name); + visitor.visit_vis(vis); + visitor.visit_defaultness(defaultness); + walk_list!(visitor, visit_attribute, attrs); + match *node { ImplItemKind::Const(ref ty, ref expr) => { visitor.visit_id(impl_item.id); visitor.visit_ty(ty); @@ -767,8 +777,13 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt } pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) { - visitor.visit_nested_impl_item(impl_item_ref.id); - visitor.visit_name(impl_item_ref.span, impl_item_ref.name); + // NB: Deliberately force a compilation error if/when new fields are added. + let ImplItemRef { id, name, ref kind, span, ref vis, ref defaultness } = *impl_item_ref; + visitor.visit_nested_impl_item(id); + visitor.visit_name(span, name); + visitor.visit_associated_item_kind(kind); + visitor.visit_vis(vis); + visitor.visit_defaultness(defaultness); } @@ -941,6 +956,18 @@ pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) { } } +pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssociatedItemKind) { + // No visitable content here: this fn exists so you can call it if + // the right thing to do, should content be added in the future, + // would be to walk it. +} + +pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) { + // No visitable content here: this fn exists so you can call it if + // the right thing to do, should content be added in the future, + // would be to walk it. +} + #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)] pub struct IdRange { pub min: NodeId, diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d1b57586ffd..05c4ae52180 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -699,7 +699,7 @@ impl<'a> LoweringContext<'a> { name: i.ident.name, attrs: this.lower_attrs(&i.attrs), vis: this.lower_visibility(&i.vis), - defaultness: this.lower_defaultness(i.defaultness), + defaultness: this.lower_defaultness(i.defaultness, true /* [1] */), node: match i.node { ImplItemKind::Const(ref ty, ref expr) => { hir::ImplItemKind::Const(this.lower_ty(ty), this.lower_expr(expr)) @@ -715,6 +715,8 @@ impl<'a> LoweringContext<'a> { span: i.span, } }) + + // [1] since `default impl` is not yet implemented, this is always true in impls } fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef { @@ -723,7 +725,7 @@ impl<'a> LoweringContext<'a> { name: i.ident.name, span: i.span, vis: self.lower_visibility(&i.vis), - defaultness: self.lower_defaultness(i.defaultness), + defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), kind: match i.node { ImplItemKind::Const(..) => hir::AssociatedItemKind::Const, ImplItemKind::Type(..) => hir::AssociatedItemKind::Type, @@ -732,9 +734,9 @@ impl<'a> LoweringContext<'a> { }, ImplItemKind::Macro(..) => unimplemented!(), }, - // since `default impl` is not yet implemented, this is always true in impls - has_value: true, } + + // [1] since `default impl` is not yet implemented, this is always true in impls } fn lower_mod(&mut self, m: &Mod) -> hir::Mod { @@ -1650,10 +1652,13 @@ impl<'a> LoweringContext<'a> { } } - fn lower_defaultness(&mut self, d: Defaultness) -> hir::Defaultness { + fn lower_defaultness(&mut self, d: Defaultness, has_value: bool) -> hir::Defaultness { match d { - Defaultness::Default => hir::Defaultness::Default, - Defaultness::Final => hir::Defaultness::Final, + Defaultness::Default => hir::Defaultness::Default { has_value: has_value }, + Defaultness::Final => { + assert!(has_value); + hir::Defaultness::Final + } } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 9dac6fac100..9f5ff6914b0 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1259,17 +1259,27 @@ pub enum Constness { #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Defaultness { - Default, + Default { has_value: bool }, Final, } impl Defaultness { + pub fn has_value(&self) -> bool { + match *self { + Defaultness::Default { has_value, .. } => has_value, + Defaultness::Final => true, + } + } + pub fn is_final(&self) -> bool { *self == Defaultness::Final } pub fn is_default(&self) -> bool { - *self == Defaultness::Default + match *self { + Defaultness::Default { .. } => true, + _ => false, + } } } @@ -1584,7 +1594,6 @@ pub struct ImplItemRef { pub span: Span, pub vis: Visibility, pub defaultness: Defaultness, - pub has_value: bool, } #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 5a381a189fc..807bbec3b58 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1036,8 +1036,9 @@ impl<'a> State<'a> { self.maybe_print_comment(ii.span.lo)?; self.print_outer_attributes(&ii.attrs)?; - if let hir::Defaultness::Default = ii.defaultness { - self.word_nbsp("default")?; + match ii.defaultness { + hir::Defaultness::Default { .. } => self.word_nbsp("default")?, + hir::Defaultness::Final => (), } match ii.node { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index ac2f3ad9b89..ca7d2ac3c69 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -943,7 +943,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( // an error when we confirm the candidate // (which will ultimately lead to `normalize_to_error` // being invoked). - node_item.item.has_value + node_item.item.defaultness.has_value() } else { node_item.item.defaultness.is_default() }; @@ -1304,7 +1304,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( match assoc_ty { Some(node_item) => { - let ty = if !node_item.item.has_value { + let ty = if !node_item.item.defaultness.has_value() { // This means that the impl is missing a definition for the // associated type. This error will be reported by the type // checker method `check_impl_items_against_trait`, so here we diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9984dd42f56..f5c23401a4e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -189,7 +189,6 @@ pub struct AssociatedItem { pub kind: AssociatedKind, pub vis: Visibility, pub defaultness: hir::Defaultness, - pub has_value: bool, pub container: AssociatedItemContainer, /// Whether this is a method with an explicit self @@ -2072,7 +2071,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn provided_trait_methods(self, id: DefId) -> Vec { self.associated_items(id) - .filter(|item| item.kind == AssociatedKind::Method && item.has_value) + .filter(|item| item.kind == AssociatedKind::Method && item.defaultness.has_value()) .collect() } @@ -2180,8 +2179,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { name: trait_item.name, kind: kind, vis: Visibility::from_hir(&hir::Inherited, trait_item.id, self), - defaultness: hir::Defaultness::Default, - has_value: has_value, + defaultness: hir::Defaultness::Default { has_value: has_value }, def_id: def_id, container: TraitContainer(parent_def_id), method_has_self_argument: has_self @@ -2211,7 +2209,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { kind: kind, vis: ty::Visibility::from_hir(vis, impl_item_ref.id.node_id, self), defaultness: impl_item_ref.defaultness, - has_value: true, def_id: def_id, container: ImplContainer(parent_def_id), method_has_self_argument: has_self diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 318cc83d9ad..fa2eff817ea 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -199,6 +199,8 @@ enum SawAbiComponent<'a> { SawExpr(SawExprComponent<'a>), SawStmt, SawVis, + SawAssociatedItemKind(hir::AssociatedItemKind), + SawDefaultness(hir::Defaultness), SawWherePredicate, SawTyParamBound, SawPolyTraitRef, @@ -693,6 +695,18 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has visit::walk_vis(self, v) } + fn visit_associated_item_kind(&mut self, kind: &'tcx AssociatedItemKind) { + debug!("visit_associated_item_kind: st={:?}", self.st); + SawAssociatedItemKind(*kind).hash(self.st); + visit::walk_associated_item_kind(self, kind); + } + + fn visit_defaultness(&mut self, defaultness: &'tcx Defaultness) { + debug!("visit_associated_item_kind: st={:?}", self.st); + SawDefaultness(*defaultness).hash(self.st); + visit::walk_defaultness(self, defaultness); + } + fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate) { debug!("visit_where_predicate: st={:?}", self.st); SawWherePredicate.hash(self.st); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ba85544326f..6dbcfc8523d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -834,7 +834,6 @@ impl<'a, 'tcx> CrateMetadata { kind: ty::AssociatedKind::Const, vis: item.visibility, defaultness: container.defaultness(), - has_value: container.has_value(), def_id: self.local_def_id(id), container: container.with_def_id(parent), method_has_self_argument: false @@ -848,7 +847,6 @@ impl<'a, 'tcx> CrateMetadata { kind: ty::AssociatedKind::Method, vis: item.visibility, defaultness: data.container.defaultness(), - has_value: data.container.has_value(), def_id: self.local_def_id(id), container: data.container.with_def_id(parent), method_has_self_argument: data.has_self @@ -861,7 +859,6 @@ impl<'a, 'tcx> CrateMetadata { kind: ty::AssociatedKind::Type, vis: item.visibility, defaultness: container.defaultness(), - has_value: container.has_value(), def_id: self.local_def_id(id), container: container.with_def_id(parent), method_has_self_argument: false diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 2d96eeb8f20..d1508d7e9b3 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -460,10 +460,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let ast_item = tcx.map.expect_trait_item(node_id); let trait_item = tcx.associated_item(def_id); - let container = if trait_item.has_value { - AssociatedContainer::TraitWithDefault - } else { - AssociatedContainer::TraitRequired + let container = match trait_item.defaultness { + hir::Defaultness::Default { has_value: true } => + AssociatedContainer::TraitWithDefault, + hir::Defaultness::Default { has_value: false } => + AssociatedContainer::TraitRequired, + hir::Defaultness::Final => + span_bug!(ast_item.span, "traits cannot have final items"), }; let kind = match trait_item.kind { @@ -501,7 +504,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Some(self.encode_item_type(def_id)) } ty::AssociatedKind::Type => { - if trait_item.has_value { + if trait_item.defaultness.has_value() { Some(self.encode_item_type(def_id)) } else { None @@ -530,8 +533,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let impl_def_id = impl_item.container.id(); let container = match impl_item.defaultness { - hir::Defaultness::Default => AssociatedContainer::ImplDefault, + hir::Defaultness::Default { has_value: true } => AssociatedContainer::ImplDefault, hir::Defaultness::Final => AssociatedContainer::ImplFinal, + hir::Defaultness::Default { has_value: false } => + span_bug!(ast_item.span, "impl items always have values (currently)"), }; let kind = match impl_item.kind { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d7a5f7ad715..7553b2e05a7 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -310,21 +310,16 @@ impl AssociatedContainer { } } - pub fn has_value(&self) -> bool { - match *self { - AssociatedContainer::TraitRequired => false, - - AssociatedContainer::TraitWithDefault | - AssociatedContainer::ImplDefault | - AssociatedContainer::ImplFinal => true, - } - } - pub fn defaultness(&self) -> hir::Defaultness { match *self { - AssociatedContainer::TraitRequired | + AssociatedContainer::TraitRequired => hir::Defaultness::Default { + has_value: false, + }, + AssociatedContainer::TraitWithDefault | - AssociatedContainer::ImplDefault => hir::Defaultness::Default, + AssociatedContainer::ImplDefault => hir::Defaultness::Default { + has_value: true, + }, AssociatedContainer::ImplFinal => hir::Defaultness::Final, } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4fb11509a1c..778f0184141 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -536,7 +536,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let def_id = if decl_id.is_local() { let ti = self.tcx.associated_item(decl_id); self.tcx.associated_items(ti.container.id()) - .find(|item| item.name == ti.name && item.has_value) + .find(|item| item.name == ti.name && item.defaultness.has_value()) .map(|item| item.def_id) } else { None diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2197ecc10a1..d2939316219 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1110,7 +1110,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } hir::ImplItemKind::Type(_) => { if ty_trait_item.kind == ty::AssociatedKind::Type { - if ty_trait_item.has_value { + if ty_trait_item.defaultness.has_value() { overridden_associated_type = Some(impl_item); } } else { @@ -1144,7 +1144,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .unwrap_or(false); if !is_implemented { - if !trait_item.has_value { + if !trait_item.defaultness.has_value() { missing_items.push(trait_item); } else if associated_type_overridden { invalidated_items.push(trait_item.name); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 066b3d4be08..2c55e8fbfd2 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -204,7 +204,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { free_id_outlive, self_ty); } ty::AssociatedKind::Type => { - if item.has_value { + if item.defaultness.has_value() { let ty = fcx.tcx.item_type(item.def_id); let ty = fcx.instantiate_type_scheme(span, free_substs, &ty); fcx.register_wf_obligation(ty, span, code.clone()); diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 1572d04f68c..9f5b73d9b30 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -118,7 +118,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .map(|item_ref| ccx.tcx.map.local_def_id(item_ref.id.node_id)) .filter(|&def_id| { let item = ccx.tcx.associated_item(def_id); - item.kind == ty::AssociatedKind::Type && item.has_value + item.kind == ty::AssociatedKind::Type && item.defaultness.has_value() }) .flat_map(|def_id| { ctp::parameters_for(&ccx.tcx.item_type(def_id), true) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e8367bca2ef..185f897c1ba 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -364,7 +364,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, let trait_items = tcx.associated_items(did).filter_map(|item| { match item.kind { ty::AssociatedKind::Const => { - let default = if item.has_value { + let default = if item.defaultness.has_value() { Some(pprust::expr_to_string( lookup_const_by_id(tcx, item.def_id, None).unwrap().0)) } else { @@ -407,7 +407,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, abi: abi }) } - _ => panic!("not a tymethod"), + ref r => panic!("not a tymethod: {:?}", r), }; Some(cleaned) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4d70c64634f..a141d0e4788 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1373,9 +1373,10 @@ impl<'tcx> Clean for ty::AssociatedItem { } } } + let provided = match self.container { ty::ImplContainer(_) => false, - ty::TraitContainer(_) => self.has_value + ty::TraitContainer(_) => self.defaultness.has_value() }; if provided { MethodItem(Method { @@ -1440,7 +1441,7 @@ impl<'tcx> Clean for ty::AssociatedItem { None => bounds.push(TyParamBound::maybe_sized(cx)), } - let ty = if self.has_value { + let ty = if self.defaultness.has_value() { Some(cx.tcx().item_type(self.def_id)) } else { None diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs new file mode 100644 index 00000000000..f7a390e8745 --- /dev/null +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -0,0 +1,128 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for let expressions. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![crate_type="rlib"] + +struct Foo; + +// Change Method Name ----------------------------------------------------------- +#[cfg(cfail1)] +impl Foo { + pub fn method_name() { } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + pub fn method_name2() { } +} + +// Change Method Body ----------------------------------------------------------- +// +// This should affect the method itself, but not the impl. +#[cfg(cfail1)] +impl Foo { + pub fn method_body() { } +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_clean(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + pub fn method_body() { + println!("Hello, world!"); + } +} + +// Change Method Privacy ----------------------------------------------------------- +#[cfg(cfail1)] +impl Foo { + pub fn method_privacy() { } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_privacy() { } +} + +// Change Method Selfness ----------------------------------------------------------- +#[cfg(cfail1)] +impl Foo { + pub fn method_selfness() { } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + pub fn method_selfness(&self) { } +} + +// Change Method Selfmutness ----------------------------------------------------------- +#[cfg(cfail1)] +impl Foo { + pub fn method_selfmutness(&self) { } +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_clean(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + pub fn method_selfmutness(&mut self) { } +} + -- cgit 1.4.1-3-g733a5 From 4e844ad1e5d0f62cfac00ad0c0f50474d99331f7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 14 Nov 2016 21:02:29 -0500 Subject: fix change_private_impl_method_cc test --- src/test/incremental/change_private_impl_method_cc/struct_point.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/test/incremental') diff --git a/src/test/incremental/change_private_impl_method_cc/struct_point.rs b/src/test/incremental/change_private_impl_method_cc/struct_point.rs index a8779e3f92d..bb7f7025c59 100644 --- a/src/test/incremental/change_private_impl_method_cc/struct_point.rs +++ b/src/test/incremental/change_private_impl_method_cc/struct_point.rs @@ -21,9 +21,7 @@ #![rustc_partition_reused(module="struct_point-fn_read_field", cfg="rpass2")] #![rustc_partition_reused(module="struct_point-fn_write_field", cfg="rpass2")] - -// FIXME(#37333) the struct fields get entangled with inherent methods -#![rustc_partition_translated(module="struct_point-fn_make_struct", cfg="rpass2")] +#![rustc_partition_reused(module="struct_point-fn_make_struct", cfg="rpass2")] // FIXME(#37720) these two should be reused, but data gets entangled across crates #![rustc_partition_translated(module="struct_point-fn_calls_methods_in_same_impl", cfg="rpass2")] -- cgit 1.4.1-3-g733a5 From c938007f90711d6acc8b55e15a5e3cf7cc147e91 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 17 Nov 2016 15:12:43 -0500 Subject: add test for hashing trait impls --- src/test/incremental/hashes/trait_impls.rs | 404 +++++++++++++++++++++++++++++ 1 file changed, 404 insertions(+) create mode 100644 src/test/incremental/hashes/trait_impls.rs (limited to 'src/test/incremental') diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs new file mode 100644 index 00000000000..500aaf52324 --- /dev/null +++ b/src/test/incremental/hashes/trait_impls.rs @@ -0,0 +1,404 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// This test case tests the incremental compilation hash (ICH) implementation +// for let expressions. + +// The general pattern followed here is: Change one thing between rev1 and rev2 +// and make sure that the hash has changed, then change nothing between rev2 and +// rev3 and make sure that the hash has not changed. + +// must-compile-successfully +// revisions: cfail1 cfail2 cfail3 +// compile-flags: -Z query-dep-graph + + +#![allow(warnings)] +#![feature(rustc_attrs)] +#![feature(specialization)] +#![crate_type="rlib"] + +struct Foo; + +// Change Method Name ----------------------------------------------------------- + +#[cfg(cfail1)] +pub trait ChangeMethodNameTrait { + fn method_name(); +} + +#[cfg(cfail1)] +impl ChangeMethodNameTrait for Foo { + fn method_name() { } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +pub trait ChangeMethodNameTrait { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name2(); +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeMethodNameTrait for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name2() { } +} + +// Change Method Body ----------------------------------------------------------- +// +// This should affect the method itself, but not the trait. + +pub trait ChangeMethodBodyTrait { + fn method_name(); +} + +#[cfg(cfail1)] +impl ChangeMethodBodyTrait for Foo { + fn method_name() { } +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_clean(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeMethodBodyTrait for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name() { + () + } +} + +// Change Method Selfness ----------------------------------------------------------- + +#[cfg(cfail1)] +pub trait ChangeMethodSelfnessTrait { + fn method_name(); +} + +#[cfg(cfail1)] +impl ChangeMethodSelfnessTrait for Foo { + fn method_name() { } +} + +#[cfg(not(cfail1))] +pub trait ChangeMethodSelfnessTrait { + fn method_name(&self); +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeMethodSelfnessTrait for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name(&self) { + () + } +} + +// Change Method Selfness ----------------------------------------------------------- + +#[cfg(cfail1)] +pub trait RemoveMethodSelfnessTrait { + fn method_name(&self); +} + +#[cfg(cfail1)] +impl RemoveMethodSelfnessTrait for Foo { + fn method_name(&self) { } +} + +#[cfg(not(cfail1))] +pub trait RemoveMethodSelfnessTrait { + fn method_name(); +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl RemoveMethodSelfnessTrait for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name() { + () + } +} + +// Change Method Selfmutness ----------------------------------------------------------- + +#[cfg(cfail1)] +pub trait ChangeMethodSelfmutnessTrait { + fn method_name(&self); +} + +#[cfg(cfail1)] +impl ChangeMethodSelfmutnessTrait for Foo { + fn method_name(&self) { } +} + +#[cfg(not(cfail1))] +pub trait ChangeMethodSelfmutnessTrait { + fn method_name(&mut self); +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeMethodSelfmutnessTrait for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name(&mut self) { + () + } +} + +// Change item kind ----------------------------------------------------------- + +#[cfg(cfail1)] +pub trait ChangeItemKindTrait { + fn name(); +} + +#[cfg(cfail1)] +impl ChangeItemKindTrait for Foo { + fn name() { } +} + +#[cfg(not(cfail1))] +pub trait ChangeItemKindTrait { + type name; +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeItemKindTrait for Foo { + type name = (); +} + +// Remove item ----------------------------------------------------------- + +#[cfg(cfail1)] +pub trait RemoveItemTrait { + type TypeName; + fn method_name(); +} + +#[cfg(cfail1)] +impl RemoveItemTrait for Foo { + type TypeName = (); + fn method_name() { } +} + +#[cfg(not(cfail1))] +pub trait RemoveItemTrait { + type TypeName; +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl RemoveItemTrait for Foo { + type TypeName = (); +} + +// Add item ----------------------------------------------------------- + +#[cfg(cfail1)] +pub trait AddItemTrait { + type TypeName; +} + +#[cfg(cfail1)] +impl AddItemTrait for Foo { + type TypeName = (); +} + +#[cfg(not(cfail1))] +pub trait AddItemTrait { + type TypeName; + fn method_name(); +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl AddItemTrait for Foo { + type TypeName = (); + fn method_name() { } +} + +// Change has-value ----------------------------------------------------------- + +#[cfg(cfail1)] +pub trait ChangeHasValueTrait { + fn method_name(); +} + +#[cfg(cfail1)] +impl ChangeHasValueTrait for Foo { + fn method_name() { } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +pub trait ChangeHasValueTrait { + fn method_name() { } +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeHasValueTrait for Foo { + fn method_name() { } +} + +// Add default + +pub trait AddDefaultTrait { + fn method_name(); +} + +#[cfg(cfail1)] +impl AddDefaultTrait for Foo { + fn method_name() { } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl AddDefaultTrait for Foo { + default fn method_name() { } +} + +// Remove default + +pub trait RemoveDefaultTrait { + fn method_name(); +} + +#[cfg(cfail1)] +impl RemoveDefaultTrait for Foo { + default fn method_name() { } +} + +#[cfg(not(cfail1))] +#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl RemoveDefaultTrait for Foo { + fn method_name() { } +} + +// Add arguments + +#[cfg(cfail1)] +pub trait AddArgumentTrait { + fn method_name(&self); +} + +#[cfg(cfail1)] +impl AddArgumentTrait for Foo { + fn method_name(&self) { } +} + +#[cfg(not(cfail1))] +pub trait AddArgumentTrait { + fn method_name(&self, x: u32); +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl AddArgumentTrait for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name(&self, _x: u32) { } +} + +// Change argument type + +#[cfg(cfail1)] +pub trait ChangeArgumentTypeTrait { + fn method_name(&self, x: u32); +} + +#[cfg(cfail1)] +impl ChangeArgumentTypeTrait for Foo { + fn method_name(&self, _x: u32) { } +} + +#[cfg(not(cfail1))] +pub trait ChangeArgumentTypeTrait { + fn method_name(&self, x: char); +} + +#[cfg(not(cfail1))] +#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_metadata_dirty(cfg="cfail2")] +#[rustc_metadata_clean(cfg="cfail3")] +impl ChangeArgumentTypeTrait for Foo { + #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + fn method_name(&self, _x: char) { } +} + -- cgit 1.4.1-3-g733a5