Auto merge of #79945 - jackh726:existential_trait_ref, r=nikomatsakis

Move binder for dyn to each list item

This essentially changes `ty::Binder<&'tcx List<ExistentialTraitRef>>` to `&'tcx List<ty::Binder<ExistentialTraitRef>>`.

This is a first step in moving the `dyn Trait` representation closer to Chalk, which we've talked about in `@rust-lang/wg-traits.`

r? `@nikomatsakis`
This commit is contained in:
bors 2020-12-17 18:21:20 +00:00
commit eb4fc71dc9
26 changed files with 315 additions and 262 deletions

View file

@ -219,8 +219,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
}
if let ty::Dynamic(traits, _) = self_ty.kind() {
for t in traits.skip_binder() {
if let ty::ExistentialPredicate::Trait(trait_ref) = t {
for t in traits.iter() {
if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() {
flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
}
}

View file

@ -551,8 +551,9 @@ fn object_ty_for_trait<'tcx>(
let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
let trait_predicate =
ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
let trait_predicate = ty::Binder::dummy(ty::ExistentialPredicate::Trait(
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
));
let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
.flat_map(|super_trait_ref| {
@ -569,24 +570,19 @@ fn object_ty_for_trait<'tcx>(
let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
// We *can* get bound lifetimes here in cases like
// `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
//
// binder moved to (*)...
let super_trait_ref = super_trait_ref.skip_binder();
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
ty: tcx.mk_projection(item.def_id, super_trait_ref.substs),
item_def_id: item.def_id,
substs: super_trait_ref.substs,
super_trait_ref.map_bound(|super_trait_ref| {
ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
ty: tcx.mk_projection(item.def_id, super_trait_ref.substs),
item_def_id: item.def_id,
substs: super_trait_ref.substs,
})
})
});
let existential_predicates =
tcx.mk_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
let existential_predicates = tcx
.mk_poly_existential_predicates(iter::once(trait_predicate).chain(projection_predicates));
let object_ty = tcx.mk_dynamic(
// (*) ... binder re-introduced here
ty::Binder::bind(existential_predicates),
lifetime,
);
let object_ty = tcx.mk_dynamic(existential_predicates, lifetime);
debug!("object_ty_for_trait: object_ty=`{}`", object_ty);

View file

@ -375,24 +375,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty());
let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref);
let data = match *self_ty.kind() {
ty::Dynamic(data, ..) => {
self.infcx
.replace_bound_vars_with_fresh_vars(
obligation.cause.span,
HigherRankedType,
data,
)
.0
}
ty::Dynamic(data, ..) => data,
_ => span_bug!(obligation.cause.span, "object candidate with non-object"),
};
let object_trait_ref = data
.principal()
.unwrap_or_else(|| {
span_bug!(obligation.cause.span, "object candidate with no principal")
})
.with_self_ty(self.tcx(), self_ty);
let object_trait_ref = data.principal().unwrap_or_else(|| {
span_bug!(obligation.cause.span, "object candidate with no principal")
});
let object_trait_ref = self
.infcx
.replace_bound_vars_with_fresh_vars(
obligation.cause.span,
HigherRankedType,
object_trait_ref,
)
.0;
let object_trait_ref = object_trait_ref.with_self_ty(self.tcx(), self_ty);
let mut nested = vec![];
@ -711,15 +709,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
// See `assemble_candidates_for_unsizing` for more info.
let existential_predicates = data_a.map_bound(|data_a| {
let iter = data_a
.principal()
.map(ty::ExistentialPredicate::Trait)
.into_iter()
.chain(data_a.projection_bounds().map(ty::ExistentialPredicate::Projection))
.chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
tcx.mk_existential_predicates(iter)
});
let iter = data_a
.principal()
.map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
.into_iter()
.chain(
data_a
.projection_bounds()
.map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
)
.chain(
data_b
.auto_traits()
.map(ty::ExistentialPredicate::AutoTrait)
.map(ty::Binder::dummy),
);
let existential_predicates = tcx.mk_poly_existential_predicates(iter);
let source_trait = tcx.mk_dynamic(existential_predicates, r_b);
// Require that the traits involved in this upcast are **equal**;

View file

@ -706,7 +706,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
fn from_object_ty(
&mut self,
ty: Ty<'tcx>,
data: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
data: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
region: ty::Region<'tcx>,
) {
// Imagine a type like this:
@ -769,7 +769,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
/// `infer::required_region_bounds`, see that for more information.
pub fn object_region_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
existential_predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
) -> Vec<ty::Region<'tcx>> {
// Since we don't actually *know* the self type for an object,
// this "open(err)" serves as a kind of dummy standin -- basically