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:
parent
dddf24d96f
commit
687ee7fee4
33 changed files with 341 additions and 294 deletions
|
|
@ -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
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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!(
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(_) |
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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)",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue