summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/messages.ftl3
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs112
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs142
-rw-r--r--compiler/rustc_ast_passes/messages.ftl5
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs23
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs16
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0203.md10
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs69
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs33
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs69
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs62
15 files changed, 270 insertions, 316 deletions
diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index c6472fd45fa..370b15d2871 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -127,9 +127,6 @@ ast_lowering_misplaced_impl_trait =
     `impl Trait` is not allowed in {$position}
     .note = `impl Trait` is only allowed in arguments and return types of functions and methods
 
-ast_lowering_misplaced_relax_trait_bound =
-    `?Trait` bounds are only permitted at the point where a type parameter is declared
-
 ast_lowering_never_pattern_with_body =
     a never pattern is always unreachable
     .label = this will never be executed
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index b444324ef91..83f3a976e83 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -325,13 +325,6 @@ pub(crate) struct MisplacedDoubleDot {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering_misplaced_relax_trait_bound)]
-pub(crate) struct MisplacedRelaxTraitBound {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(ast_lowering_match_arm_with_no_body)]
 pub(crate) struct MatchArmWithNoBody {
     #[primary_span]
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index abd70c7517c..ddf01b69e7f 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -16,14 +16,11 @@ use smallvec::{SmallVec, smallvec};
 use thin_vec::ThinVec;
 use tracing::instrument;
 
-use super::errors::{
-    InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault,
-    UnionWithDefault,
-};
+use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault};
 use super::stability::{enabled_names, gate_unstable_abi};
 use super::{
     AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
-    ResolverAstLoweringExt,
+    RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt,
 };
 
 pub(super) struct ItemLowerer<'a, 'hir> {
@@ -435,6 +432,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     |this| {
                         let bounds = this.lower_param_bounds(
                             bounds,
+                            RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait),
                             ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
                         );
                         let items = this.arena.alloc_from_iter(
@@ -455,6 +453,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     |this| {
                         this.lower_param_bounds(
                             bounds,
+                            RelaxedBoundPolicy::Allowed,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
                         )
                     },
@@ -940,6 +939,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         hir::TraitItemKind::Type(
                             this.lower_param_bounds(
                                 bounds,
+                                RelaxedBoundPolicy::Allowed,
                                 ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
                             ),
                             ty,
@@ -1677,61 +1677,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
         assert!(self.impl_trait_defs.is_empty());
         assert!(self.impl_trait_bounds.is_empty());
 
-        // Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
-        // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
-        // these into hir when we lower thee where clauses), but this makes it quite difficult to
-        // keep track of the Span info. Now, `<dyn HirTyLowerer>::add_implicit_sized_bound`
-        // checks both param bounds and where clauses for `?Sized`.
-        for pred in &generics.where_clause.predicates {
-            let WherePredicateKind::BoundPredicate(bound_pred) = &pred.kind else {
-                continue;
-            };
-            let compute_is_param = || {
-                // Check if the where clause type is a plain type parameter.
-                match self
-                    .resolver
-                    .get_partial_res(bound_pred.bounded_ty.id)
-                    .and_then(|r| r.full_res())
-                {
-                    Some(Res::Def(DefKind::TyParam, def_id))
-                        if bound_pred.bound_generic_params.is_empty() =>
-                    {
-                        generics
-                            .params
-                            .iter()
-                            .any(|p| def_id == self.local_def_id(p.id).to_def_id())
-                    }
-                    // Either the `bounded_ty` is not a plain type parameter, or
-                    // it's not found in the generic type parameters list.
-                    _ => false,
-                }
-            };
-            // We only need to compute this once per `WherePredicate`, but don't
-            // need to compute this at all unless there is a Maybe bound.
-            let mut is_param: Option<bool> = None;
-            for bound in &bound_pred.bounds {
-                if !matches!(
-                    *bound,
-                    GenericBound::Trait(PolyTraitRef {
-                        modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
-                        ..
-                    })
-                ) {
-                    continue;
-                }
-                let is_param = *is_param.get_or_insert_with(compute_is_param);
-                if !is_param && !self.tcx.features().more_maybe_bounds() {
-                    self.tcx
-                        .sess
-                        .create_feature_err(
-                            MisplacedRelaxTraitBound { span: bound.span() },
-                            sym::more_maybe_bounds,
-                        )
-                        .emit();
-                }
-            }
-        }
-
         let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
         predicates.extend(generics.params.iter().filter_map(|param| {
             self.lower_generic_bound_predicate(
@@ -1741,6 +1686,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 &param.bounds,
                 param.colon_span,
                 generics.span,
+                RelaxedBoundPolicy::Allowed,
                 itctx,
                 PredicateOrigin::GenericParam,
             )
@@ -1750,7 +1696,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 .where_clause
                 .predicates
                 .iter()
-                .map(|predicate| self.lower_where_predicate(predicate)),
+                .map(|predicate| self.lower_where_predicate(predicate, &generics.params)),
         );
 
         let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
@@ -1827,6 +1773,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         bounds: &[GenericBound],
         colon_span: Option<Span>,
         parent_span: Span,
+        rbp: RelaxedBoundPolicy<'_>,
         itctx: ImplTraitContext,
         origin: PredicateOrigin,
     ) -> Option<hir::WherePredicate<'hir>> {
@@ -1835,7 +1782,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             return None;
         }
 
-        let bounds = self.lower_param_bounds(bounds, itctx);
+        let bounds = self.lower_param_bounds(bounds, rbp, itctx);
 
         let param_span = ident.span;
 
@@ -1887,7 +1834,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         Some(hir::WherePredicate { hir_id, span, kind })
     }
 
-    fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> {
+    fn lower_where_predicate(
+        &mut self,
+        pred: &WherePredicate,
+        params: &[ast::GenericParam],
+    ) -> hir::WherePredicate<'hir> {
         let hir_id = self.lower_node_id(pred.id);
         let span = self.lower_span(pred.span);
         self.lower_attrs(hir_id, &pred.attrs, span);
@@ -1896,17 +1847,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 bound_generic_params,
                 bounded_ty,
                 bounds,
-            }) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
-                bound_generic_params: self
-                    .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
-                bounded_ty: self
-                    .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
-                bounds: self.lower_param_bounds(
-                    bounds,
-                    ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
-                ),
-                origin: PredicateOrigin::WhereClause,
-            }),
+            }) => {
+                let rbp = if bound_generic_params.is_empty() {
+                    RelaxedBoundPolicy::AllowedIfOnTyParam(bounded_ty.id, params)
+                } else {
+                    RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::LateBoundVarsInScope)
+                };
+                hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
+                    bound_generic_params: self.lower_generic_params(
+                        bound_generic_params,
+                        hir::GenericParamSource::Binder,
+                    ),
+                    bounded_ty: self.lower_ty(
+                        bounded_ty,
+                        ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
+                    ),
+                    bounds: self.lower_param_bounds(
+                        bounds,
+                        rbp,
+                        ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
+                    ),
+                    origin: PredicateOrigin::WhereClause,
+                })
+            }
             WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => {
                 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
                     lifetime: self.lower_lifetime(
@@ -1916,6 +1879,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     ),
                     bounds: self.lower_param_bounds(
                         bounds,
+                        RelaxedBoundPolicy::Allowed,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Bound),
                     ),
                     in_where_clause: true,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 1c96a375035..533ee9bff54 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -53,8 +53,8 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
 use rustc_hir::lints::DelayedLint;
 use rustc_hir::{
-    self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem,
-    LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate,
+    self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
+    LifetimeSyntax, ParamName, TraitCandidate,
 };
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_macros::extension;
@@ -281,6 +281,24 @@ impl ResolverAstLowering {
     }
 }
 
+/// How relaxed bounds `?Trait` should be treated.
+///
+/// Relaxed bounds should only be allowed in places where we later
+/// (namely during HIR ty lowering) perform *sized elaboration*.
+#[derive(Clone, Copy, Debug)]
+enum RelaxedBoundPolicy<'a> {
+    Allowed,
+    AllowedIfOnTyParam(NodeId, &'a [ast::GenericParam]),
+    Forbidden(RelaxedBoundForbiddenReason),
+}
+
+#[derive(Clone, Copy, Debug)]
+enum RelaxedBoundForbiddenReason {
+    TraitObjectTy,
+    SuperTrait,
+    LateBoundVarsInScope,
+}
+
 /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
 /// and if so, what meaning it has.
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -1084,10 +1102,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
                     hir::AssocItemConstraintKind::Equality { term: err_ty.into() }
                 } else {
-                    // Desugar `AssocTy: Bounds` into an assoc type binding where the
-                    // later desugars into a trait predicate.
-                    let bounds = self.lower_param_bounds(bounds, itctx);
-
+                    // FIXME(#135229): These should be forbidden!
+                    let bounds =
+                        self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx);
                     hir::AssocItemConstraintKind::Bound { bounds }
                 }
             }
@@ -1216,6 +1233,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         span: t.span,
                         parens: ast::Parens::No,
                     },
+                    RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy),
                     itctx,
                 );
                 let bounds = this.arena.alloc_from_iter([bound]);
@@ -1271,7 +1289,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     parenthesized: hir::GenericArgsParentheses::No,
                     span_ext: span,
                 });
-                let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args));
+                let path = self.make_lang_item_qpath(hir::LangItem::Pin, span, Some(args));
                 hir::TyKind::Path(path)
             }
             TyKind::FnPtr(f) => {
@@ -1332,7 +1350,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             // takes care of rejecting invalid modifier combinations and
                             // const trait bounds in trait object types.
                             GenericBound::Trait(ty) => {
-                                let trait_ref = this.lower_poly_trait_ref(ty, itctx);
+                                let trait_ref = this.lower_poly_trait_ref(
+                                    ty,
+                                    RelaxedBoundPolicy::Forbidden(
+                                        RelaxedBoundForbiddenReason::TraitObjectTy,
+                                    ),
+                                    itctx,
+                                );
                                 Some(trait_ref)
                             }
                             GenericBound::Outlives(lifetime) => {
@@ -1387,9 +1411,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         }
                         path
                     }
-                    ImplTraitContext::InBinding => {
-                        hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx))
-                    }
+                    ImplTraitContext::InBinding => hir::TyKind::TraitAscription(
+                        self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx),
+                    ),
                     ImplTraitContext::FeatureGated(position, feature) => {
                         let guar = self
                             .tcx
@@ -1505,7 +1529,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
 
         self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| {
-            this.lower_param_bounds(bounds, itctx)
+            this.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx)
         })
     }
 
@@ -1799,10 +1823,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_param_bound(
         &mut self,
         tpb: &GenericBound,
+        rbp: RelaxedBoundPolicy<'_>,
         itctx: ImplTraitContext,
     ) -> hir::GenericBound<'hir> {
         match tpb {
-            GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
+            GenericBound::Trait(p) => {
+                hir::GenericBound::Trait(self.lower_poly_trait_ref(p, rbp, itctx))
+            }
             GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime(
                 lifetime,
                 LifetimeSource::OutlivesBound,
@@ -2017,19 +2044,91 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     #[instrument(level = "debug", skip(self))]
     fn lower_poly_trait_ref(
         &mut self,
-        p: &PolyTraitRef,
+        PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef,
+        rbp: RelaxedBoundPolicy<'_>,
         itctx: ImplTraitContext,
     ) -> hir::PolyTraitRef<'hir> {
         let bound_generic_params =
-            self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
-        let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
-        let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
+            self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params);
+        let trait_ref = self.lower_trait_ref(*modifiers, trait_ref, itctx);
+        let modifiers = self.lower_trait_bound_modifiers(*modifiers);
+
+        if let ast::BoundPolarity::Maybe(_) = modifiers.polarity {
+            self.validate_relaxed_bound(trait_ref, *span, rbp);
+        }
+
         hir::PolyTraitRef {
             bound_generic_params,
             modifiers,
             trait_ref,
-            span: self.lower_span(p.span),
+            span: self.lower_span(*span),
+        }
+    }
+
+    fn validate_relaxed_bound(
+        &self,
+        trait_ref: hir::TraitRef<'_>,
+        span: Span,
+        rbp: RelaxedBoundPolicy<'_>,
+    ) {
+        // Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables
+        // relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user
+        // (via a feature gate) since it's super internal. Besides this, it'd be quite distracting.
+        //
+        // [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's
+        //       no longer fully consistent with default trait elaboration in HIR ty lowering.
+
+        match rbp {
+            RelaxedBoundPolicy::Allowed => return,
+            RelaxedBoundPolicy::AllowedIfOnTyParam(id, params) => {
+                if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res())
+                    && let Res::Def(DefKind::TyParam, def_id) = res
+                    && params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id())
+                {
+                    return;
+                }
+                if self.tcx.features().more_maybe_bounds() {
+                    return;
+                }
+            }
+            RelaxedBoundPolicy::Forbidden(reason) => {
+                if self.tcx.features().more_maybe_bounds() {
+                    return;
+                }
+
+                match reason {
+                    RelaxedBoundForbiddenReason::TraitObjectTy => {
+                        self.dcx().span_err(
+                            span,
+                            "relaxed bounds are not permitted in trait object types",
+                        );
+                        return;
+                    }
+                    RelaxedBoundForbiddenReason::SuperTrait => {
+                        let mut diag = self.dcx().struct_span_err(
+                            span,
+                            "relaxed bounds are not permitted in supertrait bounds",
+                        );
+                        if let Some(def_id) = trait_ref.trait_def_id()
+                            && self.tcx.is_lang_item(def_id, hir::LangItem::Sized)
+                        {
+                            diag.note("traits are `?Sized` by default");
+                        }
+                        diag.emit();
+                        return;
+                    }
+                    RelaxedBoundForbiddenReason::LateBoundVarsInScope => {}
+                };
+            }
         }
+
+        self.dcx()
+            .struct_span_err(span, "this relaxed bound is not permitted here")
+            .with_note(
+                "in this context, relaxed bounds are only allowed on \
+                 type parameters defined by the closest item",
+            )
+            .emit();
     }
 
     fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
@@ -2040,17 +2139,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_param_bounds(
         &mut self,
         bounds: &[GenericBound],
+        rbp: RelaxedBoundPolicy<'_>,
         itctx: ImplTraitContext,
     ) -> hir::GenericBounds<'hir> {
-        self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
+        self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, rbp, itctx))
     }
 
     fn lower_param_bounds_mut(
         &mut self,
         bounds: &[GenericBound],
+        rbp: RelaxedBoundPolicy<'_>,
         itctx: ImplTraitContext,
     ) -> impl Iterator<Item = hir::GenericBound<'hir>> {
-        bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
+        bounds.iter().map(move |bound| self.lower_param_bound(bound, rbp, itctx))
     }
 
     #[instrument(level = "debug", skip(self), ret)]
@@ -2084,6 +2185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             bounds,
             /* colon_span */ None,
             span,
+            RelaxedBoundPolicy::Allowed,
             ImplTraitContext::Universal,
             hir::PredicateOrigin::ImplTrait,
         );
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index e419154d65d..af93d55c898 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -212,11 +212,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
 ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
     .help = use `auto trait Trait {"{}"}` instead
 
-ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
-
-ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
-    .note = traits are `?{$path_str}` by default
-
 ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters
     .suggestion = reorder the parameters: lifetimes, then consts and types
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index c69250c0305..a08dae11153 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1381,29 +1381,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         match bound {
             GenericBound::Trait(trait_ref) => {
                 match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
-                    (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
-                        if !self.features.more_maybe_bounds() =>
-                    {
-                        self.sess
-                            .create_feature_err(
-                                errors::OptionalTraitSupertrait {
-                                    span: trait_ref.span,
-                                    path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
-                                },
-                                sym::more_maybe_bounds,
-                            )
-                            .emit();
-                    }
-                    (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
-                        if !self.features.more_maybe_bounds() =>
-                    {
-                        self.sess
-                            .create_feature_err(
-                                errors::OptionalTraitObject { span: trait_ref.span },
-                                sym::more_maybe_bounds,
-                            )
-                            .emit();
-                    }
                     (
                         BoundKind::TraitObject,
                         BoundConstness::Always(_),
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index c1ebd025c7a..fd4b2528541 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -567,22 +567,6 @@ pub(crate) struct NestedLifetimes {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_optional_trait_supertrait)]
-#[note]
-pub(crate) struct OptionalTraitSupertrait {
-    #[primary_span]
-    pub span: Span,
-    pub path_str: String,
-}
-
-#[derive(Diagnostic)]
-#[diag(ast_passes_optional_trait_object)]
-pub(crate) struct OptionalTraitObject {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(ast_passes_const_bound_trait_object)]
 pub(crate) struct ConstBoundTraitObject {
     #[primary_span]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0203.md b/compiler/rustc_error_codes/src/error_codes/E0203.md
index 1edb519275f..a4dceedbf1f 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0203.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0203.md
@@ -1,15 +1,15 @@
-Having multiple relaxed default bounds is unsupported.
+Having duplicate relaxed default bounds is unsupported.
 
 Erroneous code example:
 
 ```compile_fail,E0203
-struct Bad<T: ?Sized + ?Send>{
-    inner: T
+struct Bad<T: ?Sized + ?Sized>{
+    inner: T,
 }
 ```
 
-Here the type `T` cannot have a relaxed bound for multiple default traits
-(`Sized` and `Send`). This can be fixed by only using one relaxed bound.
+Here the type parameter `T` cannot have duplicate relaxed bounds for default
+trait `Sized`. This can be fixed by only using one relaxed bound:
 
 ```
 struct Good<T: ?Sized>{
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index e38ca9e80ce..2428c1aa29f 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -371,9 +371,6 @@ hir_analysis_missing_type_params =
         *[other] parameters
     } must be specified on the object type
 
-hir_analysis_multiple_relaxed_default_bounds =
-    type parameter has more than one relaxed default bound, only one is supported
-
 hir_analysis_must_be_name_of_associated_function = must be a name of an associated function
 
 hir_analysis_must_implement_not_function = not a function
@@ -448,8 +445,6 @@ hir_analysis_parenthesized_fn_trait_expansion =
 hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
     .label = not allowed in type signatures
 
-hir_analysis_pointee_sized_trait_object = `PointeeSized` cannot be used with trait objects
-
 hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
     .label = `Self` is not a generic argument, but an alias to the type of the {$what}
 
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index f2f1560d8b2..cc53919626e 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -267,20 +267,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
         match predicate.kind {
             hir::WherePredicateKind::BoundPredicate(bound_pred) => {
                 let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
-
                 let bound_vars = tcx.late_bound_vars(predicate.hir_id);
-                // Keep the type around in a dummy predicate, in case of no bounds.
-                // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
-                // is still checked for WF.
+
+                // This is a `where Ty:` (sic!).
                 if bound_pred.bounds.is_empty() {
                     if let ty::Param(_) = ty.kind() {
-                        // This is a `where T:`, which can be in the HIR from the
-                        // transformation that moves `?Sized` to `T`'s declaration.
-                        // We can skip the predicate because type parameters are
-                        // trivially WF, but also we *should*, to avoid exposing
-                        // users who never wrote `where Type:,` themselves, to
-                        // compiler/tooling bugs from not handling WF predicates.
+                        // We can skip the predicate because type parameters are trivially WF.
                     } else {
+                        // Keep the type around in a dummy predicate. That way, it's not a complete
+                        // noop (see #53696) and `Ty` is still checked for WF.
+
                         let span = bound_pred.bounded_ty.span;
                         let predicate = ty::Binder::bind_with_vars(
                             ty::ClauseKind::WellFormed(ty.into()),
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index fbd21f8b100..26a98722b34 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -280,13 +280,6 @@ pub(crate) struct CopyImplOnTypeWithDtor {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)]
-pub(crate) struct MultipleRelaxedDefaultBounds {
-    #[primary_span]
-    pub spans: Vec<Span>,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)]
 pub(crate) struct CopyImplOnNonAdt {
     #[primary_span]
@@ -320,13 +313,6 @@ pub(crate) struct TraitObjectDeclaredWithNoTraits {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_pointee_sized_trait_object)]
-pub(crate) struct PointeeSizedTraitObject {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)]
 pub(crate) struct AmbiguousLifetimeBound {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 9a752aeccdd..d7a827c649d 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -6,7 +6,7 @@ use rustc_errors::struct_span_code_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
-use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
+use rustc_hir::{AmbigArg, PolyTraitRef};
 use rustc_middle::bug;
 use rustc_middle::ty::{
     self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -85,17 +85,17 @@ fn search_bounds_for<'tcx>(
     }
 }
 
-fn collect_unbounds<'tcx>(
+fn collect_relaxed_bounds<'tcx>(
     hir_bounds: &'tcx [hir::GenericBound<'tcx>],
     self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
 ) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
-    let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
+    let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
     search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
         if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
-            unbounds.push(ptr);
+            relaxed_bounds.push(ptr);
         }
     });
-    unbounds
+    relaxed_bounds
 }
 
 fn collect_bounds<'a, 'tcx>(
@@ -124,13 +124,13 @@ fn collect_sizedness_bounds<'tcx>(
     self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
     span: Span,
 ) -> CollectedSizednessBounds {
-    let sized_did = tcx.require_lang_item(LangItem::Sized, span);
+    let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
     let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
 
-    let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
+    let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
     let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did);
 
-    let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
+    let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
     let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
 
     CollectedSizednessBounds { sized, meta_sized, pointee_sized }
@@ -151,24 +151,6 @@ fn add_trait_bound<'tcx>(
 }
 
 impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
-    /// Skip `PointeeSized` bounds.
-    ///
-    /// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there
-    /// is actually the absence of any bounds. This avoids limitations around non-global where
-    /// clauses being preferred over item bounds (where `PointeeSized` bounds would be
-    /// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is
-    /// added to some items.
-    pub(crate) fn should_skip_sizedness_bound<'hir>(
-        &self,
-        bound: &'hir hir::GenericBound<'tcx>,
-    ) -> bool {
-        bound
-            .trait_ref()
-            .and_then(|tr| tr.trait_def_id())
-            .map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized))
-            .unwrap_or(false)
-    }
-
     /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type.
     ///
     /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit
@@ -193,8 +175,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             return;
         }
 
-        let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
-        let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
+        let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
+        let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
 
         // If adding sizedness bounds to a trait, then there are some relevant early exits
         if let Some(trait_did) = trait_did {
@@ -209,9 +191,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 return;
             }
         } else {
-            // Report invalid unbounds on sizedness-bounded generic parameters.
-            let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates);
-            self.check_and_report_invalid_unbounds_on_param(unbounds);
+            // Report invalid relaxed bounds.
+            // FIXME: Since we only call this validation function here in this function, we only
+            //        fully validate relaxed bounds in contexts where we perform
+            //        "sized elaboration". In most cases that doesn't matter because we *usually*
+            //        reject such relaxed bounds outright during AST lowering.
+            //        However, this can easily get out of sync! Ideally, we would perform this step
+            //        where we are guaranteed to catch *all* bounds like in
+            //        `Self::lower_poly_trait_ref`. List of concrete issues:
+            //        FIXME(more_maybe_bounds): We don't call this for e.g., trait object tys or
+            //                                  supertrait bounds!
+            //        FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however,
+            //                                       AST lowering should reject them outright.
+            //        FIXME(associated_type_bounds): We don't call this for them. However, AST
+            //                                       lowering should reject them outright (#135229).
+            let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
+            self.check_and_report_invalid_relaxed_bounds(bounds);
         }
 
         let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
@@ -231,7 +226,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             } else {
                 // If there are no explicit sizedness bounds on a parameter then add a default
                 // `Sized` bound.
-                let sized_did = tcx.require_lang_item(LangItem::Sized, span);
+                let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
                 add_trait_bound(tcx, bounds, self_ty, sized_did, span);
             }
         }
@@ -463,10 +458,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         'tcx: 'hir,
     {
         for hir_bound in hir_bounds {
-            if self.should_skip_sizedness_bound(hir_bound) {
-                continue;
-            }
-
             // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
             // we skip over any traits that don't define the given associated type.
             if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
@@ -482,12 +473,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
             match hir_bound {
                 hir::GenericBound::Trait(poly_trait_ref) => {
-                    let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
                     let _ = self.lower_poly_trait_ref(
-                        &poly_trait_ref.trait_ref,
-                        poly_trait_ref.span,
-                        constness,
-                        polarity,
+                        poly_trait_ref,
                         param_ty,
                         bounds,
                         predicate_filter,
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index 364ad38556b..76bb59e3f09 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -2,7 +2,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::struct_span_code_err;
 use rustc_hir as hir;
-use rustc_hir::LangItem;
 use rustc_hir::def::{DefKind, Res};
 use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
 use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
@@ -18,9 +17,7 @@ use tracing::{debug, instrument};
 
 use super::HirTyLowerer;
 use crate::errors::SelfInTypeAlias;
-use crate::hir_ty_lowering::{
-    GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
-};
+use crate::hir_ty_lowering::{GenericArgCountMismatch, PredicateFilter, RegionInferReason};
 
 impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// Lower a trait object type from the HIR to our internal notion of a type.
@@ -38,24 +35,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         let mut user_written_bounds = Vec::new();
         let mut potential_assoc_types = Vec::new();
-        for trait_bound in hir_bounds.iter() {
-            if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity {
-                continue;
-            }
-            if let GenericArgCountResult {
-                correct:
-                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
-                ..
-            } = self.lower_poly_trait_ref(
-                &trait_bound.trait_ref,
-                trait_bound.span,
-                trait_bound.modifiers.constness,
-                hir::BoundPolarity::Positive,
+        for poly_trait_ref in hir_bounds.iter() {
+            let result = self.lower_poly_trait_ref(
+                poly_trait_ref,
                 dummy_self,
                 &mut user_written_bounds,
                 PredicateFilter::SelfOnly,
-            ) {
-                potential_assoc_types.extend(cur_potential_assoc_types);
+            );
+            if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
+                potential_assoc_types.extend(invalid_args);
             }
         }
 
@@ -81,13 +69,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             let guar = self.report_trait_object_addition_traits(&regular_traits);
             return Ty::new_error(tcx, guar);
         }
-        // We don't support `PointeeSized` principals
-        let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
-        if regular_traits.iter().any(|(pred, _)| pred.def_id() == pointee_sized_did) {
-            let guar = self.report_pointee_sized_trait_object(span);
-            return Ty::new_error(tcx, guar);
-        }
-
         // Don't create a dyn trait if we have errors in the principal.
         if let Err(guar) = regular_traits.error_reported() {
             return Ty::new_error(tcx, guar);
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 5d85a3f8455..287a5532f01 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -8,7 +8,7 @@ use rustc_errors::{
 };
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef};
+use rustc_hir::{self as hir, HirId, PolyTraitRef};
 use rustc_middle::bug;
 use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
 use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
@@ -29,59 +29,54 @@ use tracing::debug;
 use super::InherentAssocCandidate;
 use crate::errors::{
     self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
-    ParenthesizedFnTraitExpansion, PointeeSizedTraitObject, TraitObjectDeclaredWithNoTraits,
+    ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
 };
 use crate::fluent_generated as fluent;
 use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
 
 impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
-    /// Check for multiple relaxed default bounds and relaxed bounds of non-sizedness traits.
-    pub(crate) fn check_and_report_invalid_unbounds_on_param(
+    /// Check for duplicate relaxed bounds and relaxed bounds of non-default traits.
+    pub(crate) fn check_and_report_invalid_relaxed_bounds(
         &self,
-        unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
+        relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
     ) {
         let tcx = self.tcx();
 
-        let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
+        let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
 
-        let mut unique_bounds = FxIndexSet::default();
-        let mut seen_repeat = false;
-        for unbound in &unbounds {
-            if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
-                seen_repeat |= !unique_bounds.insert(unbound_def_id);
+        for bound in &relaxed_bounds {
+            if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
+                grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
             }
         }
 
-        if unbounds.len() > 1 {
-            let err = errors::MultipleRelaxedDefaultBounds {
-                spans: unbounds.iter().map(|ptr| ptr.span).collect(),
-            };
-
-            if seen_repeat {
-                tcx.dcx().emit_err(err);
-            } else if !tcx.features().more_maybe_bounds() {
-                tcx.sess.create_feature_err(err, sym::more_maybe_bounds).emit();
-            };
+        for (trait_def_id, spans) in grouped_bounds {
+            if spans.len() > 1 {
+                let name = tcx.item_name(trait_def_id);
+                self.dcx()
+                    .struct_span_err(spans, format!("duplicate relaxed `{name}` bounds"))
+                    .with_code(E0203)
+                    .emit();
+            }
         }
 
-        for unbound in unbounds {
-            if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res
-                && ((did == sized_did) || tcx.is_default_trait(did))
+        let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP);
+
+        for bound in relaxed_bounds {
+            if let Res::Def(DefKind::Trait, def_id) = bound.trait_ref.path.res
+                && (def_id == sized_def_id || tcx.is_default_trait(def_id))
             {
                 continue;
             }
-
-            let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
-                true => "`?Sized` and `experimental_default_bounds`",
-                false => "`?Sized`",
-            };
             self.dcx().span_err(
-                unbound.span,
-                format!(
-                    "relaxing a default bound only does something for {}; all other traits are \
-                     not bound by default",
-                    unbound_traits
-                ),
+                bound.span,
+                if tcx.sess.opts.unstable_opts.experimental_default_bounds
+                    || tcx.features().more_maybe_bounds()
+                {
+                    "bound modifier `?` can only be applied to default traits like `Sized`"
+                } else {
+                    "bound modifier `?` can only be applied to `Sized`"
+                },
             );
         }
     }
@@ -1410,10 +1405,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
     }
-
-    pub(super) fn report_pointee_sized_trait_object(&self, span: Span) -> ErrorGuaranteed {
-        self.dcx().emit_err(PointeeSizedTraitObject { span })
-    }
 }
 
 /// Emit an error for the given associated item constraint.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index a5bd7c1a34a..78794cd8eb6 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -747,18 +747,46 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
     /// where `'a` is a bound region at depth 0. Similarly, the `trait_ref` would be `Bar<'a>`.
     /// The lowered poly-trait-ref will track this binder explicitly, however.
-    #[instrument(level = "debug", skip(self, span, constness, bounds))]
+    #[instrument(level = "debug", skip(self, bounds))]
     pub(crate) fn lower_poly_trait_ref(
         &self,
-        trait_ref: &hir::TraitRef<'tcx>,
-        span: Span,
-        constness: hir::BoundConstness,
-        polarity: hir::BoundPolarity,
+        poly_trait_ref: &hir::PolyTraitRef<'tcx>,
         self_ty: Ty<'tcx>,
         bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
         predicate_filter: PredicateFilter,
     ) -> GenericArgCountResult {
+        let tcx = self.tcx();
+
+        // We use the *resolved* bound vars later instead of the HIR ones since the former
+        // also include the bound vars of the overarching predicate if applicable.
+        let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } =
+            *poly_trait_ref;
+        let hir::TraitBoundModifiers { constness, polarity } = modifiers;
+
         let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
+
+        // Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR
+        // as they denote the *absence* of a default bound. However, we can't bail out early here since
+        // we still need to perform several validation steps (see below). Instead, simply "pour" all
+        // resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end.
+        let (polarity, bounds) = match polarity {
+            rustc_ast::BoundPolarity::Positive
+                if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) =>
+            {
+                // To elaborate on the comment directly above, regarding `PointeeSized` specifically,
+                // we don't "reify" such bounds to avoid trait system limitations -- namely,
+                // non-global where-clauses being preferred over item bounds (where `PointeeSized`
+                // bounds would be proven) -- which can result in errors when a `PointeeSized`
+                // supertrait / bound / predicate is added to some items.
+                (ty::PredicatePolarity::Positive, &mut Vec::new())
+            }
+            rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
+            rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
+            rustc_ast::BoundPolarity::Maybe(_) => {
+                (ty::PredicatePolarity::Positive, &mut Vec::new())
+            }
+        };
+
         let trait_segment = trait_ref.path.segments.last().unwrap();
 
         let _ = self.prohibit_generic_args(
@@ -775,7 +803,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             Some(self_ty),
         );
 
-        let tcx = self.tcx();
         let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
         debug!(?bound_vars);
 
@@ -786,27 +813,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         debug!(?poly_trait_ref);
 
-        let polarity = match polarity {
-            rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
-            rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
-            rustc_ast::BoundPolarity::Maybe(_) => {
-                // Validate associated type at least. We may want to reject these
-                // outright in the future...
-                for constraint in trait_segment.args().constraints {
-                    let _ = self.lower_assoc_item_constraint(
-                        trait_ref.hir_ref_id,
-                        poly_trait_ref,
-                        constraint,
-                        &mut Default::default(),
-                        &mut Default::default(),
-                        constraint.span,
-                        predicate_filter,
-                    );
-                }
-                return arg_count;
-            }
-        };
-
         // We deal with const conditions later.
         match predicate_filter {
             PredicateFilter::All
@@ -909,7 +915,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             // Don't register any associated item constraints for negative bounds,
             // since we should have emitted an error for them earlier, and they
             // would not be well-formed!
-            if polarity != ty::PredicatePolarity::Positive {
+            if polarity == ty::PredicatePolarity::Negative {
                 self.dcx().span_delayed_bug(
                     constraint.span,
                     "negative trait bounds should not have assoc item constraints",