about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs68
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs113
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs5
-rw-r--r--compiler/rustc_infer/src/traits/util.rs47
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs14
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs4
-rw-r--r--compiler/rustc_middle/src/query/keys.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs12
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs2
-rw-r--r--tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr2
-rw-r--r--tests/ui/associated-types/issue-20825.stderr2
-rw-r--r--tests/ui/closures/self-supertrait-bounds.rs14
-rw-r--r--tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr9
-rw-r--r--tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr14
-rw-r--r--tests/ui/infinite/infinite-trait-alias-recursion.stderr17
-rw-r--r--tests/ui/issues/issue-12511.stderr12
-rw-r--r--tests/ui/issues/issue-20772.stderr2
-rw-r--r--tests/ui/lint/unused/trait-alias-supertrait.rs15
-rw-r--r--tests/ui/traits/alias/dont-elaborate-non-self.rs10
-rw-r--r--tests/ui/traits/alias/dont-elaborate-non-self.stderr20
-rw-r--r--tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs33
-rw-r--r--tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr9
28 files changed, 308 insertions, 150 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 37c894348cd..8cb95610da0 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1663,39 +1663,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             })
         });
 
-        let existential_projections = projection_bounds.iter().map(|(bound, _)| {
-            bound.map_bound(|mut b| {
-                assert_eq!(b.projection_ty.self_ty(), dummy_self);
-
-                // Like for trait refs, verify that `dummy_self` did not leak inside default type
-                // parameters.
-                let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
-                    if arg.walk().any(|arg| arg == dummy_self.into()) {
-                        return true;
+        let existential_projections = projection_bounds
+            .iter()
+            // We filter out traits that don't have `Self` as their self type above,
+            // we need to do the same for projections.
+            .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self)
+            .map(|(bound, _)| {
+                bound.map_bound(|mut b| {
+                    assert_eq!(b.projection_ty.self_ty(), dummy_self);
+
+                    // Like for trait refs, verify that `dummy_self` did not leak inside default type
+                    // parameters.
+                    let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
+                        if arg.walk().any(|arg| arg == dummy_self.into()) {
+                            return true;
+                        }
+                        false
+                    });
+                    if references_self {
+                        let guar = tcx.sess.delay_span_bug(
+                            span,
+                            "trait object projection bounds reference `Self`",
+                        );
+                        let substs: Vec<_> = b
+                            .projection_ty
+                            .substs
+                            .iter()
+                            .map(|arg| {
+                                if arg.walk().any(|arg| arg == dummy_self.into()) {
+                                    return tcx.ty_error(guar).into();
+                                }
+                                arg
+                            })
+                            .collect();
+                        b.projection_ty.substs = tcx.mk_substs(&substs);
                     }
-                    false
-                });
-                if references_self {
-                    let guar = tcx
-                        .sess
-                        .delay_span_bug(span, "trait object projection bounds reference `Self`");
-                    let substs: Vec<_> = b
-                        .projection_ty
-                        .substs
-                        .iter()
-                        .map(|arg| {
-                            if arg.walk().any(|arg| arg == dummy_self.into()) {
-                                return tcx.ty_error(guar).into();
-                            }
-                            arg
-                        })
-                        .collect();
-                    b.projection_ty.substs = tcx.mk_substs(&substs);
-                }
 
-                ty::ExistentialProjection::erase_self_ty(tcx, b)
-            })
-        });
+                    ty::ExistentialProjection::erase_self_ty(tcx, b)
+                })
+            });
 
         let regular_trait_predicates = existential_trait_refs
             .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait));
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 50862e34262..cbbaf8f857d 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -64,6 +64,7 @@ pub fn provide(providers: &mut Providers) {
         predicates_defined_on,
         explicit_predicates_of: predicates_of::explicit_predicates_of,
         super_predicates_of: predicates_of::super_predicates_of,
+        implied_predicates_of: predicates_of::implied_predicates_of,
         super_predicates_that_define_assoc_type:
             predicates_of::super_predicates_that_define_assoc_type,
         trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
@@ -596,6 +597,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
         }
         hir::ItemKind::TraitAlias(..) => {
             tcx.ensure().generics_of(def_id);
+            tcx.at(it.span).implied_predicates_of(def_id);
             tcx.at(it.span).super_predicates_of(def_id);
             tcx.ensure().predicates_of(def_id);
         }
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index fdab87b6ace..9358ed61292 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -125,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     // on a trait we need to add in the supertrait bounds and bounds found on
     // associated types.
     if let Some(_trait_ref) = is_trait {
-        predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
+        predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned());
     }
 
     // In default impls, we can assume that the self type implements
@@ -534,6 +534,19 @@ pub(super) fn explicit_predicates_of<'tcx>(
     }
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum PredicateFilter {
+    /// All predicates may be implied by the trait
+    All,
+
+    /// Only traits that reference `Self: ..` are implied by the trait
+    SelfOnly,
+
+    /// Only traits that reference `Self: ..` and define an associated type
+    /// with the given ident are implied by the trait
+    SelfThatDefines(Ident),
+}
+
 /// Ensures that the super-predicates of the trait with a `DefId`
 /// of `trait_def_id` are converted and stored. This also ensures that
 /// the transitive super-predicates are converted.
@@ -541,24 +554,42 @@ pub(super) fn super_predicates_of(
     tcx: TyCtxt<'_>,
     trait_def_id: LocalDefId,
 ) -> ty::GenericPredicates<'_> {
-    tcx.super_predicates_that_define_assoc_type((trait_def_id.to_def_id(), None))
+    implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
+}
+
+pub(super) fn super_predicates_that_define_assoc_type(
+    tcx: TyCtxt<'_>,
+    (trait_def_id, assoc_name): (DefId, Ident),
+) -> ty::GenericPredicates<'_> {
+    implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name))
+}
+
+pub(super) fn implied_predicates_of(
+    tcx: TyCtxt<'_>,
+    trait_def_id: LocalDefId,
+) -> ty::GenericPredicates<'_> {
+    if tcx.is_trait_alias(trait_def_id.to_def_id()) {
+        implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
+    } else {
+        tcx.super_predicates_of(trait_def_id)
+    }
 }
 
 /// Ensures that the super-predicates of the trait with a `DefId`
 /// of `trait_def_id` are converted and stored. This also ensures that
 /// the transitive super-predicates are converted.
-pub(super) fn super_predicates_that_define_assoc_type(
+pub(super) fn implied_predicates_with_filter(
     tcx: TyCtxt<'_>,
-    (trait_def_id, assoc_name): (DefId, Option<Ident>),
+    trait_def_id: DefId,
+    filter: PredicateFilter,
 ) -> ty::GenericPredicates<'_> {
     let Some(trait_def_id) = trait_def_id.as_local() else {
         // if `assoc_name` is None, then the query should've been redirected to an
         // external provider
-        assert!(assoc_name.is_some());
+        assert!(matches!(filter, PredicateFilter::SelfThatDefines(_)));
         return tcx.super_predicates_of(trait_def_id);
     };
 
-    debug!("local trait");
     let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id);
 
     let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
@@ -573,40 +604,58 @@ pub(super) fn super_predicates_that_define_assoc_type(
 
     let icx = ItemCtxt::new(tcx, trait_def_id);
 
-    // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
     let self_param_ty = tcx.types.self_param;
-    let superbounds1 = if let Some(assoc_name) = assoc_name {
-        icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
-    } else {
-        icx.astconv().compute_bounds(self_param_ty, bounds)
+    let (superbounds, where_bounds_that_match) = match filter {
+        PredicateFilter::All => (
+            // Convert the bounds that follow the colon (or equal in trait aliases)
+            icx.astconv().compute_bounds(self_param_ty, bounds),
+            // Also include all where clause bounds
+            icx.type_parameter_bounds_in_generics(
+                generics,
+                item.owner_id.def_id,
+                self_param_ty,
+                OnlySelfBounds(false),
+                None,
+            ),
+        ),
+        PredicateFilter::SelfOnly => (
+            // Convert the bounds that follow the colon (or equal in trait aliases)
+            icx.astconv().compute_bounds(self_param_ty, bounds),
+            // Include where clause bounds for `Self`
+            icx.type_parameter_bounds_in_generics(
+                generics,
+                item.owner_id.def_id,
+                self_param_ty,
+                OnlySelfBounds(true),
+                None,
+            ),
+        ),
+        PredicateFilter::SelfThatDefines(assoc_name) => (
+            // Convert the bounds that follow the colon (or equal) that reference the associated name
+            icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name),
+            // Include where clause bounds for `Self` that reference the associated name
+            icx.type_parameter_bounds_in_generics(
+                generics,
+                item.owner_id.def_id,
+                self_param_ty,
+                OnlySelfBounds(true),
+                Some(assoc_name),
+            ),
+        ),
     };
 
-    let superbounds1 = superbounds1.predicates();
-
-    // Convert any explicit superbounds in the where-clause,
-    // e.g., `trait Foo where Self: Bar`.
-    // In the case of trait aliases, however, we include all bounds in the where-clause,
-    // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
-    // as one of its "superpredicates".
-    let is_trait_alias = tcx.is_trait_alias(trait_def_id.to_def_id());
-    let superbounds2 = icx.type_parameter_bounds_in_generics(
-        generics,
-        item.owner_id.def_id,
-        self_param_ty,
-        OnlySelfBounds(!is_trait_alias),
-        assoc_name,
-    );
-
     // Combine the two lists to form the complete set of superbounds:
-    let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
-    debug!(?superbounds);
+    let implied_bounds = &*tcx
+        .arena
+        .alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match));
+    debug!(?implied_bounds);
 
     // Now require that immediate supertraits are converted,
     // which will, in turn, reach indirect supertraits.
-    if assoc_name.is_none() {
+    if matches!(filter, PredicateFilter::SelfOnly) {
         // Now require that immediate supertraits are converted,
         // which will, in turn, reach indirect supertraits.
-        for &(pred, span) in superbounds {
+        for &(pred, span) in implied_bounds {
             debug!("superbound: {:?}", pred);
             if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() {
                 tcx.at(span).super_predicates_of(bound.def_id());
@@ -614,7 +663,7 @@ pub(super) fn super_predicates_that_define_assoc_type(
         }
     }
 
-    ty::GenericPredicates { parent: None, predicates: superbounds }
+    ty::GenericPredicates { parent: None, predicates: implied_bounds }
 }
 
 /// Returns the predicates defined on `item_def_id` of the form
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 5e4f377a1e7..e758fe95d9c 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1749,8 +1749,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             if trait_defines_associated_type_named(def_id) {
                 break Some(bound_vars.into_iter().collect());
             }
-            let predicates =
-                tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name)));
+            let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
             let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
                 let bound_predicate = pred.kind();
                 match bound_predicate.skip_binder() {
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 15eec42d786..8c2495e1dd8 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -210,7 +210,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // and we want to keep inference generally in the same order of
             // the registered obligations.
             predicates.rev(),
-        ) {
+        )
+        // We only care about self bounds
+        .filter_only_self()
+        {
             debug!(?pred);
             let bound_predicate = pred.kind();
 
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index c7f7ed14940..ef01d5d513b 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -69,6 +69,7 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
 pub struct Elaborator<'tcx, O> {
     stack: Vec<O>,
     visited: PredicateSet<'tcx>,
+    only_self: bool,
 }
 
 /// Describes how to elaborate an obligation into a sub-obligation.
@@ -170,7 +171,8 @@ pub fn elaborate<'tcx, O: Elaboratable<'tcx>>(
     tcx: TyCtxt<'tcx>,
     obligations: impl IntoIterator<Item = O>,
 ) -> Elaborator<'tcx, O> {
-    let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) };
+    let mut elaborator =
+        Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx), only_self: false };
     elaborator.extend_deduped(obligations);
     elaborator
 }
@@ -185,14 +187,25 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
         self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate())));
     }
 
+    /// Filter to only the supertraits of trait predicates, i.e. only the predicates
+    /// that have `Self` as their self type, instead of all implied predicates.
+    pub fn filter_only_self(mut self) -> Self {
+        self.only_self = true;
+        self
+    }
+
     fn elaborate(&mut self, elaboratable: &O) {
         let tcx = self.visited.tcx;
 
         let bound_predicate = elaboratable.predicate().kind();
         match bound_predicate.skip_binder() {
             ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
-                // Get predicates declared on the trait.
-                let predicates = tcx.super_predicates_of(data.def_id());
+                // Get predicates implied by the trait, or only super predicates if we only care about self predicates.
+                let predicates = if self.only_self {
+                    tcx.super_predicates_of(data.def_id())
+                } else {
+                    tcx.implied_predicates_of(data.def_id())
+                };
 
                 let obligations =
                     predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| {
@@ -350,18 +363,16 @@ pub fn supertraits<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>,
 ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
-    let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx);
-    FilterToTraits::new(elaborate(tcx, [pred]))
+    elaborate(tcx, [trait_ref.to_predicate(tcx)]).filter_only_self().filter_to_traits()
 }
 
 pub fn transitive_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
 ) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
-    FilterToTraits::new(elaborate(
-        tcx,
-        trait_refs.map(|trait_ref| -> ty::Predicate<'tcx> { trait_ref.to_predicate(tcx) }),
-    ))
+    elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx)))
+        .filter_only_self()
+        .filter_to_traits()
 }
 
 /// A specialized variant of `elaborate` that only elaborates trait references that may
@@ -381,10 +392,8 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
         while let Some(trait_ref) = stack.pop() {
             let anon_trait_ref = tcx.anonymize_bound_vars(trait_ref);
             if visited.insert(anon_trait_ref) {
-                let super_predicates = tcx.super_predicates_that_define_assoc_type((
-                    trait_ref.def_id(),
-                    Some(assoc_name),
-                ));
+                let super_predicates =
+                    tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), assoc_name));
                 for (super_predicate, _) in super_predicates.predicates {
                     let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref);
                     if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() {
@@ -404,18 +413,18 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
 // Other
 ///////////////////////////////////////////////////////////////////////////
 
+impl<'tcx> Elaborator<'tcx, ty::Predicate<'tcx>> {
+    fn filter_to_traits(self) -> FilterToTraits<Self> {
+        FilterToTraits { base_iterator: self }
+    }
+}
+
 /// A filter around an iterator of predicates that makes it yield up
 /// just trait references.
 pub struct FilterToTraits<I> {
     base_iterator: I,
 }
 
-impl<I> FilterToTraits<I> {
-    fn new(base: I) -> FilterToTraits<I> {
-        FilterToTraits { base_iterator: base }
-    }
-}
-
 impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
     type Item = ty::PolyTraitRef<'tcx>;
 
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 35c461f5ace..1159d11e5c0 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -255,6 +255,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
                 ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
                 ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
                     elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned())
+                        // We only care about self bounds for the impl-trait
+                        .filter_only_self()
                         .find_map(|(pred, _span)| {
                             // We only look at the `DefId`, so it is safe to skip the binder here.
                             if let ty::PredicateKind::Clause(ty::Clause::Trait(
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 3a50d7c9363..31798afb852 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -253,7 +253,19 @@ provide! { tcx, def_id, other, cdata,
             .get(cdata, def_id.index)
             .map(|lazy| lazy.decode((cdata, tcx)))
             .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
-     }
+    }
+    implied_predicates_of => {
+        cdata
+            .root
+            .tables
+            .implied_predicates_of
+            .get(cdata, def_id.index)
+            .map(|lazy| lazy.decode((cdata, tcx)))
+            .unwrap_or_else(|| {
+                debug_assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
+                tcx.super_predicates_of(def_id)
+            })
+    }
 
     associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array }
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 77ec03165fb..dc8fa1ab7d3 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1316,9 +1316,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 let default = self.tcx.object_lifetime_default(def_id);
                 record!(self.tables.object_lifetime_default[def_id] <- default);
             }
-            if let DefKind::Trait | DefKind::TraitAlias = def_kind {
+            if let DefKind::Trait = def_kind {
                 record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
             }
+            if let DefKind::TraitAlias = def_kind {
+                record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
+                record!(self.tables.implied_predicates_of[def_id] <- self.tcx.implied_predicates_of(def_id));
+            }
             if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
                 self.encode_info_for_adt(def_id);
             }
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 6dc6041b284..569fd20fdfe 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -372,6 +372,9 @@ define_tables! {
     explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
     generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
     super_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
+    // As an optimization, we only store this for trait aliases,
+    // since it's identical to super_predicates_of for traits.
+    implied_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
     type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<Ty<'static>>>>,
     variances_of: Table<DefIndex, LazyArray<ty::Variance>>,
     fn_sig: Table<DefIndex, LazyValue<ty::EarlyBinder<ty::PolyFnSig<'static>>>>,
@@ -383,7 +386,6 @@ define_tables! {
     mir_for_ctfe: Table<DefIndex, LazyValue<mir::Body<'static>>>,
     mir_generator_witnesses: Table<DefIndex, LazyValue<mir::GeneratorLayout<'static>>>,
     promoted_mir: Table<DefIndex, LazyValue<IndexVec<mir::Promoted, mir::Body<'static>>>>,
-    // FIXME(compiler-errors): Why isn't this a LazyArray?
     thir_abstract_const: Table<DefIndex, LazyValue<ty::Const<'static>>>,
     impl_parent: Table<DefIndex, RawDefId>,
     impl_polarity: Table<DefIndex, ty::ImplPolarity>,
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 4a096a2c0e8..3b0eec683de 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -230,7 +230,7 @@ impl Key for (LocalDefId, LocalDefId) {
     }
 }
 
-impl Key for (DefId, Option<Ident>) {
+impl Key for (DefId, Ident) {
     type CacheSelector = DefaultCacheSelector<Self>;
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index a0fce4b47ca..2f6b7a3c860 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -627,14 +627,20 @@ rustc_queries! {
         separate_provide_extern
     }
 
+    query implied_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> {
+        desc { |tcx| "computing the implied predicates of `{}`", tcx.def_path_str(key) }
+        cache_on_disk_if { key.is_local() }
+        separate_provide_extern
+    }
+
     /// The `Option<Ident>` is the name of an associated type. If it is `None`, then this query
     /// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
     /// subset of super-predicates that reference traits that define the given associated type.
     /// This is used to avoid cycles in resolving types like `T::Item`.
-    query super_predicates_that_define_assoc_type(key: (DefId, Option<rustc_span::symbol::Ident>)) -> ty::GenericPredicates<'tcx> {
-        desc { |tcx| "computing the super traits of `{}`{}",
+    query super_predicates_that_define_assoc_type(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
+        desc { |tcx| "computing the super traits of `{}` with associated type name `{}`",
             tcx.def_path_str(key.0),
-            if let Some(assoc_name) = key.1 { format!(" with associated type name `{}`", assoc_name) } else { "".to_string() },
+            key.1
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index a33e8ef4b4a..7f0ceb6646c 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -505,7 +505,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let tcx = self.tcx();
         let own_bounds: FxIndexSet<_> =
             bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect();
-        for assumption in elaborate(tcx, own_bounds.iter().copied()) {
+        for assumption in elaborate(tcx, own_bounds.iter().copied())
+            // we only care about bounds that match the `Self` type
+            .filter_only_self()
+        {
             // FIXME: Predicates are fully elaborated in the object type's existential bounds
             // list. We want to only consider these pre-elaborated projections, and not other
             // projection predicates that we reach by elaborating the principal trait ref,
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 00c9a352258..60630979b34 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -115,7 +115,7 @@ impl<'tcx> TraitAliasExpander<'tcx> {
         }
 
         // Get components of trait alias.
-        let predicates = tcx.super_predicates_of(trait_ref.def_id());
+        let predicates = tcx.implied_predicates_of(trait_ref.def_id());
         debug!(?predicates);
 
         let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
diff --git a/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr b/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr
index 4162cdaa8dc..575b00e09b0 100644
--- a/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr
+++ b/tests/ui/associated-type-bounds/ambiguous-associated-type2.stderr
@@ -5,7 +5,7 @@ LL | trait Baz: Foo + Bar<Self::Item> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: ...which immediately requires computing the super traits of `Baz` with associated type name `Item` again
-note: cycle used when computing the super traits of `Baz`
+note: cycle used when computing the super predicates of `Baz`
   --> $DIR/ambiguous-associated-type2.rs:7:1
    |
 LL | trait Baz: Foo + Bar<Self::Item> {}
diff --git a/tests/ui/associated-types/issue-20825.stderr b/tests/ui/associated-types/issue-20825.stderr
index be2bbd44800..c4dea68b884 100644
--- a/tests/ui/associated-types/issue-20825.stderr
+++ b/tests/ui/associated-types/issue-20825.stderr
@@ -5,7 +5,7 @@ LL | pub trait Processor: Subscriber<Input = Self::Input> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: ...which immediately requires computing the super traits of `Processor` with associated type name `Input` again
-note: cycle used when computing the super traits of `Processor`
+note: cycle used when computing the super predicates of `Processor`
   --> $DIR/issue-20825.rs:5:1
    |
 LL | pub trait Processor: Subscriber<Input = Self::Input> {
diff --git a/tests/ui/closures/self-supertrait-bounds.rs b/tests/ui/closures/self-supertrait-bounds.rs
new file mode 100644
index 00000000000..f4f1cea6b81
--- /dev/null
+++ b/tests/ui/closures/self-supertrait-bounds.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+// Makes sure that we only consider `Self` supertrait predicates while
+// elaborating during closure signature deduction.
+
+#![feature(trait_alias)]
+
+trait Confusing<F> = Fn(i32) where F: Fn(u32);
+
+fn alias<T: Confusing<F>, F>(_: T, _: F) {}
+
+fn main() {
+    alias(|_| {}, |_| {});
+}
diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
index f6ffcc4b5aa..e2b2aac05ac 100644
--- a/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
+++ b/tests/ui/cycle-trait/cycle-trait-supertrait-direct.stderr
@@ -1,15 +1,10 @@
 error[E0391]: cycle detected when computing the super predicates of `Chromosome`
-  --> $DIR/cycle-trait-supertrait-direct.rs:3:1
-   |
-LL | trait Chromosome: Chromosome {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires computing the super traits of `Chromosome`...
   --> $DIR/cycle-trait-supertrait-direct.rs:3:19
    |
 LL | trait Chromosome: Chromosome {
    |                   ^^^^^^^^^^
-   = note: ...which again requires computing the super predicates of `Chromosome`, completing the cycle
+   |
+   = note: ...which immediately requires computing the super predicates of `Chromosome` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/cycle-trait-supertrait-direct.rs:3:1
    |
diff --git a/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr b/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr
index 0a2284e0efb..c903e114657 100644
--- a/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr
+++ b/tests/ui/cycle-trait/cycle-trait-supertrait-indirect.stderr
@@ -1,26 +1,16 @@
 error[E0391]: cycle detected when computing the super predicates of `B`
-  --> $DIR/cycle-trait-supertrait-indirect.rs:7:1
-   |
-LL | trait B: C {
-   | ^^^^^^^^^^
-   |
-note: ...which requires computing the super traits of `B`...
   --> $DIR/cycle-trait-supertrait-indirect.rs:7:10
    |
 LL | trait B: C {
    |          ^
-note: ...which requires computing the super predicates of `C`...
-  --> $DIR/cycle-trait-supertrait-indirect.rs:11:1
    |
-LL | trait C: B { }
-   | ^^^^^^^^^^
-note: ...which requires computing the super traits of `C`...
+note: ...which requires computing the super predicates of `C`...
   --> $DIR/cycle-trait-supertrait-indirect.rs:11:10
    |
 LL | trait C: B { }
    |          ^
    = note: ...which again requires computing the super predicates of `B`, completing the cycle
-note: cycle used when computing the super traits of `A`
+note: cycle used when computing the super predicates of `A`
   --> $DIR/cycle-trait-supertrait-indirect.rs:4:10
    |
 LL | trait A: B {
diff --git a/tests/ui/infinite/infinite-trait-alias-recursion.stderr b/tests/ui/infinite/infinite-trait-alias-recursion.stderr
index b925b3b018c..683987b4943 100644
--- a/tests/ui/infinite/infinite-trait-alias-recursion.stderr
+++ b/tests/ui/infinite/infinite-trait-alias-recursion.stderr
@@ -1,30 +1,15 @@
 error[E0391]: cycle detected when computing the super predicates of `T1`
-  --> $DIR/infinite-trait-alias-recursion.rs:3:1
-   |
-LL | trait T1 = T2;
-   | ^^^^^^^^
-   |
-note: ...which requires computing the super traits of `T1`...
   --> $DIR/infinite-trait-alias-recursion.rs:3:12
    |
 LL | trait T1 = T2;
    |            ^^
-note: ...which requires computing the super predicates of `T2`...
-  --> $DIR/infinite-trait-alias-recursion.rs:6:1
    |
-LL | trait T2 = T3;
-   | ^^^^^^^^
-note: ...which requires computing the super traits of `T2`...
+note: ...which requires computing the super predicates of `T2`...
   --> $DIR/infinite-trait-alias-recursion.rs:6:12
    |
 LL | trait T2 = T3;
    |            ^^
 note: ...which requires computing the super predicates of `T3`...
-  --> $DIR/infinite-trait-alias-recursion.rs:8:1
-   |
-LL | trait T3 = T1 + T3;
-   | ^^^^^^^^
-note: ...which requires computing the super traits of `T3`...
   --> $DIR/infinite-trait-alias-recursion.rs:8:12
    |
 LL | trait T3 = T1 + T3;
diff --git a/tests/ui/issues/issue-12511.stderr b/tests/ui/issues/issue-12511.stderr
index 789a1141c04..558aad10946 100644
--- a/tests/ui/issues/issue-12511.stderr
+++ b/tests/ui/issues/issue-12511.stderr
@@ -1,20 +1,10 @@
 error[E0391]: cycle detected when computing the super predicates of `T1`
-  --> $DIR/issue-12511.rs:1:1
-   |
-LL | trait T1 : T2 {
-   | ^^^^^^^^^^^^^
-   |
-note: ...which requires computing the super traits of `T1`...
   --> $DIR/issue-12511.rs:1:12
    |
 LL | trait T1 : T2 {
    |            ^^
-note: ...which requires computing the super predicates of `T2`...
-  --> $DIR/issue-12511.rs:5:1
    |
-LL | trait T2 : T1 {
-   | ^^^^^^^^^^^^^
-note: ...which requires computing the super traits of `T2`...
+note: ...which requires computing the super predicates of `T2`...
   --> $DIR/issue-12511.rs:5:12
    |
 LL | trait T2 : T1 {
diff --git a/tests/ui/issues/issue-20772.stderr b/tests/ui/issues/issue-20772.stderr
index 22b9f5bd4cb..416fd8c062f 100644
--- a/tests/ui/issues/issue-20772.stderr
+++ b/tests/ui/issues/issue-20772.stderr
@@ -5,7 +5,7 @@ LL | trait T : Iterator<Item=Self::Item>
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: ...which immediately requires computing the super traits of `T` with associated type name `Item` again
-note: cycle used when computing the super traits of `T`
+note: cycle used when computing the super predicates of `T`
   --> $DIR/issue-20772.rs:1:1
    |
 LL | trait T : Iterator<Item=Self::Item>
diff --git a/tests/ui/lint/unused/trait-alias-supertrait.rs b/tests/ui/lint/unused/trait-alias-supertrait.rs
new file mode 100644
index 00000000000..46f00c06bf1
--- /dev/null
+++ b/tests/ui/lint/unused/trait-alias-supertrait.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+// Make sure that we only consider *Self* supertrait predicates
+// in the `unused_must_use` lint.
+
+#![feature(trait_alias)]
+#![deny(unused_must_use)]
+
+trait Foo<T> = Sized where T: Iterator;
+
+fn test<T: Iterator>() -> impl Foo<T> {}
+
+fn main() {
+    test::<std::iter::Once<()>>();
+}
diff --git a/tests/ui/traits/alias/dont-elaborate-non-self.rs b/tests/ui/traits/alias/dont-elaborate-non-self.rs
new file mode 100644
index 00000000000..4f9eaacb8ed
--- /dev/null
+++ b/tests/ui/traits/alias/dont-elaborate-non-self.rs
@@ -0,0 +1,10 @@
+#![feature(trait_alias)]
+
+use std::future::Future;
+
+trait F<Fut: Future<Output = usize>> = Fn() -> Fut;
+
+fn f<Fut>(a: dyn F<Fut>) {}
+//~^ ERROR the size for values of type `(dyn Fn() -> Fut + 'static)` cannot be known at compilation time
+
+fn main() {}
diff --git a/tests/ui/traits/alias/dont-elaborate-non-self.stderr b/tests/ui/traits/alias/dont-elaborate-non-self.stderr
new file mode 100644
index 00000000000..247a4f81280
--- /dev/null
+++ b/tests/ui/traits/alias/dont-elaborate-non-self.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the size for values of type `(dyn Fn() -> Fut + 'static)` cannot be known at compilation time
+  --> $DIR/dont-elaborate-non-self.rs:7:11
+   |
+LL | fn f<Fut>(a: dyn F<Fut>) {}
+   |           ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Fn() -> Fut + 'static)`
+   = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL | fn f<Fut>(a: impl F<Fut>) {}
+   |              ~~~~
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn f<Fut>(a: &dyn F<Fut>) {}
+   |              +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs
new file mode 100644
index 00000000000..4a5e445d1ef
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs
@@ -0,0 +1,33 @@
+#![feature(trait_upcasting)]
+#![feature(trait_alias)]
+
+// Although we *elaborate* `T: Alias` to `i32: B`, we should
+// not consider `B` to be a supertrait of the type.
+trait Alias = A where i32: B;
+
+trait A {}
+
+trait B {
+    fn test(&self);
+}
+
+trait C: Alias {}
+
+impl A for () {}
+
+impl C for () {}
+
+impl B for i32 {
+    fn test(&self) {
+        println!("hi {self}");
+    }
+}
+
+fn test(x: &dyn C) -> &dyn B {
+    x
+    //~^ ERROR mismatched types
+}
+
+fn main() {
+    let x: &dyn C = &();
+}
diff --git a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr
new file mode 100644
index 00000000000..5574a032089
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/alias-where-clause-isnt-supertrait.rs:27:5
+   |
+LL | fn test(x: &dyn C) -> &dyn B {
+   |                       ------ expected `&dyn B` because of return type
+LL |     x
+   |     ^ expected trait `B`, found trait `C`
+   |
+   = note: expected reference `&dyn B`
+              found reference `&dyn C`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
index 15faab16abe..ca98e183150 100644
--- a/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
+++ b/tests/ui/traits/trait-upcasting/cyclic-trait-resolution.stderr
@@ -1,15 +1,10 @@
 error[E0391]: cycle detected when computing the super predicates of `A`
-  --> $DIR/cyclic-trait-resolution.rs:1:1
-   |
-LL | trait A: B + A {}
-   | ^^^^^^^^^^^^^^
-   |
-note: ...which requires computing the super traits of `A`...
   --> $DIR/cyclic-trait-resolution.rs:1:14
    |
 LL | trait A: B + A {}
    |              ^
-   = note: ...which again requires computing the super predicates of `A`, completing the cycle
+   |
+   = note: ...which immediately requires computing the super predicates of `A` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/cyclic-trait-resolution.rs:1:1
    |