diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 3bbac8d6a6425..b43c516f317f2 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -181,7 +181,7 @@ impl<'a, 'tcx, A, B> HashStable> for ty::Outlives } impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty }); -impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { trait_ref, item_name }); +impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { trait_ref, item_def_id }); impl<'a, 'tcx> HashStable> for ty::Predicate<'tcx> { diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs index 2e3c2443544f6..acc1a397b4560 100644 --- a/src/librustc/infer/region_inference/mod.rs +++ b/src/librustc/infer/region_inference/mod.rs @@ -1542,7 +1542,8 @@ impl<'a, 'gcx, 'tcx> GenericKind<'tcx> { pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { match *self { GenericKind::Param(ref p) => p.to_ty(tcx), - GenericKind::Projection(ref p) => tcx.mk_projection(p.trait_ref.clone(), p.item_name), + GenericKind::Projection(ref p) => tcx.mk_projection( + p.trait_ref.clone(), p.item_name(tcx)), } } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index d7911870f391a..f5672ffbdc534 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -355,7 +355,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>( let tcx = selcx.infcx().tcx; let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i| - i.name == projection_ty.item_name && i.kind == ty::AssociatedKind::Type + i.name == projection_ty.item_name(tcx) && i.kind == ty::AssociatedKind::Type ).map(|i| i.def_id).unwrap(); let ty_var = selcx.infcx().next_ty_var( TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id))); @@ -436,7 +436,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( // // ``` // let ty = selcx.tcx().mk_projection(projection_ty.trait_ref, - // projection_ty.item_name); + // projection_ty.item_name(tcx); // return Some(NormalizedTy { value: v, obligations: vec![] }); // ``` @@ -574,7 +574,7 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc predicate: trait_ref.to_predicate() }; let tcx = selcx.infcx().tcx; let def_id = tcx.associated_items(projection_ty.trait_ref.def_id).find(|i| - i.name == projection_ty.item_name && i.kind == ty::AssociatedKind::Type + i.name == projection_ty.item_name(tcx) && i.kind == ty::AssociatedKind::Type ).map(|i| i.def_id).unwrap(); let new_value = selcx.infcx().next_ty_var( TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id))); @@ -729,7 +729,7 @@ fn project_type<'cx, 'gcx, 'tcx>( Ok(ProjectedTy::NoProgress( selcx.tcx().mk_projection( obligation.predicate.trait_ref.clone(), - obligation.predicate.item_name))) + obligation.predicate.item_name(selcx.tcx())))) } } } @@ -815,7 +815,8 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( predicate); match predicate { ty::Predicate::Projection(ref data) => { - let same_name = data.item_name() == obligation.predicate.item_name; + let tcx = selcx.tcx(); + let same_name = data.item_name(tcx) == obligation.predicate.item_name(tcx); let is_match = same_name && infcx.probe(|_| { let data_poly_trait_ref = @@ -902,7 +903,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( // type. let node_item = assoc_ty_def(selcx, impl_data.impl_def_id, - obligation.predicate.item_name); + obligation.predicate.item_name(selcx.tcx())); let is_default = if node_item.node.is_from_trait() { // If true, the impl inherited a `type Foo = Bar` @@ -1075,9 +1076,10 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( // select only those projections that are actually projecting an // item with the correct name + let tcx = selcx.tcx(); let env_predicates = env_predicates.filter_map(|p| match p { ty::Predicate::Projection(data) => - if data.item_name() == obligation.predicate.item_name { + if data.item_name(tcx) == obligation.predicate.item_name(tcx) { Some(data) } else { None @@ -1180,10 +1182,11 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>( flag); let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here - projection_ty: ty::ProjectionTy { - trait_ref: trait_ref, - item_name: Symbol::intern(FN_OUTPUT_NAME), - }, + projection_ty: ty::ProjectionTy::from_ref_and_name( + tcx, + trait_ref, + Symbol::intern(FN_OUTPUT_NAME), + ), ty: ret_type }); @@ -1228,7 +1231,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( let VtableImplData { substs, nested, impl_def_id } = impl_vtable; let tcx = selcx.tcx(); - let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_name); + let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_name(tcx)); let ty = if !assoc_ty.item.defaultness.has_value() { // This means that the impl is missing a definition for the diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e3d7aeb22e1fa..8c801c6fa2b97 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1323,7 +1323,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { item_name: Name) -> Ty<'tcx> { // take a copy of substs so that we own the vectors inside - let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; + let inner = ProjectionTy::from_ref_and_name(self, trait_ref, item_name); self.mk_ty(TyProjection(inner)) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index aeffd71a09649..22fcc61953b2b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1051,8 +1051,8 @@ pub struct ProjectionPredicate<'tcx> { pub type PolyProjectionPredicate<'tcx> = Binder>; impl<'tcx> PolyProjectionPredicate<'tcx> { - pub fn item_name(&self) -> Name { - self.0.projection_ty.item_name // safe to skip the binder to access a name + pub fn item_name(&self, tcx: TyCtxt) -> Name { + self.0.projection_ty.item_name(tcx) // safe to skip the binder to access a name } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index bbe682e74bc04..d4f06a902eeaa 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -225,12 +225,13 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> { -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { - if a.item_name != b.item_name { + let tcx = relation.tcx(); + if a.item_name(tcx) != b.item_name(tcx) { Err(TypeError::ProjectionNameMismatched( - expected_found(relation, &a.item_name, &b.item_name))) + expected_found(relation, &a.item_name(tcx), &b.item_name(tcx)))) } else { let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; - Ok(ty::ProjectionTy { trait_ref: trait_ref, item_name: a.item_name }) + Ok(ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, a.item_name(tcx))) } } } @@ -457,7 +458,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) => { let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name)) + Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name(tcx))) } (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs)) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 53d516e581b2a..c3ca679153759 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -135,10 +135,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> { fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { tcx.lift(&self.trait_ref).map(|trait_ref| { - ty::ProjectionTy { - trait_ref: trait_ref, - item_name: self.item_name - } + ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, self.item_name(tcx)) }) } } @@ -771,7 +768,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::ProjectionTy { trait_ref: self.trait_ref.fold_with(folder), - item_name: self.item_name, + item_def_id: self.item_def_id, } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 348d164af4190..bbb399434d6ae 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -556,9 +556,34 @@ pub struct ProjectionTy<'tcx> { /// The trait reference `T as Trait<..>`. pub trait_ref: ty::TraitRef<'tcx>, - /// The name `N` of the associated type. - pub item_name: Name, + /// The DefId of the TraitItem for the associated type N. + /// + /// Note that this is not the DefId of the TraitRef containing this + /// associated type, which is in tcx.associated_item(item_def_id).container. + pub item_def_id: DefId, } + +impl<'a, 'tcx> ProjectionTy<'tcx> { + /// Construct a ProjectionTy by searching the trait from trait_ref for the + /// associated item named item_name. + pub fn from_ref_and_name( + tcx: TyCtxt, trait_ref: ty::TraitRef<'tcx>, item_name: Name + ) -> ProjectionTy<'tcx> { + let item_def_id = tcx.associated_items(trait_ref.def_id).find( + |item| item.name == item_name).unwrap().def_id; + + ProjectionTy { + trait_ref: trait_ref, + item_def_id: item_def_id, + } + } + + pub fn item_name(self, tcx: TyCtxt) -> Name { + tcx.associated_item(self.item_def_id).name + } +} + + /// Signature of a function type, which I have arbitrarily /// decided to use to refer to the input/output types. /// @@ -871,10 +896,10 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { assert!(!self_ty.has_escaping_regions()); ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), - item_name: self.item_name, - }, + projection_ty: ty::ProjectionTy::from_ref_and_name( + tcx, + self.trait_ref.with_self_ty(tcx, self_ty), + self.item_name), ty: self.ty, } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 8edae027dbfbc..ce0f1ed5bb86c 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -691,8 +691,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W> self.hash(p.name.as_str()); } TyProjection(ref data) => { - self.def_id(data.trait_ref.def_id); - self.hash(data.item_name.as_str()); + self.def_id(data.item_def_id); } TyNever | TyBool | diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 340e4f2cfccbc..5a1b7393db312 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -216,9 +216,11 @@ pub fn parameterized(f: &mut fmt::Formatter, for projection in projections { start_or_continue(f, "<", ", ")?; - write!(f, "{}={}", - projection.projection_ty.item_name, - projection.ty)?; + ty::tls::with(|tcx| + write!(f, "{}={}", + projection.projection_ty.item_name(tcx), + projection.ty) + )?; } start_or_continue(f, "", ">")?; @@ -929,9 +931,10 @@ impl<'tcx> fmt::Display for ty::ProjectionPredicate<'tcx> { impl<'tcx> fmt::Display for ty::ProjectionTy<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let item_name = ty::tls::with(|tcx| self.item_name(tcx)); write!(f, "{:?}::{}", self.trait_ref, - self.item_name) + item_name) } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index d83740936d5d4..fa74e4d6ffccc 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -618,7 +618,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if let ty::TyProjection(proj) = ty.sty { for item in self.tcx.associated_items(proj.trait_ref.def_id) { if item.kind == ty::AssociatedKind::Type { - if item.name == proj.item_name { + if item.name == proj.item_name(self.tcx) { return Def::AssociatedTy(item.def_id); } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c9eb9807c41a5..212461a6d70e2 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -553,10 +553,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { return Ok(trait_ref.map_bound(|trait_ref| { ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - trait_ref: trait_ref, - item_name: binding.item_name, - }, + projection_ty: ty::ProjectionTy::from_ref_and_name( + tcx, + trait_ref, + binding.item_name, + ), ty: binding.ty, } })); @@ -575,10 +576,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Ok(candidate.map_bound(|trait_ref| { ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy { - trait_ref: trait_ref, - item_name: binding.item_name, - }, + projection_ty: ty::ProjectionTy::from_ref_and_name( + tcx, + trait_ref, + binding.item_name, + ), ty: binding.ty, } })) @@ -652,7 +654,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let p = b.projection_ty; ty::ExistentialProjection { trait_ref: self.trait_ref_to_existential(p.trait_ref), - item_name: p.item_name, + item_name: p.item_name(tcx), ty: b.ty } }) @@ -679,7 +681,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { for projection_bound in &projection_bounds { let pair = (projection_bound.0.projection_ty.trait_ref.def_id, - projection_bound.0.projection_ty.item_name); + projection_bound.0.projection_ty.item_name(tcx)); associated_types.remove(&pair); } diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index f03451c04ed00..7d3a63263edbf 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -124,10 +124,11 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { } let normalized = traits::normalize_projection_type(&mut selcx, - ty::ProjectionTy { - trait_ref: trait_ref, - item_name: Symbol::intern("Target"), - }, + ty::ProjectionTy::from_ref_and_name( + tcx, + trait_ref, + Symbol::intern("Target"), + ), cause, 0); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b29bf01ba1996..fd26ff65661ca 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1651,8 +1651,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { declared_bounds, projection_ty); // see the extensive comment in projection_must_outlive - - let ty = self.tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name); + let item_name = projection_ty.item_name(self.tcx); + let ty = self.tcx.mk_projection(projection_ty.trait_ref, item_name); let recursive_bound = self.recursive_type_bound(span, ty); VerifyBound::AnyRegion(declared_bounds).or(recursive_bound) @@ -1718,9 +1718,9 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { { debug!("projection_bounds(projection_ty={:?})", projection_ty); - + let item_name = projection_ty.item_name(self.tcx); let ty = self.tcx.mk_projection(projection_ty.trait_ref.clone(), - projection_ty.item_name); + item_name); // Say we have a projection `>::SomeType`. We are interested // in looking for a trait definition like: @@ -1758,7 +1758,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let (outlives, _) = self.replace_late_bound_regions_with_fresh_var( span, - infer::AssocTypeProjection(projection_ty.item_name), + infer::AssocTypeProjection(projection_ty.item_name(self.tcx)), &outlives); debug!("projection_bounds: outlives={:?} (3)", diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 593477b066583..9464ac83870d9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -955,7 +955,7 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { } }; Type::QPath { - name: self.item_name.clean(cx), + name: self.item_name(cx.tcx).clean(cx), self_type: box self.trait_ref.self_ty().clean(cx), trait_: box trait_ }