Skip to content

Commit

Permalink
Downgrade ProjectionTy's TraitRef to its substs
Browse files Browse the repository at this point in the history
Addresses the second part of #42171 by removing the `TraitRef` from
`ProjectionTy`, and directly storing its `Substs`.

Closes #42171.
  • Loading branch information
tbg committed Jul 11, 2017
1 parent dddf24d commit 687ee7f
Show file tree
Hide file tree
Showing 33 changed files with 341 additions and 294 deletions.
6 changes: 3 additions & 3 deletions src/librustc/ich/impls_ty.rs
Expand Up @@ -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> {
Expand Down Expand Up @@ -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
});

Expand Down
7 changes: 3 additions & 4 deletions src/librustc/infer/mod.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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 })
Expand Down
3 changes: 1 addition & 2 deletions src/librustc/infer/region_inference/mod.rs
Expand Up @@ -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),
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/traits/fulfill.rs
Expand Up @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/object_safety.rs
Expand Up @@ -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);

Expand Down
64 changes: 30 additions & 34 deletions src/librustc/traits/project.rs
Expand Up @@ -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 {
Expand Down Expand Up @@ -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![] });
// ```

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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)))
}
}

Expand Down Expand Up @@ -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(_)) => {
Expand All @@ -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,
Expand All @@ -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)
Expand All @@ -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()));
Expand Down Expand Up @@ -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`
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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);

Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/traits/select.rs
Expand Up @@ -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!(
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/traits/trans/mod.rs
Expand Up @@ -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();

Expand Down
13 changes: 7 additions & 6 deletions src/librustc/ty/context.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 6 additions & 6 deletions src/librustc/ty/error.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -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>>>),
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/ty/flags.rs
Expand Up @@ -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) {
Expand Down
4 changes: 0 additions & 4 deletions src/librustc/ty/fold.rs
Expand Up @@ -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)
}
Expand Down

0 comments on commit 687ee7f

Please sign in to comment.