Auto merge of #57355 - arielb1:correct-subst, r=nikomatsakis

use the correct supertrait substitution in `object_ty_for_trait`

beta-nominating because regression.

Fixes #57156.
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 0096724..c37dc2a 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -252,6 +252,7 @@
                                           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) {
@@ -270,6 +271,7 @@
                                  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;
@@ -402,6 +404,7 @@
     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()
@@ -410,7 +413,10 @@
             }
         });
 
-        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,
@@ -426,18 +432,26 @@
         );
 
         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));
+        associated_types.sort_by_cached_key(|(_, item)| self.def_path_hash(item.def_id));
 
-        let projection_predicates = associated_types.into_iter().map(|item| {
+        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,
             })
         });
 
@@ -446,7 +460,8 @@
         );
 
         let object_ty = self.mk_dynamic(
-            ty::Binder::dummy(existential_predicates),
+            // (*) ... binder re-introduced here
+            ty::Binder::bind(existential_predicates),
             lifetime,
         );
 
diff --git a/src/test/ui/issues/issue-57156.rs b/src/test/ui/issues/issue-57156.rs
new file mode 100644
index 0000000..f20b0f4
--- /dev/null
+++ b/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();
+}