Skip to content

Commit

Permalink
use the correct supertrait substitution in object_ty_for_trait
Browse files Browse the repository at this point in the history
Fixes #57156.
  • Loading branch information
arielb1 committed Jan 5, 2019
1 parent 6861426 commit 85c4b4c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 9 deletions.
33 changes: 24 additions & 9 deletions src/librustc/traits/object_safety.rs
Expand Up @@ -252,6 +252,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
method: &ty::AssociatedItem)
-> Option<MethodViolationCode>
{
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite is otherwise
// exempt from the regulations.
if self.generics_require_sized_self(method.def_id) {
Expand All @@ -270,6 +271,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
method: &ty::AssociatedItem)
-> bool
{
debug!("is_vtable_safe_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite can't be called.
if self.generics_require_sized_self(method.def_id) {
return false;
Expand Down Expand Up @@ -389,6 +391,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
fn receiver_for_self_ty(
self, receiver_ty: Ty<'tcx>, self_ty: Ty<'tcx>, method_def_id: DefId
) -> Ty<'tcx> {
debug!("receiver_for_self_ty({:?}, {:?}, {:?})", receiver_ty, self_ty, method_def_id);
let substs = Substs::for_item(self, method_def_id, |param, _| {
if param.index == 0 {
self_ty.into()
Expand All @@ -397,7 +400,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
}
});

receiver_ty.subst(self, substs)
let result = receiver_ty.subst(self, substs);
debug!("receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}",
receiver_ty, self_ty, method_def_id, result);
result
}

/// creates the object type for the current trait. For example,
Expand All @@ -413,18 +419,26 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
);

let mut associated_types = traits::supertraits(self, ty::Binder::dummy(trait_ref))
.flat_map(|trait_ref| self.associated_items(trait_ref.def_id()))
.filter(|item| item.kind == ty::AssociatedKind::Type)
.flat_map(|super_trait_ref| {
self.associated_items(super_trait_ref.def_id())
.map(move |item| (super_trait_ref, item))
})
.filter(|(_, item)| item.kind == ty::AssociatedKind::Type)
.collect::<Vec<_>>();

// existential predicates need to be in a specific order
associated_types.sort_by_cached_key(|item| self.def_path_hash(item.def_id));

let projection_predicates = associated_types.into_iter().map(|item| {
associated_types.sort_by_cached_key(|(_, item)| self.def_path_hash(item.def_id));

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: self.mk_projection(item.def_id, trait_ref.substs),
ty: self.mk_projection(item.def_id, super_trait_ref.substs),
item_def_id: item.def_id,
substs: trait_ref.substs,
substs: super_trait_ref.substs,
})
});

Expand All @@ -433,7 +447,8 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
);

let object_ty = self.mk_dynamic(
ty::Binder::dummy(existential_predicates),
// (*) ... binder re-introduced here
ty::Binder::bind(existential_predicates),
lifetime,
);

Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/issues/issue-57156.rs
@@ -0,0 +1,23 @@
// compile-pass

trait Foo<Args> {
type Output;
}

trait Bar<'a, T>: for<'s> Foo<&'s T, Output=bool> {
fn cb(&self) -> Box<dyn Bar<'a, T, Output=bool>>;
}

impl<'s> Foo<&'s ()> for () {
type Output = bool;
}

impl<'a> Bar<'a, ()> for () {
fn cb(&self) -> Box<dyn Bar<'a, (), Output=bool>> {
Box::new(*self)
}
}

fn main() {
let _t = ().cb();
}

0 comments on commit 85c4b4c

Please sign in to comment.