about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/traits
diff options
context:
space:
mode:
authorTshepang Mbambo <tshepang@gmail.com>2025-04-19 16:06:07 +0200
committerGitHub <noreply@github.com>2025-04-19 16:06:07 +0200
commitb886a8e654ab660f2f2cd02c68bf170dd4918fd8 (patch)
tree86e6a9ab8518740ca6ce8deae8f409ee9c309f20 /compiler/rustc_trait_selection/src/traits
parent52616fa902a9a551ba4e574bee41dbf6162746f4 (diff)
parent07b7f00a9e961fdf66ece2ecf70ae1dba505f10e (diff)
Merge pull request #2347 from rust-lang/rustc-pull
Rustc pull update
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs50
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs31
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs99
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs25
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs6
12 files changed, 155 insertions, 137 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 1fca2f4da7e..02521c9453d 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -382,7 +382,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
                     for (new_region, old_region) in
                         iter::zip(new_args.regions(), old_args.regions())
                     {
-                        match (*new_region, *old_region) {
+                        match (new_region.kind(), old_region.kind()) {
                             // If both predicates have an `ReBound` (a HRTB) in the
                             // same spot, we do nothing.
                             (ty::ReBound(_, _), ty::ReBound(_, _)) => {}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index bcc247ba53c..93c7dae9c5b 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -537,7 +537,7 @@ fn plug_infer_with_placeholders<'tcx>(
         }
 
         fn visit_region(&mut self, r: ty::Region<'tcx>) {
-            if let ty::ReVar(vid) = *r {
+            if let ty::ReVar(vid) = r.kind() {
                 let r = self
                     .infcx
                     .inner
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index fa6bbf1d6e5..519394685a8 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -188,7 +188,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span
     tcx.associated_items(trait_def_id)
         .in_definition_order()
         // We're only looking at associated type bounds
-        .filter(|item| item.kind == ty::AssocKind::Type)
+        .filter(|item| item.is_type())
         // Ignore GATs with `Self: Sized`
         .filter(|item| !tcx.generics_require_sized_self(item.def_id))
         .flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied())
@@ -298,31 +298,33 @@ pub fn dyn_compatibility_violations_for_assoc_item(
     match item.kind {
         // Associated consts are never dyn-compatible, as they can't have `where` bounds yet at all,
         // and associated const bounds in trait objects aren't a thing yet either.
-        ty::AssocKind::Const => {
-            vec![DynCompatibilityViolation::AssocConst(item.name, item.ident(tcx).span)]
+        ty::AssocKind::Const { name } => {
+            vec![DynCompatibilityViolation::AssocConst(name, item.ident(tcx).span)]
         }
-        ty::AssocKind::Fn => virtual_call_violations_for_method(tcx, trait_def_id, item)
-            .into_iter()
-            .map(|v| {
-                let node = tcx.hir_get_if_local(item.def_id);
-                // Get an accurate span depending on the violation.
-                let span = match (&v, node) {
-                    (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
-                    (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
-                    (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
-                    (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
-                        node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
-                    }
-                    _ => item.ident(tcx).span,
-                };
+        ty::AssocKind::Fn { name, .. } => {
+            virtual_call_violations_for_method(tcx, trait_def_id, item)
+                .into_iter()
+                .map(|v| {
+                    let node = tcx.hir_get_if_local(item.def_id);
+                    // Get an accurate span depending on the violation.
+                    let span = match (&v, node) {
+                        (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
+                        (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
+                        (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span,
+                        (MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
+                            node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span())
+                        }
+                        _ => item.ident(tcx).span,
+                    };
 
-                DynCompatibilityViolation::Method(item.name, v, span)
-            })
-            .collect(),
+                    DynCompatibilityViolation::Method(name, v, span)
+                })
+                .collect()
+        }
         // Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
-        ty::AssocKind::Type => {
+        ty::AssocKind::Type { .. } => {
             if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
-                vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)]
+                vec![DynCompatibilityViolation::GAT(item.name(), item.ident(tcx).span)]
             } else {
                 // We will permit associated types if they are explicitly mentioned in the trait object.
                 // We can't check this here, as here we only check if it is guaranteed to not be possible.
@@ -344,7 +346,7 @@ fn virtual_call_violations_for_method<'tcx>(
     let sig = tcx.fn_sig(method.def_id).instantiate_identity();
 
     // The method's first parameter must be named `self`
-    if !method.fn_has_self_parameter {
+    if !method.is_method() {
         let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
             generics,
             kind: hir::TraitItemKind::Fn(sig, _),
@@ -797,7 +799,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEscapingBoundRegions<'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        if let ty::ReBound(debruijn, _) = *r
+        if let ty::ReBound(debruijn, _) = r.kind()
             && debruijn < self.binder
         {
             r
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index e98a240a53f..1b76d48e431 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -24,10 +24,10 @@ use super::{
 };
 use crate::error_reporting::InferCtxtErrorExt;
 use crate::infer::{InferCtxt, TyOrConstInferVar};
-use crate::traits::EvaluateConstErr;
 use crate::traits::normalize::normalize_with_depth_to;
 use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _};
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
+use crate::traits::{EvaluateConstErr, sizedness_fast_path};
 
 pub(crate) type PendingPredicateObligations<'tcx> = ThinVec<PendingPredicateObligation<'tcx>>;
 
@@ -335,6 +335,10 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
         let infcx = self.selcx.infcx;
 
+        if sizedness_fast_path(infcx.tcx, obligation.predicate) {
+            return ProcessResult::Changed(thin_vec::thin_vec![]);
+        }
+
         if obligation.predicate.has_aliases() {
             let mut obligations = PredicateObligations::new();
             let predicate = normalize_with_depth_to(
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index de337710b5e..0987c5b42d8 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -65,8 +65,8 @@ pub use self::specialize::{
 pub use self::structural_normalize::StructurallyNormalizeExt;
 pub use self::util::{
     BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final,
-    supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, upcast_choices,
-    with_replaced_escaping_bound_vars,
+    sizedness_fast_path, supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item,
+    upcast_choices, with_replaced_escaping_bound_vars,
 };
 use crate::error_reporting::InferCtxtErrorExt;
 use crate::infer::outlives::env::OutlivesEnvironment;
@@ -643,7 +643,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
 ) -> GenericArgsRef<'tcx> {
     struct ReplaceParamAndInferWithPlaceholder<'tcx> {
         tcx: TyCtxt<'tcx>,
-        idx: u32,
+        idx: ty::BoundVar,
     }
 
     impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceParamAndInferWithPlaceholder<'tcx> {
@@ -653,19 +653,13 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
 
         fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             if let ty::Infer(_) = t.kind() {
-                let idx = {
-                    let idx = self.idx;
-                    self.idx += 1;
-                    idx
-                };
+                let idx = self.idx;
+                self.idx += 1;
                 Ty::new_placeholder(
                     self.tcx,
                     ty::PlaceholderType {
                         universe: ty::UniverseIndex::ROOT,
-                        bound: ty::BoundTy {
-                            var: ty::BoundVar::from_u32(idx),
-                            kind: ty::BoundTyKind::Anon,
-                        },
+                        bound: ty::BoundTy { var: idx, kind: ty::BoundTyKind::Anon },
                     },
                 )
             } else {
@@ -675,16 +669,11 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
 
         fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
             if let ty::ConstKind::Infer(_) = c.kind() {
+                let idx = self.idx;
+                self.idx += 1;
                 ty::Const::new_placeholder(
                     self.tcx,
-                    ty::PlaceholderConst {
-                        universe: ty::UniverseIndex::ROOT,
-                        bound: ty::BoundVar::from_u32({
-                            let idx = self.idx;
-                            self.idx += 1;
-                            idx
-                        }),
-                    },
+                    ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, bound: idx },
                 )
             } else {
                 c.super_fold_with(self)
@@ -692,7 +681,7 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
         }
     }
 
-    args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
+    args.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: ty::BoundVar::ZERO })
 }
 
 /// Normalizes the predicates and checks whether they hold in an empty environment. If this
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 349569d750e..0dce504903c 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -669,30 +669,11 @@ fn project<'cx, 'tcx>(
 
     match candidates {
         ProjectionCandidateSet::Single(candidate) => {
-            Ok(Projected::Progress(confirm_candidate(selcx, obligation, candidate)))
+            confirm_candidate(selcx, obligation, candidate)
         }
         ProjectionCandidateSet::None => {
             let tcx = selcx.tcx();
-            let term = match tcx.def_kind(obligation.predicate.def_id) {
-                DefKind::AssocTy => Ty::new_projection_from_args(
-                    tcx,
-                    obligation.predicate.def_id,
-                    obligation.predicate.args,
-                )
-                .into(),
-                DefKind::AssocConst => ty::Const::new_unevaluated(
-                    tcx,
-                    ty::UnevaluatedConst::new(
-                        obligation.predicate.def_id,
-                        obligation.predicate.args,
-                    ),
-                )
-                .into(),
-                kind => {
-                    bug!("unknown projection def-id: {}", kind.descr(obligation.predicate.def_id))
-                }
-            };
-
+            let term = obligation.predicate.to_term(tcx);
             Ok(Projected::NoProgress(term))
         }
         // Error occurred while trying to processing impls.
@@ -1244,18 +1225,16 @@ fn confirm_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTermObligation<'tcx>,
     candidate: ProjectionCandidate<'tcx>,
-) -> Progress<'tcx> {
+) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
     debug!(?obligation, ?candidate, "confirm_candidate");
-    let mut progress = match candidate {
+    let mut result = match candidate {
         ProjectionCandidate::ParamEnv(poly_projection)
-        | ProjectionCandidate::Object(poly_projection) => {
-            confirm_param_env_candidate(selcx, obligation, poly_projection, false)
-        }
-
-        ProjectionCandidate::TraitDef(poly_projection) => {
-            confirm_param_env_candidate(selcx, obligation, poly_projection, true)
-        }
-
+        | ProjectionCandidate::Object(poly_projection) => Ok(Projected::Progress(
+            confirm_param_env_candidate(selcx, obligation, poly_projection, false),
+        )),
+        ProjectionCandidate::TraitDef(poly_projection) => Ok(Projected::Progress(
+            confirm_param_env_candidate(selcx, obligation, poly_projection, true),
+        )),
         ProjectionCandidate::Select(impl_source) => {
             confirm_select_candidate(selcx, obligation, impl_source)
         }
@@ -1266,23 +1245,26 @@ fn confirm_candidate<'cx, 'tcx>(
     // with new region variables, we need to resolve them to existing variables
     // when possible for this to work. See `auto-trait-projection-recursion.rs`
     // for a case where this matters.
-    if progress.term.has_infer_regions() {
+    if let Ok(Projected::Progress(progress)) = &mut result
+        && progress.term.has_infer_regions()
+    {
         progress.term = progress.term.fold_with(&mut OpportunisticRegionResolver::new(selcx.infcx));
     }
-    progress
+
+    result
 }
 
 fn confirm_select_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTermObligation<'tcx>,
     impl_source: Selection<'tcx>,
-) -> Progress<'tcx> {
+) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
     match impl_source {
         ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data),
         ImplSource::Builtin(BuiltinImplSource::Misc | BuiltinImplSource::Trivial, data) => {
             let tcx = selcx.tcx();
             let trait_def_id = obligation.predicate.trait_def_id(tcx);
-            if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) {
+            let progress = if tcx.is_lang_item(trait_def_id, LangItem::Coroutine) {
                 confirm_coroutine_candidate(selcx, obligation, data)
             } else if tcx.is_lang_item(trait_def_id, LangItem::Future) {
                 confirm_future_candidate(selcx, obligation, data)
@@ -1304,7 +1286,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
                 confirm_async_fn_kind_helper_candidate(selcx, obligation, data)
             } else {
                 confirm_builtin_candidate(selcx, obligation, data)
-            }
+            };
+            Ok(Projected::Progress(progress))
         }
         ImplSource::Builtin(BuiltinImplSource::Object { .. }, _)
         | ImplSource::Param(..)
@@ -1410,7 +1393,7 @@ fn confirm_future_candidate<'cx, 'tcx>(
         coroutine_sig,
     );
 
-    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Output);
+    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Output);
 
     let predicate = ty::ProjectionPredicate {
         projection_term: ty::AliasTerm::new_from_args(
@@ -1456,7 +1439,7 @@ fn confirm_iterator_candidate<'cx, 'tcx>(
         gen_sig,
     );
 
-    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
+    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Item);
 
     let predicate = ty::ProjectionPredicate {
         projection_term: ty::AliasTerm::new_from_args(
@@ -1502,7 +1485,7 @@ fn confirm_async_iterator_candidate<'cx, 'tcx>(
         gen_sig,
     );
 
-    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name, sym::Item);
+    debug_assert_eq!(tcx.associated_item(obligation.predicate.def_id).name(), sym::Item);
 
     let ty::Adt(_poll_adt, args) = *yield_ty.kind() else {
         bug!();
@@ -2000,7 +1983,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     selcx: &mut SelectionContext<'cx, 'tcx>,
     obligation: &ProjectionTermObligation<'tcx>,
     impl_impl_source: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
+) -> Result<Projected<'tcx>, ProjectionError<'tcx>> {
     let tcx = selcx.tcx();
 
     let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source;
@@ -2011,19 +1994,34 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let param_env = obligation.param_env;
     let assoc_ty = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {
         Ok(assoc_ty) => assoc_ty,
-        Err(guar) => return Progress::error(tcx, guar),
+        Err(guar) => return Ok(Projected::Progress(Progress::error(tcx, guar))),
     };
+
+    // This means that the impl is missing a definition for the
+    // associated type. This is either because the associate item
+    // has impossible-to-satisfy predicates (since those were
+    // allowed in <https://github.com/rust-lang/rust/pull/135480>),
+    // or because the impl is literally missing the definition.
     if !assoc_ty.item.defaultness(tcx).has_value() {
-        // This means that the impl is missing a definition for the
-        // associated type. This error will be reported by the type
-        // checker method `check_impl_items_against_trait`, so here we
-        // just return Error.
         debug!(
             "confirm_impl_candidate: no associated type {:?} for {:?}",
-            assoc_ty.item.name, obligation.predicate
+            assoc_ty.item.name(),
+            obligation.predicate
         );
-        return Progress { term: Ty::new_misc_error(tcx).into(), obligations: nested };
+        if tcx.impl_self_is_guaranteed_unsized(impl_def_id) {
+            // We treat this projection as rigid here, which is represented via
+            // `Projected::NoProgress`. This will ensure that the projection is
+            // checked for well-formedness, and it's either satisfied by a trivial
+            // where clause in its env or it results in an error.
+            return Ok(Projected::NoProgress(obligation.predicate.to_term(tcx)));
+        } else {
+            return Ok(Projected::Progress(Progress {
+                term: Ty::new_misc_error(tcx).into(),
+                obligations: nested,
+            }));
+        }
     }
+
     // If we're trying to normalize `<Vec<u32> as X>::A<S>` using
     //`impl<T> X for Vec<T> { type A<Y> = Box<Y>; }`, then:
     //
@@ -2033,6 +2031,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args);
     let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node);
     let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
+
     let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const {
         let did = assoc_ty.item.def_id;
         let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did);
@@ -2041,7 +2040,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     } else {
         tcx.type_of(assoc_ty.item.def_id).map_bound(|ty| ty.into())
     };
-    if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
+
+    let progress = if !tcx.check_args_compatible(assoc_ty.item.def_id, args) {
         let err = Ty::new_error_with_message(
             tcx,
             obligation.cause.span,
@@ -2051,7 +2051,8 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     } else {
         assoc_ty_own_obligations(selcx, obligation, &mut nested);
         Progress { term: term.instantiate(tcx, args), obligations: nested }
-    }
+    };
+    Ok(Projected::Progress(progress))
 }
 
 // Get obligations corresponding to the predicates from the where-clause of the
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 5dbb4382fd1..507932699c7 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -144,7 +144,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
 
     #[inline]
     fn visit_region(&mut self, r: ty::Region<'tcx>) {
-        match *r {
+        match r.kind() {
             ty::ReBound(debruijn, _) if debruijn > self.outer_index => {
                 self.escaping =
                     self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index 4f9e2e79d62..87fc532adaf 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -1,4 +1,3 @@
-use rustc_hir::LangItem;
 use rustc_infer::traits::Obligation;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::query::NoSolution;
@@ -7,7 +6,7 @@ use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
 use rustc_span::Span;
 
 use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
-use crate::traits::ObligationCtxt;
+use crate::traits::{ObligationCtxt, sizedness_fast_path};
 
 impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
     type QueryResponse = ();
@@ -16,15 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
         tcx: TyCtxt<'tcx>,
         key: &ParamEnvAnd<'tcx, Self>,
     ) -> Option<Self::QueryResponse> {
-        // Proving Sized, very often on "obviously sized" types like
-        // `&T`, accounts for about 60% percentage of the predicates
-        // we have to prove. No need to canonicalize and all that for
-        // such cases.
-        if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
-            key.value.predicate.kind().skip_binder()
-            && tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized)
-            && trait_ref.self_ty().is_trivially_sized(tcx)
-        {
+        if sizedness_fast_path(tcx, key.value.predicate) {
             return Some(());
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 2cb7d2d8931..d71d1e9ae0f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -317,7 +317,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
                     obligation.param_env,
-                    obligation.predicate.rebind(trait_ref),
+                    trait_ref,
                 )
             };
 
@@ -343,7 +343,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     obligation.cause.clone(),
                     obligation.recursion_depth + 1,
                     obligation.param_env,
-                    obligation.predicate.rebind(outlives),
+                    outlives,
                 )
             };
 
@@ -404,7 +404,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         }
 
-        let predicate = obligation.predicate.skip_binder();
+        let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate);
 
         let mut assume = predicate.trait_ref.args.const_at(2);
         // FIXME(mgca): We should shallowly normalize this.
@@ -594,9 +594,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // Associated types that require `Self: Sized` do not show up in the built-in
             // implementation of `Trait for dyn Trait`, and can be dropped here.
             .filter(|item| !tcx.generics_require_sized_self(item.def_id))
-            .filter_map(
-                |item| if item.kind == ty::AssocKind::Type { Some(item.def_id) } else { None },
-            )
+            .filter_map(|item| if item.is_type() { Some(item.def_id) } else { None })
             .collect();
 
         for assoc_type in assoc_types {
@@ -1090,26 +1088,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             {
                 // See `assemble_candidates_for_unsizing` for more info.
                 // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`.
-                let iter = data_a
-                    .principal()
-                    .filter(|_| {
-                        // optionally drop the principal, if we're unsizing to no principal
-                        data_b.principal().is_some()
-                    })
-                    .map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
-                    .into_iter()
-                    .chain(
+                let existential_predicates = if data_b.principal().is_some() {
+                    tcx.mk_poly_existential_predicates_from_iter(
                         data_a
-                            .projection_bounds()
-                            .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
+                            .principal()
+                            .map(|b| b.map_bound(ty::ExistentialPredicate::Trait))
+                            .into_iter()
+                            .chain(
+                                data_a
+                                    .projection_bounds()
+                                    .map(|b| b.map_bound(ty::ExistentialPredicate::Projection)),
+                            )
+                            .chain(
+                                data_b
+                                    .auto_traits()
+                                    .map(ty::ExistentialPredicate::AutoTrait)
+                                    .map(ty::Binder::dummy),
+                            ),
                     )
-                    .chain(
+                } else {
+                    // If we're unsizing to a dyn type that has no principal, then drop
+                    // the principal and projections from the type. We use the auto traits
+                    // from the RHS type since as we noted that we've checked for auto
+                    // trait compatibility during unsizing.
+                    tcx.mk_poly_existential_predicates_from_iter(
                         data_b
                             .auto_traits()
                             .map(ty::ExistentialPredicate::AutoTrait)
                             .map(ty::Binder::dummy),
-                    );
-                let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
+                    )
+                };
                 let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a);
 
                 // Require that the traits involved in this upcast are **equal**;
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 56ff46e89e7..4d88a23250a 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -49,7 +49,9 @@ use crate::infer::{InferCtxt, InferOk, TypeFreshener};
 use crate::solve::InferCtxtSelectExt as _;
 use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
 use crate::traits::project::{ProjectAndUnifyResult, ProjectionCacheKeyExt};
-use crate::traits::{EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects};
+use crate::traits::{
+    EvaluateConstErr, ProjectionCacheKey, Unimplemented, effects, sizedness_fast_path,
+};
 
 mod _match;
 mod candidate_assembly;
@@ -603,6 +605,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             None => self.check_recursion_limit(&obligation, &obligation)?,
         }
 
+        if sizedness_fast_path(self.tcx(), obligation.predicate) {
+            return Ok(EvaluatedToOk);
+        }
+
         ensure_sufficient_stack(|| {
             let bound_predicate = obligation.predicate.kind();
             match bound_predicate.skip_binder() {
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 15f5cf916a4..035fd38c48a 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -1,6 +1,7 @@
 use std::collections::{BTreeMap, VecDeque};
 
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
+use rustc_hir::LangItem;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::InferCtxt;
 pub use rustc_infer::traits::util::*;
@@ -289,7 +290,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
+        match r.kind() {
             ty::ReBound(debruijn, _)
                 if debruijn.as_usize()
                     >= self.current_index.as_usize() + self.universe_indices.len() =>
@@ -407,7 +408,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
     }
 
     fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        let r1 = match *r0 {
+        let r1 = match r0.kind() {
             ty::ReVar(vid) => self
                 .infcx
                 .inner
@@ -417,7 +418,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
             _ => r0,
         };
 
-        let r2 = match *r1 {
+        let r2 = match r1.kind() {
             ty::RePlaceholder(p) => {
                 let replace_var = self.mapped_regions.get(&p);
                 match replace_var {
@@ -504,3 +505,21 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
         }
     }
 }
+
+pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>) -> bool {
+    // Proving `Sized` very often on "obviously sized" types like `&T`, accounts for about 60%
+    // percentage of the predicates we have to prove. No need to canonicalize and all that for
+    // such cases.
+    if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
+        predicate.kind().skip_binder()
+    {
+        if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized)
+            && trait_ref.self_ty().is_trivially_sized(tcx)
+        {
+            debug!("fast path -- trivial sizedness");
+            return true;
+        }
+    }
+
+    false
+}
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 165174c0bcc..3565c11249a 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -197,10 +197,8 @@ fn own_existential_vtable_entries_iter(
     tcx: TyCtxt<'_>,
     trait_def_id: DefId,
 ) -> impl Iterator<Item = DefId> {
-    let trait_methods = tcx
-        .associated_items(trait_def_id)
-        .in_definition_order()
-        .filter(|item| item.kind == ty::AssocKind::Fn);
+    let trait_methods =
+        tcx.associated_items(trait_def_id).in_definition_order().filter(|item| item.is_fn());
 
     // Now list each method's DefId (for within its trait).
     let own_entries = trait_methods.filter_map(move |&trait_method| {