about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-02 06:36:44 +0000
committerbors <bors@rust-lang.org>2023-05-02 06:36:44 +0000
commit7b99493492ad59c7a44c65373558175db42b4151 (patch)
tree3175b32e64b2e498d623f3830be4faabd89ad892 /compiler/rustc_hir_analysis/src
parent5133e154590991203c84702ef59482f729b19bbf (diff)
parent2e3373c231fdd7ce607acd2339bfee501322e8c6 (diff)
downloadrust-7b99493492ad59c7a44c65373558175db42b4151.tar.gz
rust-7b99493492ad59c7a44c65373558175db42b4151.zip
Auto merge of #111089 - Dylan-DPC:rollup-b8oj6du, r=Dylan-DPC
Rollup of 7 pull requests

Successful merges:

 - #105076 (Refactor core::char::EscapeDefault and co. structures)
 - #108161 (Add `ConstParamTy` trait)
 - #108668 (Stabilize debugger_visualizer)
 - #110512 (Fix elaboration with associated type bounds)
 - #110895 (Remove `all` in target_thread_local cfg)
 - #110955 (uplift `clippy::clone_double_ref` as `suspicious_double_ref_op`)
 - #111048 (Mark`feature(return_position_impl_trait_in_trait)` and`feature(async_fn_in_trait)` as not incomplete)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs70
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs255
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs105
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs3
6 files changed, 267 insertions, 180 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 709dea43d84..6cb008bc5f8 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -56,6 +56,9 @@ use std::slice;
 #[derive(Debug)]
 pub struct PathSeg(pub DefId, pub usize);
 
+#[derive(Copy, Clone, Debug)]
+pub struct OnlySelfBounds(pub bool);
+
 pub trait AstConv<'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx>;
 
@@ -670,6 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         args: &GenericArgs<'_>,
         infer_args: bool,
         self_ty: Ty<'tcx>,
+        only_self_bounds: OnlySelfBounds,
     ) -> GenericArgCountResult {
         let (substs, arg_count) = self.create_substs_for_ast_path(
             trait_ref_span,
@@ -706,6 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 &mut dup_bindings,
                 binding_span.unwrap_or(binding.span),
                 constness,
+                only_self_bounds,
             );
             // Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
         }
@@ -741,6 +746,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
         speculative: bool,
+        only_self_bounds: OnlySelfBounds,
     ) -> GenericArgCountResult {
         let hir_id = trait_ref.hir_ref_id;
         let binding_span = None;
@@ -766,6 +772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             args,
             infer_args,
             self_ty,
+            only_self_bounds,
         )
     }
 
@@ -777,6 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         args: &GenericArgs<'_>,
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
+        only_self_bounds: OnlySelfBounds,
     ) {
         let binding_span = Some(span);
         let constness = ty::BoundConstness::NotConst;
@@ -799,6 +807,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             args,
             infer_args,
             self_ty,
+            only_self_bounds,
         );
     }
 
@@ -947,6 +956,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         ast_bounds: I,
         bounds: &mut Bounds<'tcx>,
         bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
+        only_self_bounds: OnlySelfBounds,
     ) {
         for ast_bound in ast_bounds {
             match ast_bound {
@@ -964,11 +974,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         param_ty,
                         bounds,
                         false,
+                        only_self_bounds,
                     );
                 }
                 &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => {
                     self.instantiate_lang_item_trait_ref(
-                        lang_item, span, hir_id, args, param_ty, bounds,
+                        lang_item,
+                        span,
+                        hir_id,
+                        args,
+                        param_ty,
+                        bounds,
+                        only_self_bounds,
                     );
                 }
                 hir::GenericBound::Outlives(lifetime) => {
@@ -1006,8 +1023,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: &[hir::GenericBound<'_>],
+        only_self_bounds: OnlySelfBounds,
     ) -> Bounds<'tcx> {
-        self.compute_bounds_inner(param_ty, ast_bounds)
+        let mut bounds = Bounds::default();
+        self.add_bounds(
+            param_ty,
+            ast_bounds.iter(),
+            &mut bounds,
+            ty::List::empty(),
+            only_self_bounds,
+        );
+        debug!(?bounds);
+
+        bounds
     }
 
     /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
@@ -1029,17 +1057,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
-        self.compute_bounds_inner(param_ty, &result)
-    }
-
-    fn compute_bounds_inner(
-        &self,
-        param_ty: Ty<'tcx>,
-        ast_bounds: &[hir::GenericBound<'_>],
-    ) -> Bounds<'tcx> {
         let mut bounds = Bounds::default();
-
-        self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty());
+        self.add_bounds(
+            param_ty,
+            result.iter(),
+            &mut bounds,
+            ty::List::empty(),
+            OnlySelfBounds(true),
+        );
         debug!(?bounds);
 
         bounds
@@ -1062,6 +1087,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         dup_bindings: &mut FxHashMap<DefId, Span>,
         path_span: Span,
         constness: ty::BoundConstness,
+        only_self_bounds: OnlySelfBounds,
     ) -> Result<(), ErrorGuaranteed> {
         // Given something like `U: SomeTrait<T = X>`, we want to produce a
         // predicate like `<U as SomeTrait>::T = X`. This is somewhat
@@ -1361,8 +1387,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 //
                 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
                 // parameter to have a skipped binder.
-                let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
-                self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
+                //
+                // NOTE: If `only_self_bounds` is true, do NOT expand this associated
+                // type bound into a trait predicate, since we only want to add predicates
+                // for the `Self` type.
+                if !only_self_bounds.0 {
+                    let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
+                    self.add_bounds(
+                        param_ty,
+                        ast_bounds.iter(),
+                        bounds,
+                        projection_ty.bound_vars(),
+                        only_self_bounds,
+                    );
+                }
             }
         }
         Ok(())
@@ -1403,6 +1441,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 dummy_self,
                 &mut bounds,
                 false,
+                // FIXME: This should be `true`, but we don't really handle
+                // associated type bounds or type aliases in objects in a way
+                // that makes this meaningful, I think.
+                OnlySelfBounds(false),
             ) {
                 potential_assoc_types.extend(cur_potential_assoc_types);
             }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 611ce13b739..0f450ae67b7 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -1,9 +1,11 @@
 //! Check properties that are required by built-in traits and set
 //! up data structures required by type-checking/codegen.
 
-use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
+use crate::errors::{
+    ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem,
+};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{struct_span_err, MultiSpan};
+use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
@@ -14,9 +16,11 @@ use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
 use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
 use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt};
+use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::misc::{
-    type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason,
+    type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy,
+    ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
 };
 use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{self, ObligationCause};
@@ -27,6 +31,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
     Checker { tcx, trait_def_id }
         .check(lang_items.drop_trait(), visit_implementation_of_drop)
         .check(lang_items.copy_trait(), visit_implementation_of_copy)
+        .check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty)
         .check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
         .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn);
 }
@@ -83,110 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) {
         Ok(()) => {}
         Err(CopyImplementationError::InfringingFields(fields)) => {
-            let mut err = struct_span_err!(
-                tcx.sess,
-                span,
-                E0204,
-                "the trait `Copy` cannot be implemented for this type"
-            );
-
-            // We'll try to suggest constraining type parameters to fulfill the requirements of
-            // their `Copy` implementation.
-            let mut errors: BTreeMap<_, Vec<_>> = Default::default();
-            let mut bounds = vec![];
-
-            let mut seen_tys = FxHashSet::default();
-
-            for (field, ty, reason) in fields {
-                // Only report an error once per type.
-                if !seen_tys.insert(ty) {
-                    continue;
-                }
-
-                let field_span = tcx.def_span(field.did);
-                err.span_label(field_span, "this field does not implement `Copy`");
-
-                match reason {
-                    InfringingFieldsReason::Fulfill(fulfillment_errors) => {
-                        for error in fulfillment_errors {
-                            let error_predicate = error.obligation.predicate;
-                            // Only note if it's not the root obligation, otherwise it's trivial and
-                            // should be self-explanatory (i.e. a field literally doesn't implement Copy).
-
-                            // FIXME: This error could be more descriptive, especially if the error_predicate
-                            // contains a foreign type or if it's a deeply nested type...
-                            if error_predicate != error.root_obligation.predicate {
-                                errors
-                                    .entry((ty.to_string(), error_predicate.to_string()))
-                                    .or_default()
-                                    .push(error.obligation.cause.span);
-                            }
-                            if let ty::PredicateKind::Clause(ty::Clause::Trait(
-                                ty::TraitPredicate {
-                                    trait_ref,
-                                    polarity: ty::ImplPolarity::Positive,
-                                    ..
-                                },
-                            )) = error_predicate.kind().skip_binder()
-                            {
-                                let ty = trait_ref.self_ty();
-                                if let ty::Param(_) = ty.kind() {
-                                    bounds.push((
-                                        format!("{ty}"),
-                                        trait_ref.print_only_trait_path().to_string(),
-                                        Some(trait_ref.def_id),
-                                    ));
-                                }
-                            }
-                        }
-                    }
-                    InfringingFieldsReason::Regions(region_errors) => {
-                        for error in region_errors {
-                            let ty = ty.to_string();
-                            match error {
-                                RegionResolutionError::ConcreteFailure(origin, a, b) => {
-                                    let predicate = format!("{b}: {a}");
-                                    errors
-                                        .entry((ty.clone(), predicate.clone()))
-                                        .or_default()
-                                        .push(origin.span());
-                                    if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() {
-                                        bounds.push((b.to_string(), a.to_string(), None));
-                                    }
-                                }
-                                RegionResolutionError::GenericBoundFailure(origin, a, b) => {
-                                    let predicate = format!("{a}: {b}");
-                                    errors
-                                        .entry((ty.clone(), predicate.clone()))
-                                        .or_default()
-                                        .push(origin.span());
-                                    if let infer::region_constraints::GenericKind::Param(_) = a {
-                                        bounds.push((a.to_string(), b.to_string(), None));
-                                    }
-                                }
-                                _ => continue,
-                            }
-                        }
-                    }
-                }
-            }
-            for ((ty, error_predicate), spans) in errors {
-                let span: MultiSpan = spans.into();
-                err.span_note(
-                    span,
-                    &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
-                );
-            }
-            suggest_constraining_type_params(
-                tcx,
-                tcx.hir().get_generics(impl_did).expect("impls always have generics"),
-                &mut err,
-                bounds.iter().map(|(param, constraint, def_id)| {
-                    (param.as_str(), constraint.as_str(), *def_id)
-                }),
-                None,
-            );
-            err.emit();
+            infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span);
         }
         Err(CopyImplementationError::NotAnAdt) => {
             tcx.sess.emit_err(CopyImplOnNonAdt { span });
@@ -197,6 +99,29 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     }
 }
 
+fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
+    let self_type = tcx.type_of(impl_did).subst_identity();
+    assert!(!self_type.has_escaping_bound_vars());
+
+    let param_env = tcx.param_env(impl_did);
+
+    let span = match tcx.hir().expect_item(impl_did).expect_impl() {
+        hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return,
+        impl_ => impl_.self_ty.span,
+    };
+
+    let cause = traits::ObligationCause::misc(span, impl_did);
+    match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
+        Ok(()) => {}
+        Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
+            infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span);
+        }
+        Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
+            tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span });
+        }
+    }
+}
+
 fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
     debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
 
@@ -593,3 +518,119 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
 
     CoerceUnsizedInfo { custom_kind: kind }
 }
+
+fn infringing_fields_error(
+    tcx: TyCtxt<'_>,
+    fields: Vec<(&ty::FieldDef, Ty<'_>, InfringingFieldsReason<'_>)>,
+    lang_item: LangItem,
+    impl_did: LocalDefId,
+    impl_span: Span,
+) -> ErrorGuaranteed {
+    let trait_did = tcx.require_lang_item(lang_item, Some(impl_span));
+
+    let trait_name = tcx.def_path_str(trait_did);
+
+    let mut err = struct_span_err!(
+        tcx.sess,
+        impl_span,
+        E0204,
+        "the trait `{trait_name}` cannot be implemented for this type"
+    );
+
+    // We'll try to suggest constraining type parameters to fulfill the requirements of
+    // their `Copy` implementation.
+    let mut errors: BTreeMap<_, Vec<_>> = Default::default();
+    let mut bounds = vec![];
+
+    let mut seen_tys = FxHashSet::default();
+
+    for (field, ty, reason) in fields {
+        // Only report an error once per type.
+        if !seen_tys.insert(ty) {
+            continue;
+        }
+
+        let field_span = tcx.def_span(field.did);
+        err.span_label(field_span, format!("this field does not implement `{trait_name}`"));
+
+        match reason {
+            InfringingFieldsReason::Fulfill(fulfillment_errors) => {
+                for error in fulfillment_errors {
+                    let error_predicate = error.obligation.predicate;
+                    // Only note if it's not the root obligation, otherwise it's trivial and
+                    // should be self-explanatory (i.e. a field literally doesn't implement Copy).
+
+                    // FIXME: This error could be more descriptive, especially if the error_predicate
+                    // contains a foreign type or if it's a deeply nested type...
+                    if error_predicate != error.root_obligation.predicate {
+                        errors
+                            .entry((ty.to_string(), error_predicate.to_string()))
+                            .or_default()
+                            .push(error.obligation.cause.span);
+                    }
+                    if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+                        trait_ref,
+                        polarity: ty::ImplPolarity::Positive,
+                        ..
+                    })) = error_predicate.kind().skip_binder()
+                    {
+                        let ty = trait_ref.self_ty();
+                        if let ty::Param(_) = ty.kind() {
+                            bounds.push((
+                                format!("{ty}"),
+                                trait_ref.print_only_trait_path().to_string(),
+                                Some(trait_ref.def_id),
+                            ));
+                        }
+                    }
+                }
+            }
+            InfringingFieldsReason::Regions(region_errors) => {
+                for error in region_errors {
+                    let ty = ty.to_string();
+                    match error {
+                        RegionResolutionError::ConcreteFailure(origin, a, b) => {
+                            let predicate = format!("{b}: {a}");
+                            errors
+                                .entry((ty.clone(), predicate.clone()))
+                                .or_default()
+                                .push(origin.span());
+                            if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() {
+                                        bounds.push((b.to_string(), a.to_string(), None));
+                                    }
+                        }
+                        RegionResolutionError::GenericBoundFailure(origin, a, b) => {
+                            let predicate = format!("{a}: {b}");
+                            errors
+                                .entry((ty.clone(), predicate.clone()))
+                                .or_default()
+                                .push(origin.span());
+                            if let infer::region_constraints::GenericKind::Param(_) = a {
+                                bounds.push((a.to_string(), b.to_string(), None));
+                            }
+                        }
+                        _ => continue,
+                    }
+                }
+            }
+        }
+    }
+    for ((ty, error_predicate), spans) in errors {
+        let span: MultiSpan = spans.into();
+        err.span_note(
+            span,
+            format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"),
+        );
+    }
+    suggest_constraining_type_params(
+        tcx,
+        tcx.hir().get_generics(impl_did).expect("impls always have generics"),
+        &mut err,
+        bounds
+            .iter()
+            .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)),
+        None,
+    );
+
+    err.emit()
+}
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 80d6bc7db9e..948b903e509 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -1,5 +1,5 @@
 use super::ItemCtxt;
-use crate::astconv::AstConv;
+use crate::astconv::{AstConv, OnlySelfBounds};
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::subst::InternalSubsts;
@@ -26,7 +26,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);
+    let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
     // Associated types are implicitly sized unless a `?Sized` bound is found
     icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
 
@@ -67,7 +67,7 @@ fn opaque_type_bounds<'tcx>(
 ) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
     ty::print::with_no_queries!({
         let icx = ItemCtxt::new(tcx, opaque_def_id);
-        let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
+        let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
         // 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);
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 8c414521b76..83470342a76 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1,4 +1,4 @@
-use crate::astconv::AstConv;
+use crate::astconv::{AstConv, OnlySelfBounds};
 use crate::bounds::Bounds;
 use crate::collect::ItemCtxt;
 use crate::constrained_generic_params as cgp;
@@ -14,9 +14,6 @@ use rustc_middle::ty::{GenericPredicates, ToPredicate};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
 
-#[derive(Debug)]
-struct OnlySelfBounds(bool);
-
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
 /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
 /// `Self: Trait` predicates for traits.
@@ -99,8 +96,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             | ItemKind::Struct(_, generics)
             | ItemKind::Union(_, generics) => generics,
 
-            ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => {
-                is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id()));
+            ItemKind::Trait(_, _, generics, self_bounds, ..)
+            | ItemKind::TraitAlias(generics, self_bounds) => {
+                is_trait = Some(self_bounds);
                 generics
             }
             ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
@@ -122,10 +120,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
 
     // Below we'll consider the bounds on the type parameters (including `Self`)
     // and the explicit where-clauses, but to get the full set of predicates
-    // 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.implied_predicates_of(def_id).predicates.iter().cloned());
+    // on a trait we must also consider the bounds that follow the trait's name,
+    // like `trait Foo: A + B + C`.
+    if let Some(self_bounds) = is_trait {
+        predicates.extend(
+            icx.astconv()
+                .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
+                .predicates(),
+        );
     }
 
     // In default impls, we can assume that the self type implements
@@ -225,7 +227,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                 }
 
                 let mut bounds = Bounds::default();
-                icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars);
+                icx.astconv().add_bounds(
+                    ty,
+                    bound_pred.bounds.iter(),
+                    &mut bounds,
+                    bound_vars,
+                    OnlySelfBounds(false),
+                );
                 predicates.extend(bounds.predicates());
             }
 
@@ -608,7 +616,7 @@ pub(super) fn implied_predicates_with_filter(
     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),
+            icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)),
             // Also include all where clause bounds
             icx.type_parameter_bounds_in_generics(
                 generics,
@@ -620,7 +628,7 @@ pub(super) fn implied_predicates_with_filter(
         ),
         PredicateFilter::SelfOnly => (
             // Convert the bounds that follow the colon (or equal in trait aliases)
-            icx.astconv().compute_bounds(self_param_ty, bounds),
+            icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)),
             // Include where clause bounds for `Self`
             icx.type_parameter_bounds_in_generics(
                 generics,
@@ -774,32 +782,35 @@ impl<'tcx> ItemCtxt<'tcx> {
         only_self_bounds: OnlySelfBounds,
         assoc_name: Option<Ident>,
     ) -> Vec<(ty::Predicate<'tcx>, Span)> {
-        ast_generics
-            .predicates
-            .iter()
-            .filter_map(|wp| match wp {
-                hir::WherePredicate::BoundPredicate(bp) => Some(bp),
-                _ => None,
-            })
-            .flat_map(|bp| {
-                let bt = if bp.is_param_bound(param_def_id.to_def_id()) {
-                    Some(ty)
-                } else if !only_self_bounds.0 {
-                    Some(self.to_ty(bp.bounded_ty))
-                } else {
-                    None
-                };
-                let bvars = self.tcx.late_bound_vars(bp.hir_id);
-
-                bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter(
-                    |(_, b, _)| match assoc_name {
-                        Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
-                        None => true,
-                    },
-                )
-            })
-            .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars))
-            .collect()
+        let mut bounds = Bounds::default();
+
+        for predicate in ast_generics.predicates {
+            let hir::WherePredicate::BoundPredicate(predicate) = predicate else {
+                continue;
+            };
+
+            let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
+                ty
+            } else if !only_self_bounds.0 {
+                self.to_ty(predicate.bounded_ty)
+            } else {
+                continue;
+            };
+
+            let bound_vars = self.tcx.late_bound_vars(predicate.hir_id);
+            self.astconv().add_bounds(
+                bound_ty,
+                predicate.bounds.iter().filter(|bound| {
+                    assoc_name
+                        .map_or(true, |assoc_name| self.bound_defines_assoc_item(bound, assoc_name))
+                }),
+                &mut bounds,
+                bound_vars,
+                only_self_bounds,
+            );
+        }
+
+        bounds.predicates().collect()
     }
 
     #[instrument(level = "trace", skip(self))]
@@ -817,19 +828,3 @@ impl<'tcx> ItemCtxt<'tcx> {
         }
     }
 }
-
-/// Converts a specific `GenericBound` from the AST into a set of
-/// predicates that apply to the self type. A vector is returned
-/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
-/// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar`
-/// and `<T as Bar>::X == i32`).
-fn predicates_from_bound<'tcx>(
-    astconv: &dyn AstConv<'tcx>,
-    param_ty: Ty<'tcx>,
-    bound: &'tcx hir::GenericBound<'tcx>,
-    bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
-) -> Vec<(ty::Predicate<'tcx>, Span)> {
-    let mut bounds = Bounds::default();
-    astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
-    bounds.predicates().collect()
-}
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index f82169dee98..25ad1bed763 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -108,6 +108,14 @@ pub struct CopyImplOnNonAdt {
 }
 
 #[derive(Diagnostic)]
+#[diag(hir_analysis_const_param_ty_impl_on_non_adt)]
+pub struct ConstParamTyImplOnNonAdt {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")]
 pub struct TraitObjectDeclaredWithNoTraits {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index a4b797f77f7..961457b7579 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -116,7 +116,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode,
 
 use std::ops::Not;
 
-use astconv::AstConv;
+use astconv::{AstConv, OnlySelfBounds};
 use bounds::Bounds;
 
 fluent_messages! { "../messages.ftl" }
@@ -531,6 +531,7 @@ pub fn hir_trait_to_predicates<'tcx>(
         self_ty,
         &mut bounds,
         true,
+        OnlySelfBounds(false),
     );
 
     bounds