about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david.wood2@arm.com>2025-02-27 21:19:51 +0000
committerDavid Wood <david.wood2@arm.com>2025-06-16 23:04:33 +0000
commit86ab2b60cd22f6190eb586c889f8a2504f0d926b (patch)
treec379a930de63e5cb21b83110dccd82c1c3874a25
parentf0b84b8dcfc15c3936256ccb438b1d050620ff3c (diff)
downloadrust-86ab2b60cd22f6190eb586c889f8a2504f0d926b.tar.gz
rust-86ab2b60cd22f6190eb586c889f8a2504f0d926b.zip
hir_analysis: add `{Meta,Pointee}Sized` bounds
Opting-out of `Sized` with `?Sized` is now equivalent to adding a
`MetaSized` bound, and adding a `MetaSized` or `PointeeSized` bound
is equivalent to removing the default `Sized` bound - this commit
implements this change in `rustc_hir_analysis::hir_ty_lowering`.

`MetaSized` is also added as a supertrait of all traits, as this is
necessary to preserve backwards compatibility.

Unfortunately, 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. Rather than `PointeeSized` being a bound on everything, it can
be the absence of a bound on everything, as `?Sized` was.
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs25
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs346
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs53
-rw-r--r--compiler/rustc_middle/src/ty/context.rs11
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-sized-hierarchy.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr6
-rw-r--r--tests/ui/sized-hierarchy/alias-bounds.rs28
-rw-r--r--tests/ui/sized-hierarchy/default-bound.rs49
-rw-r--r--tests/ui/sized-hierarchy/default-bound.stderr88
-rw-r--r--tests/ui/sized-hierarchy/default-supertrait.rs61
-rw-r--r--tests/ui/sized-hierarchy/default-supertrait.stderr125
-rw-r--r--tests/ui/sized-hierarchy/extern-type-behind-ptr.rs20
-rw-r--r--tests/ui/sized-hierarchy/impls.rs14
-rw-r--r--tests/ui/sized-hierarchy/impls.stderr108
-rw-r--r--tests/ui/sized-hierarchy/pointee-supertrait.rs28
-rw-r--r--tests/ui/sized-hierarchy/trait-aliases.rs9
20 files changed, 798 insertions, 207 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index c5c7e6b2aa7..5b8aa28102c 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -76,6 +76,7 @@ pub use check::{check_abi, check_abi_fn_ptr, check_custom_abi};
 use rustc_abi::{ExternAbi, VariantIdx};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
+use rustc_hir::LangItem;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_index::bit_set::DenseBitSet;
@@ -331,7 +332,7 @@ fn bounds_from_generic_predicates<'tcx>(
             ty::ClauseKind::Trait(trait_predicate) => {
                 let entry = types.entry(trait_predicate.self_ty()).or_default();
                 let def_id = trait_predicate.def_id();
-                if !tcx.is_default_trait(def_id) {
+                if !tcx.is_default_trait(def_id) && !tcx.is_lang_item(def_id, LangItem::Sized) {
                     // Do not add that restriction to the list if it is a positive requirement.
                     entry.push(trait_predicate.def_id());
                 }
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 5f1cdeddc19..53c44cdc411 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -44,6 +44,14 @@ fn associated_type_bounds<'tcx>(
             | PredicateFilter::SelfOnly
             | PredicateFilter::SelfTraitThatDefines(_)
             | PredicateFilter::SelfAndAssociatedTypeBounds => {
+                icx.lowerer().add_sizedness_bounds(
+                    &mut bounds,
+                    item_ty,
+                    hir_bounds,
+                    None,
+                    None,
+                    span,
+                );
                 icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
             }
             // `ConstIfConst` is only interested in `~const` bounds.
@@ -333,6 +341,14 @@ fn opaque_type_bounds<'tcx>(
             | PredicateFilter::SelfOnly
             | PredicateFilter::SelfTraitThatDefines(_)
             | PredicateFilter::SelfAndAssociatedTypeBounds => {
+                icx.lowerer().add_sizedness_bounds(
+                    &mut bounds,
+                    item_ty,
+                    hir_bounds,
+                    None,
+                    None,
+                    span,
+                );
                 icx.lowerer().add_default_traits(&mut bounds, item_ty, hir_bounds, None, span);
             }
             //`ConstIfConst` is only interested in `~const` bounds.
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index ce0f83d0ec2..c337765c5fe 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -162,7 +162,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                         .map(|t| ty::Binder::dummy(t.instantiate_identity()));
                 }
             }
-
             ItemKind::Trait(_, _, _, _, self_bounds, ..)
             | ItemKind::TraitAlias(_, _, self_bounds) => {
                 is_trait = Some((self_bounds, item.span));
@@ -183,21 +182,29 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     // and the explicit where-clauses, but to get the full set of predicates
     // 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 {
+    if let Some((self_bounds, span)) = is_trait {
         let mut bounds = Vec::new();
         icx.lowerer().lower_bounds(
             tcx.types.self_param,
-            self_bounds.0,
+            self_bounds,
             &mut bounds,
             ty::List::empty(),
             PredicateFilter::All,
         );
+        icx.lowerer().add_sizedness_bounds(
+            &mut bounds,
+            tcx.types.self_param,
+            self_bounds,
+            None,
+            Some(def_id),
+            span,
+        );
         icx.lowerer().add_default_super_traits(
             def_id,
             &mut bounds,
-            self_bounds.0,
+            self_bounds,
             hir_generics,
-            self_bounds.1,
+            span,
         );
         predicates.extend(bounds);
     }
@@ -224,6 +231,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
                 let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
                 let mut bounds = Vec::new();
                 // Implicit bounds are added to type params unless a `?Trait` bound is found
+                icx.lowerer().add_sizedness_bounds(
+                    &mut bounds,
+                    param_ty,
+                    &[],
+                    Some((param.def_id, hir_generics.predicates)),
+                    None,
+                    param.span,
+                );
                 icx.lowerer().add_default_traits(
                     &mut bounds,
                     param_ty,
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 106420faa4c..ea1dfdfd806 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -4,15 +4,15 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::struct_span_code_err;
 use rustc_hir as hir;
-use rustc_hir::AmbigArg;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
 use rustc_middle::bug;
 use rustc_middle::ty::{
     self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
     TypeVisitor, Upcast,
 };
-use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
+use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw};
 use rustc_trait_selection::traits;
 use smallvec::SmallVec;
 use tracing::{debug, instrument};
@@ -23,23 +23,213 @@ use crate::hir_ty_lowering::{
     AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
 };
 
+#[derive(Debug, Default)]
+struct CollectedBound {
+    /// `Trait`
+    positive: bool,
+    /// `?Trait`
+    maybe: bool,
+    /// `!Trait`
+    negative: bool,
+}
+
+impl CollectedBound {
+    /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered.
+    fn any(&self) -> bool {
+        self.positive || self.maybe || self.negative
+    }
+}
+
+#[derive(Debug)]
+struct CollectedSizednessBounds {
+    // Collected `Sized` bounds
+    sized: CollectedBound,
+    // Collected `MetaSized` bounds
+    meta_sized: CollectedBound,
+    // Collected `PointeeSized` bounds
+    pointee_sized: CollectedBound,
+}
+
+impl CollectedSizednessBounds {
+    /// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered for `Sized`,
+    /// `MetaSized` or `PointeeSized`.
+    fn any(&self) -> bool {
+        self.sized.any() || self.meta_sized.any() || self.pointee_sized.any()
+    }
+}
+
+fn search_bounds_for<'tcx>(
+    hir_bounds: &'tcx [hir::GenericBound<'tcx>],
+    self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
+    mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
+) {
+    let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
+        for hir_bound in hir_bounds {
+            let hir::GenericBound::Trait(ptr) = hir_bound else {
+                continue;
+            };
+
+            f(ptr)
+        }
+    };
+
+    search_bounds(hir_bounds);
+    if let Some((self_ty, where_clause)) = self_ty_where_predicates {
+        for clause in where_clause {
+            if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
+                && pred.is_param_bound(self_ty.to_def_id())
+            {
+                search_bounds(pred.bounds);
+            }
+        }
+    }
+}
+
+fn collect_unbounds<'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();
+    search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
+        if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
+            unbounds.push(ptr);
+        }
+    });
+    unbounds
+}
+
+fn collect_bounds<'a, 'tcx>(
+    hir_bounds: &'a [hir::GenericBound<'tcx>],
+    self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
+    target_did: DefId,
+) -> CollectedBound {
+    let mut collect_into = CollectedBound::default();
+    search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
+        if !matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
+            return;
+        }
+
+        match ptr.modifiers.polarity {
+            hir::BoundPolarity::Maybe(_) => collect_into.maybe = true,
+            hir::BoundPolarity::Negative(_) => collect_into.negative = true,
+            hir::BoundPolarity::Positive => collect_into.positive = true,
+        }
+    });
+    collect_into
+}
+
+fn collect_sizedness_bounds<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    hir_bounds: &'tcx [hir::GenericBound<'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 = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
+
+    let meta_sized_did = tcx.require_lang_item(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 = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
+
+    CollectedSizednessBounds { sized, meta_sized, pointee_sized }
+}
+
+/// Add a trait bound for `did`.
+fn add_trait_bound<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
+    self_ty: Ty<'tcx>,
+    did: DefId,
+    span: Span,
+) {
+    let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]);
+    // Preferable to put sizedness obligations first, since we report better errors for `Sized`
+    // ambiguity.
+    bounds.insert(0, (trait_ref.upcast(tcx), span));
+}
+
 impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
-    pub(crate) fn add_default_traits(
+    /// 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
+    ///   sizedness bounds are present.
+    /// - On traits and trait aliases, add default `MetaSized` supertrait if no explicit sizedness
+    ///   bounds are present.
+    /// - On parameters, opaque type, associated types and trait aliases, add a `MetaSized` bound if
+    ///   a `?Sized` bound is present.
+    pub(crate) fn add_sizedness_bounds(
         &self,
         bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
         self_ty: Ty<'tcx>,
-        hir_bounds: &[hir::GenericBound<'tcx>],
+        hir_bounds: &'tcx [hir::GenericBound<'tcx>],
         self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
+        trait_did: Option<LocalDefId>,
         span: Span,
     ) {
-        self.add_default_traits_with_filter(
-            bounds,
-            self_ty,
-            hir_bounds,
-            self_ty_where_predicates,
-            span,
-            |_| true,
-        );
+        let tcx = self.tcx();
+
+        let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
+        let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
+
+        // If adding sizedness bounds to a trait, then there are some relevant early exits
+        if let Some(trait_did) = trait_did {
+            let trait_did = trait_did.to_def_id();
+            // Never add a default supertrait to `PointeeSized`.
+            if trait_did == pointee_sized_did {
+                return;
+            }
+            // Don't add default sizedness supertraits to auto traits because it isn't possible to
+            // relax an automatically added supertrait on the defn itself.
+            if tcx.trait_is_auto(trait_did) {
+                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);
+        }
+
+        let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
+        if (collected.sized.maybe || collected.sized.negative)
+            && !collected.sized.positive
+            && !collected.meta_sized.any()
+            && !collected.pointee_sized.any()
+        {
+            // `?Sized` is equivalent to `MetaSized` (but only add the bound if there aren't any
+            // other explicit ones) - this can happen for trait aliases as well as bounds.
+            add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
+        } else if !collected.any() {
+            if trait_did.is_some() {
+                // If there are no explicit sizedness bounds on a trait then add a default
+                // `MetaSized` supertrait.
+                add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
+            } 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);
+                add_trait_bound(tcx, bounds, self_ty, sized_did, span);
+            }
+        }
     }
 
     /// Checks whether `Self: DefaultAutoTrait` bounds should be added on trait super bounds
@@ -146,13 +336,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 
         if !self.requires_default_supertraits(trait_bounds, trait_generics) {
             let self_ty_where_predicates = (parent, trait_item.generics.predicates);
-            self.add_default_traits_with_filter(
+            self.add_default_traits(
                 bounds,
                 tcx.types.self_param,
                 &[],
                 Some(self_ty_where_predicates),
                 trait_item.span,
-                |tr| tr != hir::LangItem::Sized,
             );
         }
     }
@@ -174,41 +363,37 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         assert!(matches!(self.tcx().def_kind(trait_def_id), DefKind::Trait | DefKind::TraitAlias));
         if self.requires_default_supertraits(hir_bounds, hir_generics) {
             let self_ty_where_predicates = (trait_def_id, hir_generics.predicates);
-            self.add_default_traits_with_filter(
+            self.add_default_traits(
                 bounds,
                 self.tcx().types.self_param,
                 hir_bounds,
                 Some(self_ty_where_predicates),
                 span,
-                |default_trait| default_trait != hir::LangItem::Sized,
             );
         }
     }
 
-    pub(crate) fn add_default_traits_with_filter(
+    pub(crate) fn add_default_traits(
         &self,
         bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
         self_ty: Ty<'tcx>,
         hir_bounds: &[hir::GenericBound<'tcx>],
         self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
         span: Span,
-        f: impl Fn(hir::LangItem) -> bool,
     ) {
-        self.tcx().default_traits().iter().filter(|&&default_trait| f(default_trait)).for_each(
-            |default_trait| {
-                self.add_default_trait(
-                    *default_trait,
-                    bounds,
-                    self_ty,
-                    hir_bounds,
-                    self_ty_where_predicates,
-                    span,
-                );
-            },
-        );
+        self.tcx().default_traits().iter().for_each(|default_trait| {
+            self.add_default_trait(
+                *default_trait,
+                bounds,
+                self_ty,
+                hir_bounds,
+                self_ty_where_predicates,
+                span,
+            );
+        });
     }
 
-    /// Add a `Sized` or `experimental_default_bounds` bounds to the `bounds` if appropriate.
+    /// Add a `experimental_default_bounds` bound to the `bounds` if appropriate.
     ///
     /// Doesn't add the bound if the HIR bounds contain any of `Trait`, `?Trait` or `!Trait`.
     pub(crate) fn add_default_trait(
@@ -220,7 +405,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
         span: Span,
     ) {
-        let trait_id = self.tcx().lang_items().get(trait_);
+        let tcx = self.tcx();
+        let trait_id = tcx.lang_items().get(trait_);
         if let Some(trait_id) = trait_id
             && self.do_not_provide_default_trait_bound(
                 trait_id,
@@ -228,11 +414,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 self_ty_where_predicates,
             )
         {
-            // There was no `?Trait` or `!Trait` bound;
-            // add `Trait` if it's available.
-            let trait_ref = ty::TraitRef::new(self.tcx(), trait_id, [self_ty]);
-            // Preferable to put this obligation first, since we report better errors for sized ambiguity.
-            bounds.insert(0, (trait_ref.upcast(self.tcx()), span));
+            add_trait_bound(tcx, bounds, self_ty, trait_id, span);
         }
     }
 
@@ -242,90 +424,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         hir_bounds: &'a [hir::GenericBound<'tcx>],
         self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
     ) -> bool {
-        let tcx = self.tcx();
-        let mut seen_negative_bound = false;
-        let mut seen_positive_bound = false;
-
-        // Try to find an unbound in bounds.
-        let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
-        let mut search_bounds = |hir_bounds: &'a [hir::GenericBound<'tcx>]| {
-            for hir_bound in hir_bounds {
-                let hir::GenericBound::Trait(ptr) = hir_bound else {
-                    continue;
-                };
-                match ptr.modifiers.polarity {
-                    hir::BoundPolarity::Maybe(_) => unbounds.push(ptr),
-                    hir::BoundPolarity::Negative(_) => {
-                        if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) {
-                            seen_negative_bound = true;
-                        }
-                    }
-                    hir::BoundPolarity::Positive => {
-                        if ptr.trait_ref.path.res == Res::Def(DefKind::Trait, trait_def_id) {
-                            seen_positive_bound = true;
-                        }
-                    }
-                }
-            }
-        };
-        search_bounds(hir_bounds);
-        if let Some((self_ty, where_clause)) = self_ty_where_predicates {
-            for clause in where_clause {
-                if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
-                    && pred.is_param_bound(self_ty.to_def_id())
-                {
-                    search_bounds(pred.bounds);
-                }
-            }
-        }
-
-        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);
-            }
-        }
-        if unbounds.len() > 1 {
-            let err = errors::MultipleRelaxedDefaultBounds {
-                spans: unbounds.iter().map(|ptr| ptr.span).collect(),
-            };
-            if seen_repeat {
-                self.dcx().emit_err(err);
-            } else if !tcx.features().more_maybe_bounds() {
-                self.tcx().sess.create_feature_err(err, sym::more_maybe_bounds).emit();
-            };
-        }
-
-        let mut seen_unbound = false;
-        for unbound in unbounds {
-            let unbound_def_id = unbound.trait_ref.trait_def_id();
-            if unbound_def_id == Some(trait_def_id) {
-                seen_unbound = true;
-            }
-            let emit_relax_err = || {
-                let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
-                    true => "`?Sized` and `experimental_default_bounds`",
-                    false => "`?Sized`",
-                };
-                // There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`.
-                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
-                    ),
-                );
-            };
-            match unbound_def_id {
-                Some(def_id) if !tcx.is_default_trait(def_id) => emit_relax_err(),
-                None => emit_relax_err(),
-                _ => {}
-            }
-        }
-
-        !(seen_unbound || seen_negative_bound || seen_positive_bound)
+        let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id);
+        !collected.any()
     }
 
     /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any.
@@ -361,6 +461,10 @@ 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 {
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 c7cdf1d5bd2..05465b47a26 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
@@ -61,14 +61,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let ast_bounds: Vec<_> =
             hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect();
 
-        self.add_default_traits_with_filter(
-            &mut user_written_bounds,
-            dummy_self,
-            &ast_bounds,
-            None,
-            span,
-            |tr| tr != hir::LangItem::Sized,
-        );
+        self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span);
 
         let (elaborated_trait_bounds, elaborated_projection_bounds) =
             traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
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 45fee0fa402..1cda6dff21e 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};
+use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef};
 use rustc_middle::bug;
 use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
 use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
@@ -34,6 +34,57 @@ 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(
+        &self,
+        unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
+    ) {
+        let tcx = self.tcx();
+
+        let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
+
+        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);
+            }
+        }
+
+        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 unbound in unbounds {
+            if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res
+                && ((did == sized_did) || tcx.is_default_trait(did))
+            {
+                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
+                ),
+            );
+        }
+    }
+
     /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
     /// the type parameter's name as a placeholder.
     pub(crate) fn report_missing_type_params(
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 850c9207877..f1395c242f2 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1619,16 +1619,17 @@ impl<'tcx> TyCtxt<'tcx> {
         self.reserve_and_set_memory_dedup(alloc, salt)
     }
 
+    /// Traits added on all bounds by default, excluding `Sized` which is treated separately.
     pub fn default_traits(self) -> &'static [rustc_hir::LangItem] {
-        match self.sess.opts.unstable_opts.experimental_default_bounds {
-            true => &[
-                LangItem::Sized,
+        if self.sess.opts.unstable_opts.experimental_default_bounds {
+            &[
                 LangItem::DefaultTrait1,
                 LangItem::DefaultTrait2,
                 LangItem::DefaultTrait3,
                 LangItem::DefaultTrait4,
-            ],
-            false => &[LangItem::Sized],
+            ]
+        } else {
+            &[]
         }
     }
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 923c9242ff8..d996ee2b60a 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -95,7 +95,7 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness {
 /// `def_id` is assumed to be the `AdtDef` of a struct and will panic otherwise.
 ///
 /// For `Sized`, there are only a few options for the types in the constraint:
-///     - an metasized type (str, slices, trait objects, etc)
+///     - an meta-sized type (str, slices, trait objects, etc)
 ///     - an pointee-sized type (extern types)
 ///     - a type parameter or projection whose sizedness can't be known
 ///
diff --git a/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs b/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs
index 5e2a76ba254..33688c2e2ce 100644
--- a/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs
+++ b/tests/ui/feature-gates/feature-gate-sized-hierarchy.rs
@@ -3,8 +3,8 @@
 
 use std::marker::{MetaSized, PointeeSized};
 
-fn needs_pointeesized<T: ?Sized + PointeeSized>() {}
-fn needs_metasized<T: ?Sized + MetaSized>() {}
+fn needs_pointeesized<T: PointeeSized>() {}
+fn needs_metasized<T: MetaSized>() {}
 fn needs_sized<T: Sized>() {}
 
 fn main() {
diff --git a/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr b/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr
index 8cbea3b6ba4..6a35fcfb0e8 100644
--- a/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr
+++ b/tests/ui/feature-gates/feature-gate-sized-hierarchy.stderr
@@ -19,10 +19,10 @@ LL |     needs_metasized::<Foo>();
    |
    = help: the trait `MetaSized` is not implemented for `main::Foo`
 note: required by a bound in `needs_metasized`
-  --> $DIR/feature-gate-sized-hierarchy.rs:7:32
+  --> $DIR/feature-gate-sized-hierarchy.rs:7:23
    |
-LL | fn needs_metasized<T: ?Sized + MetaSized>() {}
-   |                                ^^^^^^^^^ required by this bound in `needs_metasized`
+LL | fn needs_metasized<T: MetaSized>() {}
+   |                       ^^^^^^^^^ required by this bound in `needs_metasized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
   --> $DIR/feature-gate-sized-hierarchy.rs:27:19
diff --git a/tests/ui/sized-hierarchy/alias-bounds.rs b/tests/ui/sized-hierarchy/alias-bounds.rs
new file mode 100644
index 00000000000..87b4bab11b7
--- /dev/null
+++ b/tests/ui/sized-hierarchy/alias-bounds.rs
@@ -0,0 +1,28 @@
+//@ check-pass
+//@ compile-flags: --crate-type=lib
+//@ revisions: old next
+//@[next] compile-flags: -Znext-solver
+#![feature(sized_hierarchy)]
+
+use std::marker::{PointeeSized, MetaSized};
+
+trait Id: PointeeSized {
+    type This: PointeeSized;
+}
+
+impl<T: PointeeSized> Id for T {
+    type This = T;
+}
+
+fn requires_metasized<T: MetaSized>() {}
+
+fn foo<T>()
+where
+    T: PointeeSized,
+    <T as Id>::This: Sized
+{
+    // `T: Sized` from where bounds (`T: PointeeSized` removes any default bounds and
+    // `<T as Id>::This: Sized` normalizes to `T: Sized`). This should trivially satisfy
+    // `T: MetaSized`.
+    requires_metasized::<T>();
+}
diff --git a/tests/ui/sized-hierarchy/default-bound.rs b/tests/ui/sized-hierarchy/default-bound.rs
new file mode 100644
index 00000000000..12b2eb2b5c1
--- /dev/null
+++ b/tests/ui/sized-hierarchy/default-bound.rs
@@ -0,0 +1,49 @@
+//@ check-fail
+#![feature(extern_types, sized_hierarchy)]
+
+use std::marker::{MetaSized, PointeeSized};
+
+fn bare<T>() {}
+
+
+fn sized<T: Sized>() {}
+
+fn neg_sized<T: ?Sized>() {}
+
+
+fn metasized<T: MetaSized>() {}
+
+fn neg_metasized<T: ?MetaSized>() {}
+//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+
+
+fn pointeesized<T: PointeeSized>() { }
+
+fn neg_pointeesized<T: ?PointeeSized>() { }
+//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+
+
+fn main() {
+    // Functions which should have a `T: Sized` bound - check for an error given a non-Sized type:
+
+    bare::<[u8]>();
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+    sized::<[u8]>();
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+    metasized::<[u8]>();
+    pointeesized::<[u8]>();
+
+    // Functions which should have a `T: MetaSized` bound - check for an error given a
+    // non-MetaSized type:
+    unsafe extern "C" {
+        type Foo;
+    }
+
+    bare::<Foo>();
+    //~^ ERROR the size for values of type `main::Foo` cannot be known
+    sized::<Foo>();
+    //~^ ERROR the size for values of type `main::Foo` cannot be known
+    metasized::<Foo>();
+    //~^ ERROR the size for values of type `main::Foo` cannot be known
+    pointeesized::<Foo>();
+}
diff --git a/tests/ui/sized-hierarchy/default-bound.stderr b/tests/ui/sized-hierarchy/default-bound.stderr
new file mode 100644
index 00000000000..22f0fa29d3e
--- /dev/null
+++ b/tests/ui/sized-hierarchy/default-bound.stderr
@@ -0,0 +1,88 @@
+error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/default-bound.rs:16:21
+   |
+LL | fn neg_metasized<T: ?MetaSized>() {}
+   |                     ^^^^^^^^^^
+
+error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default
+  --> $DIR/default-bound.rs:22:24
+   |
+LL | fn neg_pointeesized<T: ?PointeeSized>() { }
+   |                        ^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/default-bound.rs:29:12
+   |
+LL |     bare::<[u8]>();
+   |            ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by an implicit `Sized` bound in `bare`
+  --> $DIR/default-bound.rs:6:9
+   |
+LL | fn bare<T>() {}
+   |         ^ required by the implicit `Sized` requirement on this type parameter in `bare`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | fn bare<T: ?Sized>() {}
+   |          ++++++++
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/default-bound.rs:31:13
+   |
+LL |     sized::<[u8]>();
+   |             ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `sized`
+  --> $DIR/default-bound.rs:9:13
+   |
+LL | fn sized<T: Sized>() {}
+   |             ^^^^^ required by this bound in `sized`
+
+error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
+  --> $DIR/default-bound.rs:42:12
+   |
+LL |     bare::<Foo>();
+   |            ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `main::Foo`
+note: required by an implicit `Sized` bound in `bare`
+  --> $DIR/default-bound.rs:6:9
+   |
+LL | fn bare<T>() {}
+   |         ^ required by the implicit `Sized` requirement on this type parameter in `bare`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | fn bare<T: ?Sized>() {}
+   |          ++++++++
+
+error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
+  --> $DIR/default-bound.rs:44:13
+   |
+LL |     sized::<Foo>();
+   |             ^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `main::Foo`
+note: required by a bound in `sized`
+  --> $DIR/default-bound.rs:9:13
+   |
+LL | fn sized<T: Sized>() {}
+   |             ^^^^^ required by this bound in `sized`
+
+error[E0277]: the size for values of type `main::Foo` cannot be known
+  --> $DIR/default-bound.rs:46:17
+   |
+LL |     metasized::<Foo>();
+   |                 ^^^ doesn't have a known size
+   |
+   = help: the trait `MetaSized` is not implemented for `main::Foo`
+note: required by a bound in `metasized`
+  --> $DIR/default-bound.rs:14:17
+   |
+LL | fn metasized<T: MetaSized>() {}
+   |                 ^^^^^^^^^ required by this bound in `metasized`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/sized-hierarchy/default-supertrait.rs b/tests/ui/sized-hierarchy/default-supertrait.rs
new file mode 100644
index 00000000000..b25acf9e6ea
--- /dev/null
+++ b/tests/ui/sized-hierarchy/default-supertrait.rs
@@ -0,0 +1,61 @@
+//@ check-fail
+#![feature(sized_hierarchy)]
+
+use std::marker::{MetaSized, PointeeSized};
+
+trait Sized_: Sized { }
+
+trait NegSized: ?Sized { }
+//~^ ERROR `?Trait` is not permitted in supertraits
+
+trait MetaSized_: MetaSized { }
+
+trait NegMetaSized: ?MetaSized { }
+//~^ ERROR `?Trait` is not permitted in supertraits
+
+
+trait PointeeSized_: PointeeSized { }
+
+trait NegPointeeSized: ?PointeeSized { }
+//~^ ERROR `?Trait` is not permitted in supertraits
+
+trait Bare {}
+
+fn requires_sized<T: Sized>() {}
+fn requires_metasized<T: MetaSized>() {}
+fn requires_pointeesized<T: PointeeSized>() {}
+
+fn with_sized_supertrait<T: PointeeSized + Sized_>() {
+    requires_sized::<T>();
+    requires_metasized::<T>();
+    requires_pointeesized::<T>();
+}
+
+fn with_metasized_supertrait<T: PointeeSized + MetaSized_>() {
+    requires_sized::<T>();
+    //~^ ERROR the size for values of type `T` cannot be known at compilation time
+    requires_metasized::<T>();
+    requires_pointeesized::<T>();
+}
+
+// It isn't really possible to write this one..
+fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_>() {
+    requires_sized::<T>();
+    //~^ ERROR the size for values of type `T` cannot be known
+    requires_metasized::<T>();
+    //~^ ERROR the size for values of type `T` cannot be known
+    requires_pointeesized::<T>();
+}
+
+// `T` won't inherit the `const MetaSized` implicit supertrait of `Bare`, so there is an error on
+// the bound, which is expected.
+fn with_bare_trait<T: PointeeSized + Bare>() {
+//~^ ERROR the size for values of type `T` cannot be known
+    requires_sized::<T>();
+    //~^ ERROR the size for values of type `T` cannot be known
+    requires_metasized::<T>();
+    //~^ ERROR the size for values of type `T` cannot be known
+    requires_pointeesized::<T>();
+}
+
+fn main() { }
diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr
new file mode 100644
index 00000000000..de23936b900
--- /dev/null
+++ b/tests/ui/sized-hierarchy/default-supertrait.stderr
@@ -0,0 +1,125 @@
+error[E0658]: `?Trait` is not permitted in supertraits
+  --> $DIR/default-supertrait.rs:8:17
+   |
+LL | trait NegSized: ?Sized { }
+   |                 ^^^^^^
+   |
+   = note: traits are `?Sized` by default
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `?Trait` is not permitted in supertraits
+  --> $DIR/default-supertrait.rs:13:21
+   |
+LL | trait NegMetaSized: ?MetaSized { }
+   |                     ^^^^^^^^^^
+   |
+   = note: traits are `?MetaSized` by default
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `?Trait` is not permitted in supertraits
+  --> $DIR/default-supertrait.rs:19:24
+   |
+LL | trait NegPointeeSized: ?PointeeSized { }
+   |                        ^^^^^^^^^^^^^
+   |
+   = note: traits are `?PointeeSized` by default
+   = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0277]: the size for values of type `T` cannot be known
+  --> $DIR/default-supertrait.rs:52:38
+   |
+LL | fn with_bare_trait<T: PointeeSized + Bare>() {
+   |                                      ^^^^ doesn't have a known size
+   |
+note: required by a bound in `Bare`
+  --> $DIR/default-supertrait.rs:22:1
+   |
+LL | trait Bare {}
+   | ^^^^^^^^^^^^^ required by this bound in `Bare`
+help: consider further restricting type parameter `T` with unstable trait `MetaSized`
+   |
+LL | fn with_bare_trait<T: PointeeSized + Bare + std::marker::MetaSized>() {
+   |                                           ++++++++++++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/default-supertrait.rs:35:22
+   |
+LL | fn with_metasized_supertrait<T: PointeeSized + MetaSized_>() {
+   |                              - this type parameter needs to be `Sized`
+LL |     requires_sized::<T>();
+   |                      ^ doesn't have a size known at compile-time
+   |
+note: required by a bound in `requires_sized`
+  --> $DIR/default-supertrait.rs:24:22
+   |
+LL | fn requires_sized<T: Sized>() {}
+   |                      ^^^^^ required by this bound in `requires_sized`
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/default-supertrait.rs:43:22
+   |
+LL | fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_>() {
+   |                                 - this type parameter needs to be `Sized`
+LL |     requires_sized::<T>();
+   |                      ^ doesn't have a size known at compile-time
+   |
+note: required by a bound in `requires_sized`
+  --> $DIR/default-supertrait.rs:24:22
+   |
+LL | fn requires_sized<T: Sized>() {}
+   |                      ^^^^^ required by this bound in `requires_sized`
+
+error[E0277]: the size for values of type `T` cannot be known
+  --> $DIR/default-supertrait.rs:45:26
+   |
+LL |     requires_metasized::<T>();
+   |                          ^ doesn't have a known size
+   |
+note: required by a bound in `requires_metasized`
+  --> $DIR/default-supertrait.rs:25:26
+   |
+LL | fn requires_metasized<T: MetaSized>() {}
+   |                          ^^^^^^^^^ required by this bound in `requires_metasized`
+help: consider further restricting type parameter `T` with unstable trait `MetaSized`
+   |
+LL | fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_ + std::marker::MetaSized>() {
+   |                                                                 ++++++++++++++++++++++++
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/default-supertrait.rs:54:22
+   |
+LL | fn with_bare_trait<T: PointeeSized + Bare>() {
+   |                    - this type parameter needs to be `Sized`
+LL |
+LL |     requires_sized::<T>();
+   |                      ^ doesn't have a size known at compile-time
+   |
+note: required by a bound in `requires_sized`
+  --> $DIR/default-supertrait.rs:24:22
+   |
+LL | fn requires_sized<T: Sized>() {}
+   |                      ^^^^^ required by this bound in `requires_sized`
+
+error[E0277]: the size for values of type `T` cannot be known
+  --> $DIR/default-supertrait.rs:56:26
+   |
+LL |     requires_metasized::<T>();
+   |                          ^ doesn't have a known size
+   |
+note: required by a bound in `requires_metasized`
+  --> $DIR/default-supertrait.rs:25:26
+   |
+LL | fn requires_metasized<T: MetaSized>() {}
+   |                          ^^^^^^^^^ required by this bound in `requires_metasized`
+help: consider further restricting type parameter `T` with unstable trait `MetaSized`
+   |
+LL | fn with_bare_trait<T: PointeeSized + Bare + std::marker::MetaSized>() {
+   |                                           ++++++++++++++++++++++++
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0277, E0658.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/sized-hierarchy/extern-type-behind-ptr.rs b/tests/ui/sized-hierarchy/extern-type-behind-ptr.rs
new file mode 100644
index 00000000000..70a84aabf2c
--- /dev/null
+++ b/tests/ui/sized-hierarchy/extern-type-behind-ptr.rs
@@ -0,0 +1,20 @@
+//@ check-pass
+#![feature(extern_types, sized_hierarchy)]
+
+use std::marker::{MetaSized, PointeeSized};
+
+pub fn hash<T: PointeeSized>(_: *const T) {
+    unimplemented!();
+}
+
+unsafe extern "C" {
+    type Foo;
+}
+
+fn get() -> *const Foo {
+    unimplemented!()
+}
+
+fn main() {
+    hash::<Foo>(get());
+}
diff --git a/tests/ui/sized-hierarchy/impls.rs b/tests/ui/sized-hierarchy/impls.rs
index b05313dccae..601d837043e 100644
--- a/tests/ui/sized-hierarchy/impls.rs
+++ b/tests/ui/sized-hierarchy/impls.rs
@@ -1,8 +1,10 @@
 //@ check-fail
-//@ edition:2021
+//@ edition: 2024
+
 #![allow(incomplete_features, internal_features)]
 #![feature(sized_hierarchy)]
 #![feature(coroutines, dyn_star, extern_types, f16, never_type, unsized_fn_params)]
+
 use std::fmt::Debug;
 use std::marker::{MetaSized, PointeeSized};
 
@@ -11,11 +13,11 @@ use std::marker::{MetaSized, PointeeSized};
 fn needs_sized<T: Sized>() { }
 fn takes_sized<T: Sized>(_t: T) { }
 
-fn needs_metasized<T: ?Sized + MetaSized>() { }
-fn takes_metasized<T: ?Sized + MetaSized>(_t: T) { }
+fn needs_metasized<T: MetaSized>() { }
+fn takes_metasized<T: MetaSized>(_t: T) { }
 
-fn needs_pointeesized<T: ?Sized + PointeeSized>() { }
-fn takes_pointeesized<T: ?Sized + PointeeSized>(_t: T) { }
+fn needs_pointeesized<T: PointeeSized>() { }
+fn takes_pointeesized<T: PointeeSized>(_t: T) { }
 
 fn main() {
     // `bool`
@@ -173,7 +175,7 @@ fn main() {
     needs_pointeesized::<dyn Debug>();
 
     // `extern type`
-    extern "C" {
+    unsafe extern "C" {
         type Foo;
     }
     needs_sized::<Foo>();
diff --git a/tests/ui/sized-hierarchy/impls.stderr b/tests/ui/sized-hierarchy/impls.stderr
index 5fffe478663..02ccfebdc44 100644
--- a/tests/ui/sized-hierarchy/impls.stderr
+++ b/tests/ui/sized-hierarchy/impls.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:237:42
+  --> $DIR/impls.rs:239:42
    |
 LL |     struct StructAllFieldsMetaSized { x: [u8], y: [u8] }
    |                                          ^^^^ doesn't have a size known at compile-time
@@ -17,7 +17,7 @@ LL |     struct StructAllFieldsMetaSized { x: Box<[u8]>, y: [u8] }
    |                                          ++++    +
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:245:40
+  --> $DIR/impls.rs:247:40
    |
 LL |     struct StructAllFieldsUnsized { x: Foo, y: Foo }
    |                                        ^^^ doesn't have a size known at compile-time
@@ -35,7 +35,7 @@ LL |     struct StructAllFieldsUnsized { x: Box<Foo>, y: Foo }
    |                                        ++++   +
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:281:44
+  --> $DIR/impls.rs:283:44
    |
 LL |     enum EnumAllFieldsMetaSized { Qux { x: [u8], y: [u8] } }
    |                                            ^^^^ doesn't have a size known at compile-time
@@ -53,7 +53,7 @@ LL |     enum EnumAllFieldsMetaSized { Qux { x: Box<[u8]>, y: [u8] } }
    |                                            ++++    +
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:288:42
+  --> $DIR/impls.rs:290:42
    |
 LL |     enum EnumAllFieldsUnsized { Qux { x: Foo, y: Foo } }
    |                                          ^^^ doesn't have a size known at compile-time
@@ -71,7 +71,7 @@ LL |     enum EnumAllFieldsUnsized { Qux { x: Box<Foo>, y: Foo } }
    |                                          ++++   +
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:295:52
+  --> $DIR/impls.rs:297:52
    |
 LL |     enum EnumLastFieldMetaSized { Qux { x: u32, y: [u8] } }
    |                                                    ^^^^ doesn't have a size known at compile-time
@@ -89,7 +89,7 @@ LL |     enum EnumLastFieldMetaSized { Qux { x: u32, y: Box<[u8]> } }
    |                                                    ++++    +
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:302:50
+  --> $DIR/impls.rs:304:50
    |
 LL |     enum EnumLastFieldUnsized { Qux { x: u32, y: Foo } }
    |                                                  ^^^ doesn't have a size known at compile-time
@@ -107,72 +107,72 @@ LL |     enum EnumLastFieldUnsized { Qux { x: u32, y: Box<Foo> } }
    |                                                  ++++   +
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/impls.rs:158:19
+  --> $DIR/impls.rs:160:19
    |
 LL |     needs_sized::<str>();
    |                   ^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:164:19
+  --> $DIR/impls.rs:166:19
    |
 LL |     needs_sized::<[u8]>();
    |                   ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
-  --> $DIR/impls.rs:170:19
+  --> $DIR/impls.rs:172:19
    |
 LL |     needs_sized::<dyn Debug>();
    |                   ^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `dyn Debug`
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:179:19
+  --> $DIR/impls.rs:181:19
    |
 LL |     needs_sized::<Foo>();
    |                   ^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `main::Foo`
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known
-  --> $DIR/impls.rs:181:23
+  --> $DIR/impls.rs:183:23
    |
 LL |     needs_metasized::<Foo>();
    |                       ^^^ doesn't have a known size
    |
    = help: the trait `MetaSized` is not implemented for `main::Foo`
 note: required by a bound in `needs_metasized`
-  --> $DIR/impls.rs:14:32
+  --> $DIR/impls.rs:16:23
    |
-LL | fn needs_metasized<T: ?Sized + MetaSized>() { }
-   |                                ^^^^^^^^^ required by this bound in `needs_metasized`
+LL | fn needs_metasized<T: MetaSized>() { }
+   |                       ^^^^^^^^^ required by this bound in `needs_metasized`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:196:19
+  --> $DIR/impls.rs:198:19
    |
 LL |     needs_sized::<([u8], [u8])>();
    |                   ^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -181,7 +181,7 @@ LL |     needs_sized::<([u8], [u8])>();
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:198:23
+  --> $DIR/impls.rs:200:23
    |
 LL |     needs_metasized::<([u8], [u8])>();
    |                       ^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -190,7 +190,7 @@ LL |     needs_metasized::<([u8], [u8])>();
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:200:26
+  --> $DIR/impls.rs:202:26
    |
 LL |     needs_pointeesized::<([u8], [u8])>();
    |                          ^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -199,7 +199,7 @@ LL |     needs_pointeesized::<([u8], [u8])>();
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:204:19
+  --> $DIR/impls.rs:206:19
    |
 LL |     needs_sized::<(Foo, Foo)>();
    |                   ^^^^^^^^^^ doesn't have a size known at compile-time
@@ -208,7 +208,7 @@ LL |     needs_sized::<(Foo, Foo)>();
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:206:23
+  --> $DIR/impls.rs:208:23
    |
 LL |     needs_metasized::<(Foo, Foo)>();
    |                       ^^^^^^^^^^ doesn't have a size known at compile-time
@@ -217,7 +217,7 @@ LL |     needs_metasized::<(Foo, Foo)>();
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:208:26
+  --> $DIR/impls.rs:210:26
    |
 LL |     needs_pointeesized::<(Foo, Foo)>();
    |                          ^^^^^^^^^^ doesn't have a size known at compile-time
@@ -226,7 +226,7 @@ LL |     needs_pointeesized::<(Foo, Foo)>();
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:212:19
+  --> $DIR/impls.rs:214:19
    |
 LL |     needs_sized::<(u32, [u8])>();
    |                   ^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -234,13 +234,13 @@ LL |     needs_sized::<(u32, [u8])>();
    = help: within `(u32, [u8])`, the trait `Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `(u32, [u8])`
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:218:19
+  --> $DIR/impls.rs:220:19
    |
 LL |     needs_sized::<(u32, Foo)>();
    |                   ^^^^^^^^^^ doesn't have a size known at compile-time
@@ -248,13 +248,13 @@ LL |     needs_sized::<(u32, Foo)>();
    = help: within `(u32, main::Foo)`, the trait `Sized` is not implemented for `main::Foo`
    = note: required because it appears within the type `(u32, main::Foo)`
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known
-  --> $DIR/impls.rs:220:23
+  --> $DIR/impls.rs:222:23
    |
 LL |     needs_metasized::<(u32, Foo)>();
    |                       ^^^^^^^^^^ doesn't have a known size
@@ -262,118 +262,118 @@ LL |     needs_metasized::<(u32, Foo)>();
    = help: within `(u32, main::Foo)`, the trait `MetaSized` is not implemented for `main::Foo`
    = note: required because it appears within the type `(u32, main::Foo)`
 note: required by a bound in `needs_metasized`
-  --> $DIR/impls.rs:14:32
+  --> $DIR/impls.rs:16:23
    |
-LL | fn needs_metasized<T: ?Sized + MetaSized>() { }
-   |                                ^^^^^^^^^ required by this bound in `needs_metasized`
+LL | fn needs_metasized<T: MetaSized>() { }
+   |                       ^^^^^^^^^ required by this bound in `needs_metasized`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:239:19
+  --> $DIR/impls.rs:241:19
    |
 LL |     needs_sized::<StructAllFieldsMetaSized>();
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `StructAllFieldsMetaSized`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `StructAllFieldsMetaSized`
-  --> $DIR/impls.rs:237:12
+  --> $DIR/impls.rs:239:12
    |
 LL |     struct StructAllFieldsMetaSized { x: [u8], y: [u8] }
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:247:19
+  --> $DIR/impls.rs:249:19
    |
 LL |     needs_sized::<StructAllFieldsUnsized>();
    |                   ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `StructAllFieldsUnsized`, the trait `Sized` is not implemented for `main::Foo`
 note: required because it appears within the type `StructAllFieldsUnsized`
-  --> $DIR/impls.rs:245:12
+  --> $DIR/impls.rs:247:12
    |
 LL |     struct StructAllFieldsUnsized { x: Foo, y: Foo }
    |            ^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known
-  --> $DIR/impls.rs:249:23
+  --> $DIR/impls.rs:251:23
    |
 LL |     needs_metasized::<StructAllFieldsUnsized>();
    |                       ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size
    |
    = help: within `StructAllFieldsUnsized`, the trait `MetaSized` is not implemented for `main::Foo`
 note: required because it appears within the type `StructAllFieldsUnsized`
-  --> $DIR/impls.rs:245:12
+  --> $DIR/impls.rs:247:12
    |
 LL |     struct StructAllFieldsUnsized { x: Foo, y: Foo }
    |            ^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `needs_metasized`
-  --> $DIR/impls.rs:14:32
+  --> $DIR/impls.rs:16:23
    |
-LL | fn needs_metasized<T: ?Sized + MetaSized>() { }
-   |                                ^^^^^^^^^ required by this bound in `needs_metasized`
+LL | fn needs_metasized<T: MetaSized>() { }
+   |                       ^^^^^^^^^ required by this bound in `needs_metasized`
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/impls.rs:255:19
+  --> $DIR/impls.rs:257:19
    |
 LL |     needs_sized::<StructLastFieldMetaSized>();
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `StructLastFieldMetaSized`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `StructLastFieldMetaSized`
-  --> $DIR/impls.rs:254:12
+  --> $DIR/impls.rs:256:12
    |
 LL |     struct StructLastFieldMetaSized { x: u32, y: [u8] }
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known at compilation time
-  --> $DIR/impls.rs:262:19
+  --> $DIR/impls.rs:264:19
    |
 LL |     needs_sized::<StructLastFieldUnsized>();
    |                   ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `StructLastFieldUnsized`, the trait `Sized` is not implemented for `main::Foo`
 note: required because it appears within the type `StructLastFieldUnsized`
-  --> $DIR/impls.rs:261:12
+  --> $DIR/impls.rs:263:12
    |
 LL |     struct StructLastFieldUnsized { x: u32, y: Foo }
    |            ^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `needs_sized`
-  --> $DIR/impls.rs:11:19
+  --> $DIR/impls.rs:13:19
    |
 LL | fn needs_sized<T: Sized>() { }
    |                   ^^^^^ required by this bound in `needs_sized`
 
 error[E0277]: the size for values of type `main::Foo` cannot be known
-  --> $DIR/impls.rs:264:23
+  --> $DIR/impls.rs:266:23
    |
 LL |     needs_metasized::<StructLastFieldUnsized>();
    |                       ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a known size
    |
    = help: within `StructLastFieldUnsized`, the trait `MetaSized` is not implemented for `main::Foo`
 note: required because it appears within the type `StructLastFieldUnsized`
-  --> $DIR/impls.rs:261:12
+  --> $DIR/impls.rs:263:12
    |
 LL |     struct StructLastFieldUnsized { x: u32, y: Foo }
    |            ^^^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `needs_metasized`
-  --> $DIR/impls.rs:14:32
+  --> $DIR/impls.rs:16:23
    |
-LL | fn needs_metasized<T: ?Sized + MetaSized>() { }
-   |                                ^^^^^^^^^ required by this bound in `needs_metasized`
+LL | fn needs_metasized<T: MetaSized>() { }
+   |                       ^^^^^^^^^ required by this bound in `needs_metasized`
 
 error: aborting due to 26 previous errors
 
diff --git a/tests/ui/sized-hierarchy/pointee-supertrait.rs b/tests/ui/sized-hierarchy/pointee-supertrait.rs
new file mode 100644
index 00000000000..4bf486890bf
--- /dev/null
+++ b/tests/ui/sized-hierarchy/pointee-supertrait.rs
@@ -0,0 +1,28 @@
+//@ check-pass
+#![feature(sized_hierarchy)]
+
+// This is a reduction of some code in `library/core/src/cmp.rs` that would ICE if a default
+// `Pointee` bound is added - motivating the current status quo of `PointeeSized` being syntactic
+// sugar for an absense of any bounds whatsoever.
+
+use std::marker::PhantomData;
+
+pub trait Bar<'a> {
+    type Foo;
+}
+
+pub struct Foo<'a, T: Bar<'a>> {
+    phantom: PhantomData<&'a T>,
+}
+
+impl<'a, 'b, T> PartialEq<Foo<'b, T>> for Foo<'a, T>
+    where
+        T: for<'c> Bar<'c>,
+        <T as Bar<'a>>::Foo: PartialEq<<T as Bar<'b>>::Foo>,
+{
+    fn eq(&self, _: &Foo<'b, T>) -> bool {
+        loop {}
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/sized-hierarchy/trait-aliases.rs b/tests/ui/sized-hierarchy/trait-aliases.rs
new file mode 100644
index 00000000000..ffec302adaa
--- /dev/null
+++ b/tests/ui/sized-hierarchy/trait-aliases.rs
@@ -0,0 +1,9 @@
+//@ check-pass
+//@ compile-flags: --crate-type=lib
+#![feature(trait_alias)]
+
+// Checks that `?Sized` in a trait alias doesn't trigger an ICE.
+
+use std::ops::{Index, IndexMut};
+
+pub trait SlicePrereq<T> = ?Sized + IndexMut<usize, Output = <[T] as Index<usize>>::Output>;