about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs183
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs54
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs83
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs38
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs1
13 files changed, 310 insertions, 119 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index c6942b0f456..3067e2d0b71 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -1,12 +1,15 @@
-use rustc_data_structures::fx::FxIndexMap;
+use std::ops::ControlFlow;
+
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::{self as ty, Ty};
+use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
-use rustc_span::{ErrorGuaranteed, Span};
+use rustc_span::{ErrorGuaranteed, Span, Symbol};
 use rustc_trait_selection::traits;
+use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 use smallvec::SmallVec;
 
 use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
@@ -433,14 +436,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                 binding.kind
             {
                 let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
-                // Since the arguments passed to the alias type above may contain early-bound
-                // generic parameters, the instantiated type may contain some as well.
-                // Therefore wrap it in `EarlyBinder`.
-                // FIXME(fmease): Reject escaping late-bound vars.
-                tcx.feed_anon_const_type(
-                    anon_const.def_id,
-                    ty::EarlyBinder::bind(ty.skip_binder()),
-                );
+                let ty = check_assoc_const_binding_type(tcx, assoc_ident, ty, binding.hir_id);
+                tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
             }
 
             alias_ty
@@ -530,3 +527,167 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
         Ok(())
     }
 }
+
+/// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
+///
+/// FIXME(const_generics): This is a temporary and semi-artifical restriction until the
+/// arrival of *generic const generics*[^1].
+///
+/// It might actually be possible that we can already support early-bound generic params
+/// in such types if we just lifted some more checks in other places, too, for example
+/// inside [`ty::Const::from_anon_const`]. However, even if that were the case, we should
+/// probably gate this behind another feature flag.
+///
+/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
+fn check_assoc_const_binding_type<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    assoc_const: Ident,
+    ty: ty::Binder<'tcx, Ty<'tcx>>,
+    hir_id: hir::HirId,
+) -> Ty<'tcx> {
+    // We can't perform the checks for early-bound params during name resolution unlike E0770
+    // because this information depends on *type* resolution.
+    // We can't perform these checks in `resolve_bound_vars` either for the same reason.
+    // Consider the trait ref `for<'a> Trait<'a, C = { &0 }>`. We need to know the fully
+    // resolved type of `Trait::C` in order to know if it references `'a` or not.
+
+    let ty = ty.skip_binder();
+    if !ty.has_param() && !ty.has_escaping_bound_vars() {
+        return ty;
+    }
+
+    let mut collector = GenericParamAndBoundVarCollector {
+        tcx,
+        params: Default::default(),
+        vars: Default::default(),
+        depth: ty::INNERMOST,
+    };
+    let mut guar = ty.visit_with(&mut collector).break_value();
+
+    let ty_note = ty
+        .make_suggestable(tcx, false)
+        .map(|ty| crate::errors::TyOfAssocConstBindingNote { assoc_const, ty });
+
+    let enclosing_item_owner_id = tcx
+        .hir()
+        .parent_owner_iter(hir_id)
+        .find_map(|(owner_id, parent)| parent.generics().map(|_| owner_id))
+        .unwrap();
+    let generics = tcx.generics_of(enclosing_item_owner_id);
+    for index in collector.params {
+        let param = generics.param_at(index as _, tcx);
+        let is_self_param = param.name == rustc_span::symbol::kw::SelfUpper;
+        guar.get_or_insert(tcx.dcx().emit_err(crate::errors::ParamInTyOfAssocConstBinding {
+            span: assoc_const.span,
+            assoc_const,
+            param_name: param.name,
+            param_def_kind: tcx.def_descr(param.def_id),
+            param_category: if is_self_param {
+                "self"
+            } else if param.kind.is_synthetic() {
+                "synthetic"
+            } else {
+                "normal"
+            },
+            param_defined_here_label:
+                (!is_self_param).then(|| tcx.def_ident_span(param.def_id).unwrap()),
+            ty_note,
+        }));
+    }
+    for (var_def_id, var_name) in collector.vars {
+        guar.get_or_insert(tcx.dcx().emit_err(
+            crate::errors::EscapingBoundVarInTyOfAssocConstBinding {
+                span: assoc_const.span,
+                assoc_const,
+                var_name,
+                var_def_kind: tcx.def_descr(var_def_id),
+                var_defined_here_label: tcx.def_ident_span(var_def_id).unwrap(),
+                ty_note,
+            },
+        ));
+    }
+
+    let guar = guar.unwrap_or_else(|| bug!("failed to find gen params or bound vars in ty"));
+    Ty::new_error(tcx, guar)
+}
+
+struct GenericParamAndBoundVarCollector<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    params: FxIndexSet<u32>,
+    vars: FxIndexSet<(DefId, Symbol)>,
+    depth: ty::DebruijnIndex,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'tcx> {
+    type Result = ControlFlow<ErrorGuaranteed>;
+
+    fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
+        &mut self,
+        binder: &ty::Binder<'tcx, T>,
+    ) -> Self::Result {
+        self.depth.shift_in(1);
+        let result = binder.super_visit_with(self);
+        self.depth.shift_out(1);
+        result
+    }
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
+        match ty.kind() {
+            ty::Param(param) => {
+                self.params.insert(param.index);
+            }
+            ty::Bound(db, bt) if *db >= self.depth => {
+                self.vars.insert(match bt.kind {
+                    ty::BoundTyKind::Param(def_id, name) => (def_id, name),
+                    ty::BoundTyKind::Anon => {
+                        let reported = self
+                            .tcx
+                            .dcx()
+                            .delayed_bug(format!("unexpected anon bound ty: {:?}", bt.var));
+                        return ControlFlow::Break(reported);
+                    }
+                });
+            }
+            _ if ty.has_param() || ty.has_bound_vars() => return ty.super_visit_with(self),
+            _ => {}
+        }
+        ControlFlow::Continue(())
+    }
+
+    fn visit_region(&mut self, re: ty::Region<'tcx>) -> Self::Result {
+        match re.kind() {
+            ty::ReEarlyParam(param) => {
+                self.params.insert(param.index);
+            }
+            ty::ReBound(db, br) if db >= self.depth => {
+                self.vars.insert(match br.kind {
+                    ty::BrNamed(def_id, name) => (def_id, name),
+                    ty::BrAnon | ty::BrEnv => {
+                        let guar = self
+                            .tcx
+                            .dcx()
+                            .delayed_bug(format!("unexpected bound region kind: {:?}", br.kind));
+                        return ControlFlow::Break(guar);
+                    }
+                });
+            }
+            _ => {}
+        }
+        ControlFlow::Continue(())
+    }
+
+    fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result {
+        match ct.kind() {
+            ty::ConstKind::Param(param) => {
+                self.params.insert(param.index);
+            }
+            ty::ConstKind::Bound(db, ty::BoundVar { .. }) if db >= self.depth => {
+                let guar = self.tcx.dcx().delayed_bug("unexpected escaping late-bound const var");
+                return ControlFlow::Break(guar);
+            }
+            _ if ct.has_param() || ct.has_bound_vars() => return ct.super_visit_with(self),
+            _ => {}
+        }
+        ControlFlow::Continue(())
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 428eea2f686..42e303c10ea 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -16,7 +16,7 @@ use rustc_middle::ty::{
     self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt,
 };
 use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
-use rustc_span::symbol::kw;
+use rustc_span::symbol::{kw, sym};
 use smallvec::SmallVec;
 
 /// Report an error that a generic argument did not match the generic parameter that was
@@ -41,9 +41,11 @@ fn generic_arg_mismatch_err(
     if let GenericParamDefKind::Const { .. } = param.kind {
         if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) {
             err.help("const arguments cannot yet be inferred with `_`");
-            if sess.is_nightly_build() {
-                err.help("add `#![feature(generic_arg_infer)]` to the crate attributes to enable");
-            }
+            tcx.disabled_nightly_features(
+                &mut err,
+                param.def_id.as_local().map(|local| tcx.local_def_id_to_hir_id(local)),
+                [(String::new(), sym::generic_arg_infer)],
+            );
         }
     }
 
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index ec9e928ce59..d2fdff6177e 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1305,7 +1305,7 @@ fn compare_number_of_generics<'tcx>(
                     .iter()
                     .filter(|p| match p.kind {
                         hir::GenericParamKind::Lifetime {
-                            kind: hir::LifetimeParamKind::Elided,
+                            kind: hir::LifetimeParamKind::Elided(_),
                         } => {
                             // A fn can have an arbitrary number of extra elided lifetimes for the
                             // same signature.
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 35755a46df3..07054c184f4 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -441,7 +441,7 @@ pub fn check_intrinsic_type(
 
             sym::ptr_guaranteed_cmp => (
                 1,
-                0,
+                1,
                 vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
                 tcx.types.u8,
             ),
@@ -579,7 +579,7 @@ pub fn check_intrinsic_type(
 
             sym::is_val_statically_known => (1, 1, vec![param(0)], tcx.types.bool),
 
-            sym::const_eval_select => (4, 0, vec![param(0), param(1), param(2)], param(3)),
+            sym::const_eval_select => (4, 1, vec![param(0), param(1), param(2)], param(3)),
 
             sym::vtable_size | sym::vtable_align => {
                 (0, 0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize)
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 22afddad633..8760901b71b 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -291,12 +291,16 @@ fn default_body_is_unstable(
         reason: reason_str,
     });
 
+    let inject_span = item_did
+        .as_local()
+        .and_then(|id| tcx.crate_level_attribute_injection_span(tcx.local_def_id_to_hir_id(id)));
     rustc_session::parse::add_feature_diagnostics_for_issue(
         &mut err,
         &tcx.sess,
         feature,
         rustc_feature::GateIssue::Library(issue),
         false,
+        inject_span,
     );
 
     err.emit();
@@ -427,7 +431,7 @@ fn fn_sig_suggestion<'tcx>(
 
     let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
         output = if let ty::Alias(_, alias_ty) = *output.kind() {
-            tcx.explicit_item_bounds(alias_ty.def_id)
+            tcx.explicit_item_super_predicates(alias_ty.def_id)
                 .iter_instantiated_copied(tcx, alias_ty.args)
                 .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
                 .unwrap_or_else(|| {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index f5250045344..b5377e40bfd 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -196,7 +196,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorG
         hir::OwnerNode::TraitItem(item) => check_trait_item(tcx, item),
         hir::OwnerNode::ImplItem(item) => check_impl_item(tcx, item),
         hir::OwnerNode::ForeignItem(item) => check_foreign_item(tcx, item),
-        hir::OwnerNode::AssocOpaqueTy(..) => unreachable!(),
+        hir::OwnerNode::Synthetic => unreachable!(),
     };
 
     if let Some(generics) = node.generics() {
@@ -999,9 +999,14 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
                     // Implments `ConstParamTy`, suggest adding the feature to enable.
                     Ok(..) => true,
                 };
-                if may_suggest_feature && tcx.sess.is_nightly_build() {
-                    diag.help(
-                        "add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
+                if may_suggest_feature {
+                    tcx.disabled_nightly_features(
+                        &mut diag,
+                        Some(param.hir_id),
+                        [(
+                            " more complex and user defined types".to_string(),
+                            sym::adt_const_params,
+                        )],
                     );
                 }
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 5cd6862786b..bd56275b159 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -61,6 +61,9 @@ pub fn provide(providers: &mut Providers) {
         type_alias_is_lazy: type_of::type_alias_is_lazy,
         item_bounds: item_bounds::item_bounds,
         explicit_item_bounds: item_bounds::explicit_item_bounds,
+        item_super_predicates: item_bounds::item_super_predicates,
+        explicit_item_super_predicates: item_bounds::explicit_item_super_predicates,
+        item_non_self_assumptions: item_bounds::item_non_self_assumptions,
         generics_of: generics_of::generics_of,
         predicates_of: predicates_of::predicates_of,
         predicates_defined_on,
@@ -633,7 +636,9 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
             tcx.ensure().generics_of(def_id);
             tcx.ensure().predicates_of(def_id);
             tcx.ensure().explicit_item_bounds(def_id);
+            tcx.ensure().explicit_item_super_predicates(def_id);
             tcx.ensure().item_bounds(def_id);
+            tcx.ensure().item_super_predicates(def_id);
         }
 
         hir::ItemKind::TyAlias(..) => {
@@ -689,6 +694,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
 
         hir::TraitItemKind::Type(_, Some(_)) => {
             tcx.ensure().item_bounds(def_id);
+            tcx.ensure().item_super_predicates(def_id);
             tcx.ensure().type_of(def_id);
             // Account for `type T = _;`.
             let mut visitor = HirPlaceholderCollector::default();
@@ -698,6 +704,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
 
         hir::TraitItemKind::Type(_, None) => {
             tcx.ensure().item_bounds(def_id);
+            tcx.ensure().item_super_predicates(def_id);
             // #74612: Visit and try to find bad placeholders
             // even if there is no concrete type.
             let mut visitor = HirPlaceholderCollector::default();
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index c86788db988..bc6abc53cad 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -508,29 +508,9 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
         visitor.has_late_bound_regions
     }
 
-    match node {
-        Node::TraitItem(item) => match &item.kind {
-            hir::TraitItemKind::Fn(sig, _) => has_late_bound_regions(tcx, item.generics, sig.decl),
-            _ => None,
-        },
-        Node::ImplItem(item) => match &item.kind {
-            hir::ImplItemKind::Fn(sig, _) => has_late_bound_regions(tcx, item.generics, sig.decl),
-            _ => None,
-        },
-        Node::ForeignItem(item) => match item.kind {
-            hir::ForeignItemKind::Fn(fn_decl, _, generics) => {
-                has_late_bound_regions(tcx, generics, fn_decl)
-            }
-            _ => None,
-        },
-        Node::Item(item) => match &item.kind {
-            hir::ItemKind::Fn(sig, .., generics, _) => {
-                has_late_bound_regions(tcx, generics, sig.decl)
-            }
-            _ => None,
-        },
-        _ => None,
-    }
+    let decl = node.fn_decl()?;
+    let generics = node.generics()?;
+    has_late_bound_regions(tcx, generics, decl)
 }
 
 struct AnonConstInParamTyDetector {
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 78c390d0924..f914f1f9b17 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -1,5 +1,6 @@
 use super::ItemCtxt;
 use crate::astconv::{AstConv, PredicateFilter};
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::GenericArgs;
@@ -19,6 +20,7 @@ fn associated_type_bounds<'tcx>(
     assoc_item_def_id: LocalDefId,
     ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     span: Span,
+    filter: PredicateFilter,
 ) -> &'tcx [(ty::Clause<'tcx>, Span)] {
     let item_ty = Ty::new_projection(
         tcx,
@@ -27,7 +29,7 @@ fn associated_type_bounds<'tcx>(
     );
 
     let icx = ItemCtxt::new(tcx, assoc_item_def_id);
-    let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
+    let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, filter);
     // Associated types are implicitly sized unless a `?Sized` bound is found
     icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
 
@@ -63,10 +65,11 @@ fn opaque_type_bounds<'tcx>(
     ast_bounds: &'tcx [hir::GenericBound<'tcx>],
     item_ty: Ty<'tcx>,
     span: Span,
+    filter: PredicateFilter,
 ) -> &'tcx [(ty::Clause<'tcx>, Span)] {
     ty::print::with_reduced_queries!({
         let icx = ItemCtxt::new(tcx, opaque_def_id);
-        let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
+        let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, filter);
         // Opaque types are implicitly sized unless a `?Sized` bound is found
         icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
         debug!(?bounds);
@@ -79,6 +82,21 @@ pub(super) fn explicit_item_bounds(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
 ) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
+    explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::All)
+}
+
+pub(super) fn explicit_item_super_predicates(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
+    explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::SelfOnly)
+}
+
+pub(super) fn explicit_item_bounds_with_filter(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+    filter: PredicateFilter,
+) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
     match tcx.opt_rpitit_info(def_id.to_def_id()) {
         // RPITIT's bounds are the same as opaque type bounds, but with
         // a projection self type.
@@ -95,6 +113,7 @@ pub(super) fn explicit_item_bounds(
                     ty::GenericArgs::identity_for_item(tcx, def_id),
                 ),
                 item.span,
+                filter,
             ));
         }
         Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
@@ -109,7 +128,7 @@ pub(super) fn explicit_item_bounds(
             kind: hir::TraitItemKind::Type(bounds, _),
             span,
             ..
-        }) => associated_type_bounds(tcx, def_id, bounds, *span),
+        }) => associated_type_bounds(tcx, def_id, bounds, *span, filter),
         hir::Node::Item(hir::Item {
             kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait: false, .. }),
             span,
@@ -117,7 +136,7 @@ pub(super) fn explicit_item_bounds(
         }) => {
             let args = GenericArgs::identity_for_item(tcx, def_id);
             let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
-            opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
+            opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
         }
         // Since RPITITs are astconv'd as projections in `ast_ty_to_ty`, when we're asking
         // for the item bounds of the *opaques* in a trait's default method signature, we
@@ -135,7 +154,7 @@ pub(super) fn explicit_item_bounds(
             let args = GenericArgs::identity_for_item(tcx, def_id);
             let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
             tcx.arena.alloc_slice(
-                &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
+                &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
                     .to_vec()
                     .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
             )
@@ -155,6 +174,31 @@ pub(super) fn item_bounds(
     })
 }
 
+pub(super) fn item_super_predicates(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
+    tcx.explicit_item_super_predicates(def_id).map_bound(|bounds| {
+        tcx.mk_clauses_from_iter(
+            util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)).filter_only_self(),
+        )
+    })
+}
+
+pub(super) fn item_non_self_assumptions(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
+    let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect();
+    let own_bounds: FxIndexSet<_> =
+        tcx.item_super_predicates(def_id).skip_binder().iter().collect();
+    if all_bounds.len() == own_bounds.len() {
+        ty::EarlyBinder::bind(ty::List::empty())
+    } else {
+        ty::EarlyBinder::bind(tcx.mk_clauses_from_iter(all_bounds.difference(&own_bounds).copied()))
+    }
+}
+
 struct AssocTyToOpaque<'tcx> {
     tcx: TyCtxt<'tcx>,
     fn_def_id: DefId,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 6aae4aa21b8..66c9fb93500 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -123,43 +123,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     // Preserving the order of insertion is important here so as not to break UI tests.
     let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
 
-    let ast_generics = match node {
-        Node::TraitItem(item) => item.generics,
-
-        Node::ImplItem(item) => item.generics,
-
-        Node::Item(item) => match item.kind {
+    let ast_generics = node.generics().unwrap_or(NO_GENERICS);
+    if let Node::Item(item) = node {
+        match item.kind {
             ItemKind::Impl(impl_) => {
                 if impl_.defaultness.is_default() {
                     is_default_impl_trait = tcx
                         .impl_trait_ref(def_id)
                         .map(|t| ty::Binder::dummy(t.instantiate_identity()));
                 }
-                impl_.generics
             }
-            ItemKind::Fn(.., generics, _)
-            | ItemKind::TyAlias(_, generics)
-            | ItemKind::Const(_, generics, _)
-            | ItemKind::Enum(_, generics)
-            | ItemKind::Struct(_, generics)
-            | ItemKind::Union(_, generics) => generics,
-
-            ItemKind::Trait(_, _, generics, self_bounds, ..)
-            | ItemKind::TraitAlias(generics, self_bounds) => {
+
+            ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
                 is_trait = Some(self_bounds);
-                generics
             }
-            ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
-            _ => NO_GENERICS,
-        },
-
-        Node::ForeignItem(item) => match item.kind {
-            ForeignItemKind::Static(..) => NO_GENERICS,
-            ForeignItemKind::Fn(_, _, generics) => generics,
-            ForeignItemKind::Type => NO_GENERICS,
-        },
-
-        _ => NO_GENERICS,
+            _ => {}
+        }
     };
 
     let generics = tcx.generics_of(def_id);
@@ -703,45 +682,17 @@ pub(super) fn type_param_predicates(
     let mut extend = None;
 
     let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
-    let ast_generics = match tcx.hir_node(item_hir_id) {
-        Node::TraitItem(item) => item.generics,
-
-        Node::ImplItem(item) => item.generics,
-
-        Node::Item(item) => {
-            match item.kind {
-                ItemKind::Fn(.., generics, _)
-                | ItemKind::Impl(&hir::Impl { generics, .. })
-                | ItemKind::TyAlias(_, generics)
-                | ItemKind::Const(_, generics, _)
-                | ItemKind::OpaqueTy(&OpaqueTy {
-                    generics,
-                    origin: hir::OpaqueTyOrigin::TyAlias { .. },
-                    ..
-                })
-                | ItemKind::Enum(_, generics)
-                | ItemKind::Struct(_, generics)
-                | ItemKind::Union(_, generics) => generics,
-                ItemKind::Trait(_, _, generics, ..) => {
-                    // Implied `Self: Trait` and supertrait bounds.
-                    if param_id == item_hir_id {
-                        let identity_trait_ref =
-                            ty::TraitRef::identity(tcx, item_def_id.to_def_id());
-                        extend = Some((identity_trait_ref.to_predicate(tcx), item.span));
-                    }
-                    generics
-                }
-                _ => return result,
-            }
-        }
-
-        Node::ForeignItem(item) => match item.kind {
-            ForeignItemKind::Fn(_, _, generics) => generics,
-            _ => return result,
-        },
 
-        _ => return result,
-    };
+    let hir_node = tcx.hir_node(item_hir_id);
+    let Some(ast_generics) = hir_node.generics() else { return result };
+    if let Node::Item(item) = hir_node
+        && let ItemKind::Trait(..) = item.kind
+        // Implied `Self: Trait` and supertrait bounds.
+        && param_id == item_hir_id
+    {
+        let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id());
+        extend = Some((identity_trait_ref.to_predicate(tcx), item.span));
+    }
 
     let icx = ItemCtxt::new(tcx, item_def_id);
     let extra_predicates = extend.into_iter().chain(
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 d1da2fa0fdc..86b075a84a7 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -262,7 +262,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
             visitor.visit_impl_item(item)
         }
         hir::OwnerNode::Crate(_) => {}
-        hir::OwnerNode::AssocOpaqueTy(..) => unreachable!(),
+        hir::OwnerNode::Synthetic => unreachable!(),
     }
 
     let mut rl = ResolveBoundVars::default();
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 7bf87f444db..fb919714afd 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -295,6 +295,44 @@ pub struct AssocTypeBindingNotAllowed {
     pub fn_trait_expansion: Option<ParenthesizedFnTraitExpansion>,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_param_in_ty_of_assoc_const_binding)]
+pub(crate) struct ParamInTyOfAssocConstBinding<'tcx> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub assoc_const: Ident,
+    pub param_name: Symbol,
+    pub param_def_kind: &'static str,
+    pub param_category: &'static str,
+    #[label(hir_analysis_param_defined_here_label)]
+    pub param_defined_here_label: Option<Span>,
+    #[subdiagnostic]
+    pub ty_note: Option<TyOfAssocConstBindingNote<'tcx>>,
+}
+
+#[derive(Subdiagnostic, Clone, Copy)]
+#[note(hir_analysis_ty_of_assoc_const_binding_note)]
+pub(crate) struct TyOfAssocConstBindingNote<'tcx> {
+    pub assoc_const: Ident,
+    pub ty: Ty<'tcx>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_escaping_bound_var_in_ty_of_assoc_const_binding)]
+pub(crate) struct EscapingBoundVarInTyOfAssocConstBinding<'tcx> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub assoc_const: Ident,
+    pub var_name: Symbol,
+    pub var_def_kind: &'static str,
+    #[label(hir_analysis_var_defined_here_label)]
+    pub var_defined_here_label: Span,
+    #[subdiagnostic]
+    pub ty_note: Option<TyOfAssocConstBindingNote<'tcx>>,
+}
+
 #[derive(Subdiagnostic)]
 #[help(hir_analysis_parenthesized_fn_trait_expansion)]
 pub struct ParenthesizedFnTraitExpansion {
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 19ab2045cc5..5fe8d1fe586 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -68,7 +68,6 @@ This API is completely unstable and subject to change.
 #![feature(is_sorted)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(min_specialization))]
 #![feature(never_type)]
 #![feature(lazy_cell)]
 #![feature(slice_partition_dedup)]