Downgrade ProjectionTy's TraitRef to its substs

Addresses the second part of #42171 by removing the `TraitRef` from
`ProjectionTy`, and directly storing its `Substs`.

Closes #42171.
This commit is contained in:
Tobias Schottdorf 2017-07-11 10:33:09 -04:00
parent dddf24d96f
commit 687ee7fee4
33 changed files with 341 additions and 294 deletions

View file

@ -187,7 +187,7 @@ for ty::OutlivesPredicate<A, B>
}
impl_stable_hash_for!(struct ty::ProjectionPredicate<'tcx> { projection_ty, ty });
impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { trait_ref, item_def_id });
impl_stable_hash_for!(struct ty::ProjectionTy<'tcx> { substs, item_def_id });
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::Predicate<'tcx> {
@ -599,8 +599,8 @@ impl_stable_hash_for!(struct ty::ExistentialTraitRef<'tcx> {
});
impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> {
trait_ref,
item_name,
item_def_id,
substs,
ty
});

View file

@ -274,7 +274,7 @@ pub enum LateBoundRegionConversionTime {
HigherRankedType,
/// when projecting an associated type
AssocTypeProjection(ast::Name),
AssocTypeProjection(ast::Name), // FIXME(tschottdorf): should contain DefId, not Name
}
/// Reasons to create a region inference variable
@ -1277,14 +1277,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
match_b: ty::TraitRef<'tcx>)
-> InferResult<'tcx, HrMatchResult<Ty<'tcx>>>
{
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref(self.tcx), p.ty));
let span = cause.span;
let match_trait_ref = match_a.skip_binder().projection_ty.trait_ref;
let trace = TypeTrace {
cause,
values: TraitRefs(ExpectedFound::new(true, match_trait_ref, match_b))
values: TraitRefs(ExpectedFound::new(true, match_pair.skip_binder().0, match_b))
};
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
let mut combine = self.combine_fields(trace, param_env);
let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
Ok(InferOk { value: result, obligations: combine.obligations })

View file

@ -1550,8 +1550,7 @@ 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(tcx)),
GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
}
}
}

View file

@ -470,8 +470,9 @@ fn process_predicate<'a, 'gcx, 'tcx>(
let project_obligation = obligation.with(data.clone());
match project::poly_project_and_unify_type(selcx, &project_obligation) {
Ok(None) => {
let tcx = selcx.tcx();
pending_obligation.stalled_on =
trait_ref_type_vars(selcx, data.to_poly_trait_ref());
trait_ref_type_vars(selcx, data.to_poly_trait_ref(tcx));
Ok(None)
}
Ok(v) => Ok(v),

View file

@ -354,7 +354,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// direct equality here because all of these types
// are part of the formal parameter listing, and
// hence there should be no inference variables.
let projection_trait_ref = ty::Binder(data.trait_ref.clone());
let projection_trait_ref = ty::Binder(data.trait_ref(self));
let is_supertrait_of_current_trait =
supertraits.as_ref().unwrap().contains(&projection_trait_ref);

View file

@ -365,9 +365,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
// information is available.
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(tcx) && i.kind == ty::AssociatedKind::Type
).map(|i| i.def_id).unwrap();
let def_id = projection_ty.item_def_id;
let ty_var = selcx.infcx().next_ty_var(
TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
let projection = ty::Binder(ty::ProjectionPredicate {
@ -447,8 +445,8 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
// normalization. In that case, I think we will want this code:
//
// ```
// let ty = selcx.tcx().mk_projection(projection_ty.trait_ref,
// projection_ty.item_name(tcx);
// let ty = selcx.tcx().mk_projection(projection_ty.item_def_id,
// projection_ty.substs;
// return Some(NormalizedTy { value: v, obligations: vec![] });
// ```
@ -585,15 +583,13 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc
depth: usize)
-> NormalizedTy<'tcx>
{
let trait_ref = projection_ty.trait_ref.to_poly_trait_ref();
let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref();
let trait_obligation = Obligation { cause,
recursion_depth: depth,
param_env,
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(tcx) && i.kind == ty::AssociatedKind::Type
).map(|i| i.def_id).unwrap();
let def_id = projection_ty.item_def_id;
let new_value = selcx.infcx().next_ty_var(
TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
Normalized {
@ -654,7 +650,7 @@ fn project_type<'cx, 'gcx, 'tcx>(
selcx.infcx().report_overflow_error(&obligation, true);
}
let obligation_trait_ref = &obligation.predicate.trait_ref;
let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
debug!("project: obligation_trait_ref={:?}", obligation_trait_ref);
@ -743,12 +739,10 @@ fn project_type<'cx, 'gcx, 'tcx>(
&obligation_trait_ref,
candidate)))
}
None => {
Ok(ProjectedTy::NoProgress(
selcx.tcx().mk_projection(
obligation.predicate.trait_ref.clone(),
obligation.predicate.item_name(selcx.tcx()))))
}
None => Ok(ProjectedTy::NoProgress(
selcx.tcx().mk_projection(
obligation.predicate.item_def_id,
obligation.predicate.substs)))
}
}
@ -788,10 +782,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
{
debug!("assemble_candidates_from_trait_def(..)");
let tcx = selcx.tcx();
// Check whether the self-type is itself a projection.
let (def_id, substs) = match obligation_trait_ref.self_ty().sty {
ty::TyProjection(ref data) => {
(data.trait_ref.def_id, data.trait_ref.substs)
(data.trait_ref(tcx).def_id, data.substs)
}
ty::TyAnon(def_id, substs) => (def_id, substs),
ty::TyInfer(ty::TyVar(_)) => {
@ -804,9 +799,9 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
};
// If so, extract what we know from the trait and try to come up with a good answer.
let trait_predicates = selcx.tcx().predicates_of(def_id);
let bounds = trait_predicates.instantiate(selcx.tcx(), substs);
let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates);
let trait_predicates = tcx.predicates_of(def_id);
let bounds = trait_predicates.instantiate(tcx, substs);
let bounds = elaborate_predicates(tcx, bounds.predicates);
assemble_candidates_from_predicates(selcx,
obligation,
obligation_trait_ref,
@ -832,12 +827,12 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
predicate);
match predicate {
ty::Predicate::Projection(ref data) => {
let tcx = selcx.tcx();
let same_name = data.item_name(tcx) == obligation.predicate.item_name(tcx);
let same_def_id =
data.0.projection_ty.item_def_id == obligation.predicate.item_def_id;
let is_match = same_name && infcx.probe(|_| {
let is_match = same_def_id && infcx.probe(|_| {
let data_poly_trait_ref =
data.to_poly_trait_ref();
data.to_poly_trait_ref(infcx.tcx);
let obligation_poly_trait_ref =
obligation_trait_ref.to_poly_trait_ref();
infcx.at(&obligation.cause, obligation.param_env)
@ -850,8 +845,8 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>(
});
debug!("assemble_candidates_from_predicates: candidate={:?} \
is_match={} same_name={}",
data, is_match, same_name);
is_match={} same_def_id={}",
data, is_match, same_def_id);
if is_match {
candidate_set.vec.push(ctor(data.clone()));
@ -916,9 +911,10 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
// In either case, we handle this by not adding a
// candidate for an impl if it contains a `default`
// type.
let item_name = selcx.tcx().associated_item(obligation.predicate.item_def_id).name;
let node_item = assoc_ty_def(selcx,
impl_data.impl_def_id,
obligation.predicate.item_name(selcx.tcx()));
item_name);
let is_default = if node_item.node.is_from_trait() {
// If true, the impl inherited a `type Foo = Bar`
@ -1091,10 +1087,9 @@ 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(tcx) == obligation.predicate.item_name(tcx) {
if data.0.projection_ty.item_def_id == obligation.predicate.item_def_id {
Some(data)
} else {
None
@ -1104,7 +1099,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
// select those with a relevant trait-ref
let mut env_predicates = env_predicates.filter(|data| {
let data_poly_trait_ref = data.to_poly_trait_ref();
let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
selcx.infcx().probe(|_| {
selcx.infcx().at(&obligation.cause, obligation.param_env)
@ -1202,7 +1197,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
// Note: we unwrap the binder here but re-create it below (1)
let ty::Binder((trait_ref, ret_type)) =
tcx.closure_trait_ref_and_return_type(fn_once_def_id,
obligation.predicate.trait_ref.self_ty(),
obligation.predicate.self_ty(),
fn_sig,
flag);
@ -1227,7 +1222,7 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>(
let infcx = selcx.infcx();
let cause = obligation.cause.clone();
let param_env = obligation.param_env;
let trait_ref = obligation.predicate.trait_ref;
let trait_ref = obligation.predicate.trait_ref(infcx.tcx);
match infcx.match_poly_projection_predicate(cause, param_env, poly_projection, trait_ref) {
Ok(InferOk { value: ty_match, obligations }) => {
Progress {
@ -1258,7 +1253,8 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
let tcx = selcx.tcx();
let param_env = obligation.param_env;
let assoc_ty = assoc_ty_def(selcx, impl_def_id, obligation.predicate.item_name(tcx));
let assoc_ty = assoc_ty_def(selcx, impl_def_id,
tcx.associated_item(obligation.predicate.item_def_id).name);
let ty = if !assoc_ty.item.defaultness.has_value() {
// This means that the impl is missing a definition for the
@ -1267,7 +1263,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
// just return TyError.
debug!("confirm_impl_candidate: no associated type {:?} for {:?}",
assoc_ty.item.name,
obligation.predicate.trait_ref);
obligation.predicate);
tcx.types.err
} else {
tcx.type_of(assoc_ty.item.def_id)

View file

@ -1335,7 +1335,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
skol_map);
let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty {
ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs),
ty::TyProjection(ref data) =>
(data.trait_ref(self.tcx()).def_id, data.substs),
ty::TyAnon(def_id, substs) => (def_id, substs),
_ => {
span_bug!(

View file

@ -203,9 +203,9 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
let def_ids: Vec<DefId> =
key.walk()
.filter_map(|t| match t.sty {
ty::TyAdt(adt_def, _) => Some(adt_def.did),
ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
_ => None,
ty::TyAdt(adt_def, _) => Some(adt_def.did),
ty::TyProjection(ref proj) => Some(proj.item_def_id),
_ => None,
})
.collect();

View file

@ -28,7 +28,7 @@ use mir::transform::Passes;
use ty::subst::{Kind, Substs};
use ty::ReprOptions;
use traits;
use ty::{self, TraitRef, Ty, TypeAndMut};
use ty::{self, Ty, TypeAndMut};
use ty::{TyS, TypeVariants, Slice};
use ty::{AdtKind, AdtDef, ClosureSubsts, Region};
use hir::FreevarMap;
@ -1387,12 +1387,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
pub fn mk_projection(self,
trait_ref: TraitRef<'tcx>,
item_name: Name)
item_def_id: DefId,
substs: &'tcx Substs<'tcx>)
-> Ty<'tcx> {
// take a copy of substs so that we own the vectors inside
let inner = ProjectionTy::from_ref_and_name(self, trait_ref, item_name);
self.mk_ty(TyProjection(inner))
self.mk_ty(TyProjection(ProjectionTy {
item_def_id: item_def_id,
substs: substs,
}))
}
pub fn mk_closure(self,

View file

@ -14,7 +14,7 @@ use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt};
use std::fmt;
use syntax::abi;
use syntax::ast::{self, Name};
use syntax::ast;
use errors::DiagnosticBuilder;
use syntax_pos::Span;
@ -47,7 +47,7 @@ pub enum TypeError<'tcx> {
Traits(ExpectedFound<DefId>),
VariadicMismatch(ExpectedFound<bool>),
CyclicTy,
ProjectionNameMismatched(ExpectedFound<Name>),
ProjectionMismatched(ExpectedFound<DefId>),
ProjectionBoundsLength(ExpectedFound<usize>),
TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>),
ExistentialMismatch(ExpectedFound<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>),
@ -154,11 +154,11 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
if values.expected { "variadic" } else { "non-variadic" },
if values.found { "variadic" } else { "non-variadic" })
}
ProjectionNameMismatched(ref values) => {
ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
write!(f, "expected {}, found {}",
values.expected,
values.found)
}
tcx.item_path_str(values.expected),
tcx.item_path_str(values.found))
}),
ProjectionBoundsLength(ref values) => {
write!(f, "expected {} associated type bindings, found {}",
values.expected,

View file

@ -193,12 +193,12 @@ impl FlagComputation {
}
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) {
self.add_substs(projection.trait_ref.substs);
self.add_substs(projection.substs);
self.add_ty(projection.ty);
}
fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) {
self.add_substs(projection_ty.trait_ref.substs);
self.add_substs(projection_ty.substs);
}
fn add_substs(&mut self, substs: &Substs) {

View file

@ -150,10 +150,6 @@ pub trait TypeVisitor<'tcx> : Sized {
t.super_visit_with(self)
}
fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
trait_ref.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
r.super_visit_with(self)
}

View file

@ -1030,8 +1030,13 @@ pub struct ProjectionPredicate<'tcx> {
pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
impl<'tcx> PolyProjectionPredicate<'tcx> {
pub fn item_name(&self, tcx: TyCtxt) -> Name {
self.0.projection_ty.item_name(tcx) // safe to skip the binder to access a name
pub fn to_poly_trait_ref(&self, tcx: TyCtxt) -> PolyTraitRef<'tcx> {
// Note: unlike with TraitRef::to_poly_trait_ref(),
// self.0.trait_ref is permitted to have escaping regions.
// This is because here `self` has a `Binder` and so does our
// return value, so we are preserving the number of binding
// levels.
ty::Binder(self.0.projection_ty.trait_ref(tcx))
}
}
@ -1052,17 +1057,6 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
}
}
impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
// Note: unlike with TraitRef::to_poly_trait_ref(),
// self.0.trait_ref is permitted to have escaping regions.
// This is because here `self` has a `Binder` and so does our
// return value, so we are preserving the number of binding
// levels.
ty::Binder(self.0.projection_ty.trait_ref)
}
}
pub trait ToPredicate<'tcx> {
fn to_predicate(&self) -> Predicate<'tcx>;
}
@ -1132,8 +1126,7 @@ impl<'tcx> Predicate<'tcx> {
vec![]
}
ty::Predicate::Projection(ref data) => {
let trait_inputs = data.0.projection_ty.trait_ref.input_types();
trait_inputs.chain(Some(data.0.ty)).collect()
data.0.projection_ty.substs.types().chain(Some(data.0.ty)).collect()
}
ty::Predicate::WellFormed(data) => {
vec![data]

View file

@ -225,13 +225,15 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionTy<'tcx> {
-> RelateResult<'tcx, ty::ProjectionTy<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
let tcx = relation.tcx();
if a.item_name(tcx) != b.item_name(tcx) {
Err(TypeError::ProjectionNameMismatched(
expected_found(relation, &a.item_name(tcx), &b.item_name(tcx))))
if a.item_def_id != b.item_def_id {
Err(TypeError::ProjectionMismatched(
expected_found(relation, &a.item_def_id, &b.item_def_id)))
} else {
let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?;
Ok(ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, a.item_name(tcx)))
let substs = relation.relate(&a.substs, &b.substs)?;
Ok(ty::ProjectionTy {
item_def_id: a.item_def_id,
substs: &substs,
})
}
}
}
@ -243,15 +245,15 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
-> RelateResult<'tcx, ty::ExistentialProjection<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
if a.item_name != b.item_name {
Err(TypeError::ProjectionNameMismatched(
expected_found(relation, &a.item_name, &b.item_name)))
if a.item_def_id != b.item_def_id {
Err(TypeError::ProjectionMismatched(
expected_found(relation, &a.item_def_id, &b.item_def_id)))
} else {
let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?;
let ty = relation.relate(&a.ty, &b.ty)?;
let substs = relation.relate(&a.substs, &b.substs)?;
Ok(ty::ExistentialProjection {
trait_ref,
item_name: a.item_name,
item_def_id: a.item_def_id,
substs: substs,
ty,
})
}
@ -456,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(tcx)))
Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
}
(&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs))

View file

@ -134,8 +134,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> {
type Lifted = ty::ProjectionTy<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
-> Option<ty::ProjectionTy<'tcx>> {
tcx.lift(&self.trait_ref).map(|trait_ref| {
ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, self.item_name(tcx))
tcx.lift(&self.substs).map(|substs| {
ty::ProjectionTy {
item_def_id: self.item_def_id,
substs: substs,
}
})
}
}
@ -156,11 +159,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> {
impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> {
type Lifted = ty::ExistentialProjection<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
tcx.lift(&(self.trait_ref, self.ty)).map(|(trait_ref, ty)| {
tcx.lift(&self.substs).map(|substs| {
ty::ExistentialProjection {
trait_ref,
item_name: self.item_name,
ty,
substs,
ty: tcx.lift(&self.ty).expect("type must lift when substs do"),
item_def_id: self.item_def_id,
}
})
}
@ -356,7 +359,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
Traits(x) => Traits(x),
VariadicMismatch(x) => VariadicMismatch(x),
CyclicTy => CyclicTy,
ProjectionNameMismatched(x) => ProjectionNameMismatched(x),
ProjectionMismatched(x) => ProjectionMismatched(x),
ProjectionBoundsLength(x) => ProjectionBoundsLength(x),
Sorts(ref x) => return tcx.lift(x).map(Sorts),
@ -621,10 +624,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.substs.visit_with(visitor)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
visitor.visit_trait_ref(*self)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> {
@ -847,27 +846,27 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ExistentialProjection {
trait_ref: self.trait_ref.fold_with(folder),
item_name: self.item_name,
ty: self.ty.fold_with(folder),
substs: self.substs.fold_with(folder),
item_def_id: self.item_def_id,
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.trait_ref.visit_with(visitor) || self.ty.visit_with(visitor)
self.substs.visit_with(visitor) || self.ty.visit_with(visitor)
}
}
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),
substs: self.substs.fold_with(folder),
item_def_id: self.item_def_id,
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.trait_ref.visit_with(visitor)
self.substs.visit_with(visitor)
}
}
@ -1018,7 +1017,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> {
Traits(x) => Traits(x),
VariadicMismatch(x) => VariadicMismatch(x),
CyclicTy => CyclicTy,
ProjectionNameMismatched(x) => ProjectionNameMismatched(x),
ProjectionMismatched(x) => ProjectionMismatched(x),
ProjectionBoundsLength(x) => ProjectionBoundsLength(x),
Sorts(x) => Sorts(x.fold_with(folder)),
TyParamDefaultMismatch(ref x) => TyParamDefaultMismatch(x.fold_with(folder)),
@ -1054,7 +1053,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> {
Traits(_) |
VariadicMismatch(_) |
CyclicTy |
ProjectionNameMismatched(_) |
ProjectionMismatched(_) |
ProjectionBoundsLength(_) => false,
}
}

View file

@ -11,7 +11,6 @@
//! This module contains TypeVariants and its major components
use hir::def_id::DefId;
use hir::map::DefPathHash;
use middle::region;
use ty::subst::{Substs, Subst};
@ -24,7 +23,7 @@ use std::iter;
use std::cmp::Ordering;
use syntax::abi;
use syntax::ast::{self, Name};
use syntax::symbol::{keywords, InternedString};
use syntax::symbol::keywords;
use util::nodemap::FxHashMap;
use serialize;
@ -291,7 +290,8 @@ impl<'a, 'gcx, 'tcx> ExistentialPredicate<'tcx> {
use self::ExistentialPredicate::*;
match (*self, *other) {
(Trait(_), Trait(_)) => Ordering::Equal,
(Projection(ref a), Projection(ref b)) => a.sort_key(tcx).cmp(&b.sort_key(tcx)),
(Projection(ref a), Projection(ref b)) =>
tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id)),
(AutoTrait(ref a), AutoTrait(ref b)) =>
tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash),
(Trait(_), _) => Ordering::Less,
@ -551,8 +551,8 @@ impl fmt::Debug for TypeFlags {
/// form this would be written `<T as Trait<..>>::N`.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct ProjectionTy<'tcx> {
/// The trait reference `T as Trait<..>`.
pub trait_ref: ty::TraitRef<'tcx>,
/// The parameters of the associated item.
pub substs: &'tcx Substs<'tcx>,
/// The DefId of the TraitItem for the associated type N.
///
@ -568,16 +568,28 @@ impl<'a, 'tcx> ProjectionTy<'tcx> {
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;
|item| item.name == item_name && item.kind == ty::AssociatedKind::Type
).unwrap().def_id;
ProjectionTy {
trait_ref,
substs: trait_ref.substs,
item_def_id,
}
}
pub fn item_name(self, tcx: TyCtxt) -> Name {
tcx.associated_item(self.item_def_id).name
/// Extracts the underlying trait reference from this projection.
/// For example, if this is a projection of `<T as Iterator>::Item`,
/// then this function would return a `T: Iterator` trait reference.
pub fn trait_ref(&self, tcx: TyCtxt) -> ty::TraitRef<'tcx> {
let def_id = tcx.associated_item(self.item_def_id).container.id();
ty::TraitRef {
def_id: def_id,
substs: self.substs,
}
}
pub fn self_ty(&self) -> Ty<'tcx> {
self.substs.type_at(0)
}
}
@ -861,29 +873,24 @@ pub enum InferTy {
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct ExistentialProjection<'tcx> {
pub trait_ref: ExistentialTraitRef<'tcx>,
pub item_name: Name,
pub item_def_id: DefId,
pub substs: &'tcx Substs<'tcx>,
pub ty: Ty<'tcx>,
}
pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>;
impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
pub fn item_name(&self) -> Name {
self.item_name // safe to skip the binder to access a name
}
pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (DefPathHash, InternedString) {
// We want something here that is stable across crate boundaries.
// The DefId isn't but the `deterministic_hash` of the corresponding
// DefPath is.
let trait_def = tcx.trait_def(self.trait_ref.def_id);
let def_path_hash = trait_def.def_path_hash;
// An `ast::Name` is also not stable (it's just an index into an
// interning table), so map to the corresponding `InternedString`.
let item_name = self.item_name.as_str();
(def_path_hash, item_name)
/// Extracts the underlying existential trait reference from this projection.
/// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
/// then this function would return a `exists T. T: Iterator` existential trait
/// reference.
pub fn trait_ref(&self, tcx: TyCtxt) -> ty::ExistentialTraitRef<'tcx> {
let def_id = tcx.associated_item(self.item_def_id).container.id();
ty::ExistentialTraitRef{
def_id: def_id,
substs: self.substs,
}
}
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
@ -894,24 +901,17 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> {
assert!(!self_ty.has_escaping_regions());
ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy::from_ref_and_name(
tcx,
self.trait_ref.with_self_ty(tcx, self_ty),
self.item_name),
projection_ty: ty::ProjectionTy {
item_def_id: self.item_def_id,
substs: tcx.mk_substs(
iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned())),
},
ty: self.ty,
}
}
}
impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
pub fn item_name(&self) -> Name {
self.skip_binder().item_name()
}
pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (DefPathHash, InternedString) {
self.skip_binder().sort_key(tcx)
}
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
-> ty::PolyProjectionPredicate<'tcx> {
self.map_bound(|p| p.with_self_ty(tcx, self_ty))
@ -1397,7 +1397,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
substs.substs.regions().collect()
}
TyProjection(ref data) => {
data.trait_ref.substs.regions().collect()
data.substs.regions().collect()
}
TyFnDef(..) |
TyFnPtr(_) |

View file

@ -90,14 +90,14 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
stack.push(mt.ty);
}
ty::TyProjection(ref data) => {
stack.extend(data.trait_ref.substs.types().rev());
stack.extend(data.substs.types().rev());
}
ty::TyDynamic(ref obj, ..) => {
stack.extend(obj.iter().rev().flat_map(|predicate| {
let (substs, opt_ty) = match *predicate.skip_binder() {
ty::ExistentialPredicate::Trait(tr) => (tr.substs, None),
ty::ExistentialPredicate::Projection(p) =>
(p.trait_ref.substs, Some(p.ty)),
(p.substs, Some(p.ty)),
ty::ExistentialPredicate::AutoTrait(_) =>
// Empty iterator
(ty::Substs::empty(), None),

View file

@ -155,11 +155,11 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
// A projection is well-formed if (a) the trait ref itself is
// WF and (b) the trait-ref holds. (It may also be
// normalizable and be WF that way.)
self.compute_trait_ref(&data.trait_ref);
let trait_ref = data.trait_ref(self.infcx.tcx);
self.compute_trait_ref(&trait_ref);
if !data.has_escaping_regions() {
let predicate = data.trait_ref.to_predicate();
let predicate = trait_ref.to_predicate();
let cause = self.cause(traits::ProjectionWf(data));
self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
}

View file

@ -224,7 +224,7 @@ pub fn parameterized(f: &mut fmt::Formatter,
start_or_continue(f, "<", ", ")?;
ty::tls::with(|tcx|
write!(f, "{}={}",
projection.projection_ty.item_name(tcx),
tcx.associated_item(projection.projection_ty.item_def_id).name,
projection.ty)
)?;
}
@ -958,9 +958,14 @@ 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));
// FIXME(tschottdorf): use something like
// parameterized(f, self.substs, self.item_def_id, &[])
// (which currently ICEs).
let (trait_ref, item_name) = ty::tls::with(|tcx|
(self.trait_ref(tcx), tcx.associated_item(self.item_def_id).name)
);
write!(f, "{:?}::{}",
self.trait_ref,
trait_ref,
item_name)
}
}

View file

@ -89,7 +89,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
ty::TyAdt(adt, _) => adt.did,
ty::TyDynamic(ref obj, ..) if obj.principal().is_some() =>
obj.principal().unwrap().def_id(),
ty::TyProjection(ref proj) => proj.trait_ref.def_id,
ty::TyProjection(ref proj) => proj.trait_ref(self.tcx).def_id,
_ => return Some(AccessLevel::Public)
};
if let Some(node_id) = self.tcx.hir.as_local_node_id(ty_def_id) {
@ -395,7 +395,22 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
}
fn predicates(&mut self) -> &mut Self {
self.ev.tcx.predicates_of(self.item_def_id).visit_with(self);
let predicates = self.ev.tcx.predicates_of(self.item_def_id);
for predicate in &predicates.predicates {
predicate.visit_with(self);
match predicate {
&ty::Predicate::Trait(poly_predicate) => {
self.check_trait_ref(poly_predicate.skip_binder().trait_ref);
},
&ty::Predicate::Projection(poly_predicate) => {
let tcx = self.ev.tcx;
self.check_trait_ref(
poly_predicate.skip_binder().projection_ty.trait_ref(tcx)
);
},
_ => (),
};
}
self
}
@ -411,9 +426,19 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
}
fn impl_trait_ref(&mut self) -> &mut Self {
self.ev.tcx.impl_trait_ref(self.item_def_id).visit_with(self);
if let Some(impl_trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) {
self.check_trait_ref(impl_trait_ref);
impl_trait_ref.super_visit_with(self);
}
self
}
fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) {
if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) {
let item = self.ev.tcx.hir.expect_item(node_id);
self.ev.update(item.id, Some(AccessLevel::Reachable));
}
}
}
impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
@ -421,7 +446,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
let ty_def_id = match ty.sty {
ty::TyAdt(adt, _) => Some(adt.did),
ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
ty::TyProjection(ref proj) => Some(proj.item_def_id),
ty::TyFnDef(def_id, ..) |
ty::TyAnon(def_id, _) => Some(def_id),
_ => None
@ -435,15 +460,6 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
ty.super_visit_with(self)
}
fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
if let Some(node_id) = self.ev.tcx.hir.as_local_node_id(trait_ref.def_id) {
let item = self.ev.tcx.hir.expect_item(node_id);
self.ev.update(item.id, Some(AccessLevel::Reachable));
}
trait_ref.super_visit_with(self)
}
}
//////////////////////////////////////////////////////////////////////////////////////
@ -633,14 +649,42 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
}
fn predicates(&mut self) -> &mut Self {
self.tcx.predicates_of(self.current_item).visit_with(self);
let predicates = self.tcx.predicates_of(self.current_item);
for predicate in &predicates.predicates {
predicate.visit_with(self);
match predicate {
&ty::Predicate::Trait(poly_predicate) => {
self.check_trait_ref(poly_predicate.skip_binder().trait_ref);
},
&ty::Predicate::Projection(poly_predicate) => {
let tcx = self.tcx;
self.check_trait_ref(
poly_predicate.skip_binder().projection_ty.trait_ref(tcx)
);
},
_ => (),
};
}
self
}
fn impl_trait_ref(&mut self) -> &mut Self {
self.tcx.impl_trait_ref(self.current_item).visit_with(self);
if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.current_item) {
self.check_trait_ref(impl_trait_ref);
}
self.tcx.predicates_of(self.current_item).visit_with(self);
self
}
fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
if !self.item_is_accessible(trait_ref.def_id) {
let msg = format!("trait `{}` is private", trait_ref);
self.tcx.sess.span_err(self.span, &msg);
return true;
}
trait_ref.super_visit_with(self)
}
}
impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
@ -817,7 +861,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
let is_private = predicates.skip_binder().iter().any(|predicate| {
let def_id = match *predicate {
ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id,
ty::ExistentialPredicate::Projection(proj) => proj.trait_ref.def_id,
ty::ExistentialPredicate::Projection(proj) =>
proj.trait_ref(self.tcx).def_id,
ty::ExistentialPredicate::AutoTrait(def_id) => def_id,
};
!self.item_is_accessible(def_id)
@ -828,6 +873,12 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
return true;
}
}
ty::TyProjection(ref proj) => {
let tcx = self.tcx;
if self.check_trait_ref(proj.trait_ref(tcx)) {
return true;
}
}
ty::TyAnon(def_id, ..) => {
for predicate in &self.tcx.predicates_of(def_id).predicates {
let trait_ref = match *predicate {
@ -838,7 +889,8 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
if poly_projection_predicate.skip_binder().ty.visit_with(self) {
return true;
}
Some(poly_projection_predicate.skip_binder().projection_ty.trait_ref)
Some(poly_projection_predicate.skip_binder()
.projection_ty.trait_ref(self.tcx))
}
ty::Predicate::TypeOutlives(..) => None,
_ => bug!("unexpected predicate: {:?}", predicate),
@ -863,16 +915,6 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
ty.super_visit_with(self)
}
fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
if !self.item_is_accessible(trait_ref.def_id) {
let msg = format!("trait `{}` is private", trait_ref);
self.tcx.sess.span_err(self.span, &msg);
return true;
}
trait_ref.super_visit_with(self)
}
}
///////////////////////////////////////////////////////////////////////////////
@ -1249,7 +1291,22 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
}
fn predicates(&mut self) -> &mut Self {
self.tcx.predicates_of(self.item_def_id).visit_with(self);
let predicates = self.tcx.predicates_of(self.item_def_id);
for predicate in &predicates.predicates {
predicate.visit_with(self);
match predicate {
&ty::Predicate::Trait(poly_predicate) => {
self.check_trait_ref(poly_predicate.skip_binder().trait_ref);
},
&ty::Predicate::Projection(poly_predicate) => {
let tcx = self.tcx;
self.check_trait_ref(
poly_predicate.skip_binder().projection_ty.trait_ref(tcx)
);
},
_ => (),
};
}
self
}
@ -1265,9 +1322,38 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
}
fn impl_trait_ref(&mut self) -> &mut Self {
self.tcx.impl_trait_ref(self.item_def_id).visit_with(self);
if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) {
self.check_trait_ref(impl_trait_ref);
impl_trait_ref.super_visit_with(self);
}
self
}
fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) {
// Non-local means public (private items can't leave their crate, modulo bugs)
if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) {
let item = self.tcx.hir.expect_item(node_id);
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
if !vis.is_at_least(self.min_visibility, self.tcx) {
self.min_visibility = vis;
}
if !vis.is_at_least(self.required_visibility, self.tcx) {
if self.has_pub_restricted || self.has_old_errors {
struct_span_err!(self.tcx.sess, self.span, E0445,
"private trait `{}` in public interface", trait_ref)
.span_label(self.span, format!(
"private trait can't be public"))
.emit();
} else {
self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
node_id,
self.span,
format!("private trait `{}` in public \
interface (error E0445)", trait_ref));
}
}
}
}
}
impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
@ -1285,8 +1371,8 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
// free type aliases, but this isn't done yet.
return false;
}
Some(proj.trait_ref.def_id)
let trait_ref = proj.trait_ref(self.tcx);
Some(trait_ref.def_id)
}
_ => None
};
@ -1317,42 +1403,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
}
}
if let ty::TyProjection(ref proj) = ty.sty {
// Avoid calling `visit_trait_ref` below on the trait,
// as we have already checked the trait itself above.
proj.trait_ref.super_visit_with(self)
} else {
ty.super_visit_with(self)
}
}
fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
// Non-local means public (private items can't leave their crate, modulo bugs)
if let Some(node_id) = self.tcx.hir.as_local_node_id(trait_ref.def_id) {
let item = self.tcx.hir.expect_item(node_id);
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
if !vis.is_at_least(self.min_visibility, self.tcx) {
self.min_visibility = vis;
}
if !vis.is_at_least(self.required_visibility, self.tcx) {
if self.has_pub_restricted || self.has_old_errors {
struct_span_err!(self.tcx.sess, self.span, E0445,
"private trait `{}` in public interface", trait_ref)
.span_label(self.span, format!(
"private trait can't be public"))
.emit();
} else {
self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
node_id,
self.span,
format!("private trait `{}` in public \
interface (error E0445)", trait_ref));
}
}
}
trait_ref.super_visit_with(self)
ty.super_visit_with(self)
}
}

View file

@ -608,13 +608,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
hir::QPath::TypeRelative(..) => {
let ty = hir_ty_to_ty(self.tcx, ty);
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(self.tcx) {
return HirDef::AssociatedTy(item.def_id);
}
}
}
return HirDef::AssociatedTy(proj.item_def_id);
}
HirDef::Err
}

View file

@ -558,7 +558,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
for projection in projections {
let projection = projection.skip_binder();
let name = &projection.item_name.as_str();
let name = &self.tcx.associated_item(projection.item_def_id).name.as_str();
output.push_str(name);
output.push_str("=");
self.push_type_name(projection.ty, output);

View file

@ -66,8 +66,8 @@ pub trait AstConv<'gcx, 'tcx> {
/// late-bound regions.
fn projected_ty_from_poly_trait_ref(&self,
span: Span,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
item_name: ast::Name)
item_def_id: DefId,
poly_trait_ref: ty::PolyTraitRef<'tcx>)
-> Ty<'tcx>;
/// Normalize an associated type coming from the user.
@ -651,11 +651,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
});
let existential_projections = projection_bounds.iter().map(|bound| {
bound.map_bound(|b| {
let p = b.projection_ty;
let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
ty::ExistentialProjection {
trait_ref: self.trait_ref_to_existential(p.trait_ref),
item_name: p.item_name(tcx),
ty: b.ty
ty: b.ty,
item_def_id: b.projection_ty.item_def_id,
substs: trait_ref.substs,
}
})
});
@ -676,22 +676,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
for tr in traits::supertraits(tcx, principal) {
associated_types.extend(tcx.associated_items(tr.def_id())
.filter(|item| item.kind == ty::AssociatedKind::Type)
.map(|item| (tr.def_id(), item.name)));
.map(|item| item.def_id));
}
for projection_bound in &projection_bounds {
let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
projection_bound.0.projection_ty.item_name(tcx));
associated_types.remove(&pair);
associated_types.remove(&projection_bound.0.projection_ty.item_def_id);
}
for (trait_def_id, name) in associated_types {
for item_def_id in associated_types {
let assoc_item = tcx.associated_item(item_def_id);
let trait_def_id = assoc_item.container.id();
struct_span_err!(tcx.sess, span, E0191,
"the value of the associated type `{}` (from the trait `{}`) must be specified",
name,
assoc_item.name,
tcx.item_path_str(trait_def_id))
.span_label(span, format!(
"missing associated type `{}` value", name))
"missing associated type `{}` value", assoc_item.name))
.emit();
}
@ -896,11 +896,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
};
let trait_did = bound.0.def_id;
let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
let ty = self.normalize_ty(span, ty);
let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name)
.expect("missing associated type");
let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, bound);
let ty = self.normalize_ty(span, ty);
let def = Def::AssociatedTy(item.def_id);
let def_scope = tcx.adjust(assoc_name, item.container.id(), ref_id).1;
if !item.vis.is_accessible_from(def_scope, tcx) {
@ -915,12 +916,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
fn qpath_to_ty(&self,
span: Span,
opt_self_ty: Option<Ty<'tcx>>,
trait_def_id: DefId,
item_def_id: DefId,
trait_segment: &hir::PathSegment,
item_segment: &hir::PathSegment)
-> Ty<'tcx>
{
let tcx = self.tcx();
let trait_def_id = tcx.parent_def_id(item_def_id).unwrap();
self.prohibit_type_params(slice::ref_slice(item_segment));
@ -944,7 +946,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
self.normalize_ty(span, tcx.mk_projection(trait_ref, item_segment.name))
self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs))
}
pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
@ -1050,10 +1052,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
Def::AssociatedTy(def_id) => {
self.prohibit_type_params(&path.segments[..path.segments.len()-2]);
let trait_did = tcx.parent_def_id(def_id).unwrap();
self.qpath_to_ty(span,
opt_self_ty,
trait_did,
def_id,
&path.segments[path.segments.len()-2],
path.segments.last().unwrap())
}

View file

@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Given a Projection predicate, we can potentially infer
// the complete signature.
ty::Predicate::Projection(ref proj_predicate) => {
let trait_ref = proj_predicate.to_poly_trait_ref();
let trait_ref = proj_predicate.to_poly_trait_ref(self.tcx);
self.self_type_matches_expected_vid(trait_ref, expected_vid)
.and_then(|_| self.deduce_sig_from_projection(proj_predicate))
}
@ -174,7 +174,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
.map(|obligation| &obligation.obligation)
.filter_map(|obligation| {
let opt_trait_ref = match obligation.predicate {
ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref()),
ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)),
ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()),
ty::Predicate::Equate(..) => None,
ty::Predicate::Subtype(..) => None,
@ -211,7 +211,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
debug!("deduce_sig_from_projection({:?})", projection);
let trait_ref = projection.to_poly_trait_ref();
let trait_ref = projection.to_poly_trait_ref(tcx);
if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() {
return None;

View file

@ -861,7 +861,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
debug!("assemble_projection_candidates: step={:?}", step);
let (def_id, substs) = match step.self_ty.sty {
ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs),
ty::TyProjection(ref data) => {
let trait_ref = data.trait_ref(self.tcx);
(trait_ref.def_id, trait_ref.substs)
},
ty::TyAnon(def_id, substs) => (def_id, substs),
_ => continue,
};

View file

@ -1620,17 +1620,18 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
fn projected_ty_from_poly_trait_ref(&self,
span: Span,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
item_name: ast::Name)
item_def_id: DefId,
poly_trait_ref: ty::PolyTraitRef<'tcx>)
-> Ty<'tcx>
{
let item = self.tcx().associated_item(item_def_id);
let (trait_ref, _) =
self.replace_late_bound_regions_with_fresh_var(
span,
infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
infer::LateBoundRegionConversionTime::AssocTypeProjection(item.name),
&poly_trait_ref);
self.tcx().mk_projection(trait_ref, item_name)
self.tcx().mk_projection(item_def_id, trait_ref.substs)
}
fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx> {

View file

@ -1595,15 +1595,15 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
let needs_infer = projection_ty.trait_ref.needs_infer();
let needs_infer = projection_ty.needs_infer();
if env_bounds.is_empty() && needs_infer {
debug!("projection_must_outlive: no declared bounds");
for component_ty in projection_ty.trait_ref.substs.types() {
for component_ty in projection_ty.substs.types() {
self.type_must_outlive(origin.clone(), component_ty, region);
}
for r in projection_ty.trait_ref.substs.regions() {
for r in projection_ty.substs.regions() {
self.sub_regions(origin.clone(), region, r);
}
@ -1621,7 +1621,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) {
let unique_bound = env_bounds[0];
debug!("projection_must_outlive: unique declared bound = {:?}", unique_bound);
if projection_ty.trait_ref.substs.regions().any(|r| env_bounds.contains(&r)) {
if projection_ty.substs.regions().any(|r| env_bounds.contains(&r)) {
debug!("projection_must_outlive: unique declared bound appears in trait ref");
self.sub_regions(origin.clone(), region, unique_bound);
return;
@ -1691,8 +1691,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
declared_bounds, projection_ty);
// see the extensive comment in projection_must_outlive
let item_name = projection_ty.item_name(self.tcx);
let ty = self.tcx.mk_projection(projection_ty.trait_ref, item_name);
let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
let recursive_bound = self.recursive_type_bound(span, ty);
VerifyBound::AnyRegion(declared_bounds).or(recursive_bound)
@ -1758,9 +1757,7 @@ 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(),
item_name);
let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
// Say we have a projection `<T as SomeTrait<'a>>::SomeType`. We are interested
// in looking for a trait definition like:
@ -1772,7 +1769,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// ```
//
// we can thus deduce that `<T as SomeTrait<'a>>::SomeType : 'a`.
let trait_predicates = self.tcx.predicates_of(projection_ty.trait_ref.def_id);
let trait_predicates = self.tcx.predicates_of(projection_ty.trait_ref(self.tcx).def_id);
assert_eq!(trait_predicates.parent, None);
let predicates = trait_predicates.predicates.as_slice().to_vec();
traits::elaborate_predicates(self.tcx, predicates)
@ -1788,7 +1785,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// apply the substitutions (and normalize any projected types)
let outlives = self.instantiate_type_scheme(span,
projection_ty.trait_ref.substs,
projection_ty.substs,
&outlives);
debug!("projection_bounds: outlives={:?} (2)",
@ -1798,7 +1795,8 @@ 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(self.tcx)),
infer::AssocTypeProjection(
self.tcx.associated_item(projection_ty.item_def_id).name),
&outlives);
debug!("projection_bounds: outlives={:?} (3)",

View file

@ -508,7 +508,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
.map(|(index, _)| Parameter(index as u32))
.collect();
identify_constrained_type_params(ty_predicates.predicates.as_slice(),
identify_constrained_type_params(self.tcx,
ty_predicates.predicates.as_slice(),
None,
&mut constrained_parameters);

View file

@ -225,12 +225,12 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
fn projected_ty_from_poly_trait_ref(&self,
span: Span,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
item_name: ast::Name)
item_def_id: DefId,
poly_trait_ref: ty::PolyTraitRef<'tcx>)
-> Ty<'tcx>
{
if let Some(trait_ref) = self.tcx().no_late_bound_regions(&poly_trait_ref) {
self.tcx().mk_projection(trait_ref, item_name)
self.tcx().mk_projection(item_def_id, trait_ref.substs)
} else {
// no late-bound regions, we can just ignore the binder
span_err!(self.tcx().sess, span, E0212,
@ -1438,7 +1438,10 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
};
let assoc_ty = tcx.mk_projection(self_trait_ref, trait_item.name);
let assoc_ty = tcx.mk_projection(
tcx.hir.local_def_id(trait_item.id),
self_trait_ref.substs,
);
let bounds = compute_bounds(&ItemCtxt::new(tcx, def_id),
assoc_ty,
@ -1458,7 +1461,8 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
if let NodeItem(&Item { node: ItemImpl(..), .. }) = node {
let self_ty = tcx.type_of(def_id);
let trait_ref = tcx.impl_trait_ref(def_id);
ctp::setup_constraining_predicates(&mut predicates,
ctp::setup_constraining_predicates(tcx,
&mut predicates,
trait_ref,
&mut ctp::parameters_for_impl(self_ty, trait_ref));
}

View file

@ -86,12 +86,13 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
}
}
pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>],
pub fn identify_constrained_type_params<'tcx>(tcx: ty::TyCtxt,
predicates: &[ty::Predicate<'tcx>],
impl_trait_ref: Option<ty::TraitRef<'tcx>>,
input_parameters: &mut FxHashSet<Parameter>)
{
let mut predicates = predicates.to_owned();
setup_constraining_predicates(&mut predicates, impl_trait_ref, input_parameters);
setup_constraining_predicates(tcx, &mut predicates, impl_trait_ref, input_parameters);
}
@ -135,7 +136,8 @@ pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>]
/// which is determined by 1, which requires `U`, that is determined
/// by 0. I should probably pick a less tangled example, but I can't
/// think of any.
pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>],
pub fn setup_constraining_predicates<'tcx>(tcx: ty::TyCtxt,
predicates: &mut [ty::Predicate<'tcx>],
impl_trait_ref: Option<ty::TraitRef<'tcx>>,
input_parameters: &mut FxHashSet<Parameter>)
{
@ -175,7 +177,7 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>
// Special case: watch out for some kind of sneaky attempt
// to project out an associated type defined by this very
// trait.
let unbound_trait_ref = &projection.projection_ty.trait_ref;
let unbound_trait_ref = projection.projection_ty.trait_ref(tcx);
if Some(unbound_trait_ref.clone()) == impl_trait_ref {
continue;
}
@ -185,8 +187,7 @@ pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>
// `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
// Then the projection only applies if `T` is known, but it still
// does not determine `U`.
let inputs = parameters_for(&projection.projection_ty.trait_ref, true);
let inputs = parameters_for(&projection.projection_ty.trait_ref(tcx), true);
let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p));
if !relies_only_on_inputs {
continue;

View file

@ -102,7 +102,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let mut input_parameters = ctp::parameters_for_impl(impl_self_ty, impl_trait_ref);
ctp::identify_constrained_type_params(
&impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
tcx, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
// Disallow ANY unconstrained type parameters.
for (ty_param, param) in impl_generics.types.iter().zip(&impl_hir_generics.ty_params) {

View file

@ -324,7 +324,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
ty::TyProjection(ref data) => {
self.add_constraints_from_trait_ref(current, data.trait_ref, variance);
let tcx = self.tcx();
self.add_constraints_from_trait_ref(current, data.trait_ref(tcx), variance);
}
ty::TyAnon(_, substs) => {

View file

@ -952,15 +952,15 @@ impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
fn clean(&self, cx: &DocContext) -> Type {
let trait_ = match self.trait_ref.clean(cx) {
let trait_ = match self.trait_ref(cx.tcx).clean(cx) {
TyParamBound::TraitBound(t, _) => t.trait_,
TyParamBound::RegionBound(_) => {
panic!("cleaning a trait got a region")
}
};
Type::QPath {
name: self.item_name(cx.tcx).clean(cx),
self_type: box self.trait_ref.self_ty().clean(cx),
name: cx.tcx.associated_item(self.item_def_id).name.clean(cx),
self_type: box self.self_ty().clean(cx),
trait_: box trait_
}
}
@ -1784,7 +1784,7 @@ impl Clean<Type> for hir::Ty {
let mut def = Def::Err;
let ty = hir_ty_to_ty(cx.tcx, self);
if let ty::TyProjection(proj) = ty.sty {
def = Def::Trait(proj.trait_ref.def_id);
def = Def::Trait(proj.trait_ref(cx.tcx).def_id);
}
let trait_path = hir::Path {
span: self.span,
@ -1901,7 +1901,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
let mut bindings = vec![];
for ty::Binder(ref pb) in obj.projection_bounds() {
bindings.push(TypeBinding {
name: pb.item_name.clean(cx),
name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx),
ty: pb.ty.clean(cx)
});
}