about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/traits
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs53
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs96
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs69
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs58
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs117
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs177
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs28
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs51
15 files changed, 490 insertions, 242 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 7ee9eb45309..3b40882ef57 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -368,9 +368,10 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
                 overflowing_predicates: ambiguities
                     .into_iter()
                     .filter(|error| {
-                        matches!(error.code, FulfillmentErrorCode::Ambiguity {
-                            overflow: Some(true)
-                        })
+                        matches!(
+                            error.code,
+                            FulfillmentErrorCode::Ambiguity { overflow: Some(true) }
+                        )
                     })
                     .map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate))
                     .collect(),
@@ -491,13 +492,16 @@ fn plug_infer_with_placeholders<'tcx>(
                         // Comparing against a type variable never registers hidden types anyway
                         DefineOpaqueTypes::Yes,
                         ty,
-                        Ty::new_placeholder(self.infcx.tcx, ty::Placeholder {
-                            universe: self.universe,
-                            bound: ty::BoundTy {
-                                var: self.next_var(),
-                                kind: ty::BoundTyKind::Anon,
+                        Ty::new_placeholder(
+                            self.infcx.tcx,
+                            ty::Placeholder {
+                                universe: self.universe,
+                                bound: ty::BoundTy {
+                                    var: self.next_var(),
+                                    kind: ty::BoundTyKind::Anon,
+                                },
                             },
-                        }),
+                        ),
                     )
                 else {
                     bug!("we always expect to be able to plug an infer var with placeholder")
@@ -517,10 +521,10 @@ fn plug_infer_with_placeholders<'tcx>(
                         // registration happening anyway.
                         DefineOpaqueTypes::Yes,
                         ct,
-                        ty::Const::new_placeholder(self.infcx.tcx, ty::Placeholder {
-                            universe: self.universe,
-                            bound: self.next_var(),
-                        }),
+                        ty::Const::new_placeholder(
+                            self.infcx.tcx,
+                            ty::Placeholder { universe: self.universe, bound: self.next_var() },
+                        ),
                     )
                 else {
                     bug!("we always expect to be able to plug an infer var with placeholder")
@@ -545,13 +549,16 @@ fn plug_infer_with_placeholders<'tcx>(
                             // Lifetimes don't contain opaque types (or any types for that matter).
                             DefineOpaqueTypes::Yes,
                             r,
-                            ty::Region::new_placeholder(self.infcx.tcx, ty::Placeholder {
-                                universe: self.universe,
-                                bound: ty::BoundRegion {
-                                    var: self.next_var(),
-                                    kind: ty::BoundRegionKind::Anon,
+                            ty::Region::new_placeholder(
+                                self.infcx.tcx,
+                                ty::Placeholder {
+                                    universe: self.universe,
+                                    bound: ty::BoundRegion {
+                                        var: self.next_var(),
+                                        kind: ty::BoundRegionKind::Anon,
+                                    },
                                 },
-                            }),
+                            ),
                         )
                     else {
                         bug!("we always expect to be able to plug an infer var with placeholder")
@@ -763,9 +770,9 @@ fn search_ambiguity_causes<'tcx>(
     causes: &mut FxIndexSet<IntercrateAmbiguityCause<'tcx>>,
 ) {
     infcx.probe(|_| {
-        infcx.visit_proof_tree(goal, &mut AmbiguityCausesVisitor {
-            cache: Default::default(),
-            causes,
-        })
+        infcx.visit_proof_tree(
+            goal,
+            &mut AmbiguityCausesVisitor { cache: Default::default(), causes },
+        )
     });
 }
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index 617bc87a9d2..740f44ebcad 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -128,8 +128,7 @@ fn sized_trait_bound_spans<'tcx>(
 }
 
 fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
-    tcx.hir()
-        .get_if_local(trait_def_id)
+    tcx.hir_get_if_local(trait_def_id)
         .and_then(|node| match node {
             hir::Node::Item(hir::Item {
                 kind: hir::ItemKind::Trait(.., generics, bounds, _),
@@ -187,7 +186,10 @@ fn predicates_reference_self(
 fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
     tcx.associated_items(trait_def_id)
         .in_definition_order()
+        // We're only looking at associated type bounds
         .filter(|item| item.kind == ty::AssocKind::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())
         .filter_map(|(clause, sp)| {
             // Item bounds *can* have self projections, since they never get
@@ -301,7 +303,7 @@ pub fn dyn_compatibility_violations_for_assoc_item(
         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);
+                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,
@@ -346,7 +348,7 @@ fn virtual_call_violations_for_method<'tcx>(
             generics,
             kind: hir::TraitItemKind::Fn(sig, _),
             ..
-        })) = tcx.hir().get_if_local(method.def_id).as_ref()
+        })) = tcx.hir_get_if_local(method.def_id).as_ref()
         {
             let sm = tcx.sess.source_map();
             Some((
@@ -380,7 +382,7 @@ fn virtual_call_violations_for_method<'tcx>(
             let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
                 kind: hir::TraitItemKind::Fn(sig, _),
                 ..
-            })) = tcx.hir().get_if_local(method.def_id).as_ref()
+            })) = tcx.hir_get_if_local(method.def_id).as_ref()
             {
                 Some(sig.decl.inputs[i].span)
             } else {
@@ -418,7 +420,7 @@ fn virtual_call_violations_for_method<'tcx>(
             let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
                 kind: hir::TraitItemKind::Fn(sig, _),
                 ..
-            })) = tcx.hir().get_if_local(method.def_id).as_ref()
+            })) = tcx.hir_get_if_local(method.def_id).as_ref()
             {
                 Some(sig.decl.inputs[0].span)
             } else {
@@ -696,11 +698,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
                     ControlFlow::Continue(())
                 }
             }
-            ty::Alias(ty::Projection, ref data) if self.tcx.is_impl_trait_in_trait(data.def_id) => {
+            ty::Alias(ty::Projection, data) if self.tcx.is_impl_trait_in_trait(data.def_id) => {
                 // We'll deny these later in their own pass
                 ControlFlow::Continue(())
             }
-            ty::Alias(ty::Projection, ref data) => {
+            ty::Alias(ty::Projection, data) => {
                 match self.allow_self_projections {
                     AllowSelfProjections::Yes => {
                         // This is a projected type `<Foo as SomeTrait>::X`.
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index f2d2dd2f3ce..e39f8e673db 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -1,6 +1,5 @@
 use std::marker::PhantomData;
 
-use rustc_data_structures::captures::Captures;
 use rustc_data_structures::obligation_forest::{
     Error, ForestObligation, ObligationForest, ObligationProcessor, Outcome, ProcessResult,
 };
@@ -900,10 +899,10 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
 }
 
 /// Returns the set of inference variables contained in `args`.
-fn args_infer_vars<'a, 'tcx>(
-    selcx: &SelectionContext<'a, 'tcx>,
+fn args_infer_vars<'tcx>(
+    selcx: &SelectionContext<'_, 'tcx>,
     args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
-) -> impl Iterator<Item = TyOrConstInferVar> + Captures<'tcx> {
+) -> impl Iterator<Item = TyOrConstInferVar> {
     selcx
         .infcx
         .resolve_vars_if_possible(args)
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index 79e178150de..a4b6f330b9d 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -208,7 +208,7 @@ pub fn all_fields_implement_trait<'tcx>(
             }
 
             let field_span = tcx.def_span(field.did);
-            let field_ty_span = match tcx.hir().get_if_local(field.did) {
+            let field_ty_span = match tcx.hir_get_if_local(field.did) {
                 Some(hir::Node::Field(field_def)) => field_def.ty.span,
                 _ => field_span,
             };
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index d4a9664e282..105cb917571 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -660,13 +660,16 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
                     self.idx += 1;
                     idx
                 };
-                Ty::new_placeholder(self.tcx, ty::PlaceholderType {
-                    universe: ty::UniverseIndex::ROOT,
-                    bound: ty::BoundTy {
-                        var: ty::BoundVar::from_u32(idx),
-                        kind: ty::BoundTyKind::Anon,
+                Ty::new_placeholder(
+                    self.tcx,
+                    ty::PlaceholderType {
+                        universe: ty::UniverseIndex::ROOT,
+                        bound: ty::BoundTy {
+                            var: ty::BoundVar::from_u32(idx),
+                            kind: ty::BoundTyKind::Anon,
+                        },
                     },
-                })
+                )
             } else {
                 t.super_fold_with(self)
             }
@@ -674,14 +677,17 @@ 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() {
-                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::Const::new_placeholder(
+                    self.tcx,
+                    ty::PlaceholderConst {
+                        universe: ty::UniverseIndex::ROOT,
+                        bound: ty::BoundVar::from_u32({
+                            let idx = self.idx;
+                            self.idx += 1;
+                            idx
+                        }),
+                    },
+                )
             } else {
                 c.super_fold_with(self)
             }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 537b042bde5..de5aaa5bd97 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1670,14 +1670,18 @@ fn confirm_closure_candidate<'cx, 'tcx>(
                 } else {
                     let upvars_projection_def_id =
                         tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
-                    let tupled_upvars_ty = Ty::new_projection(tcx, upvars_projection_def_id, [
-                        ty::GenericArg::from(kind_ty),
-                        Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce).into(),
-                        tcx.lifetimes.re_static.into(),
-                        sig.tupled_inputs_ty.into(),
-                        args.tupled_upvars_ty().into(),
-                        args.coroutine_captures_by_ref_ty().into(),
-                    ]);
+                    let tupled_upvars_ty = Ty::new_projection(
+                        tcx,
+                        upvars_projection_def_id,
+                        [
+                            ty::GenericArg::from(kind_ty),
+                            Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce).into(),
+                            tcx.lifetimes.re_static.into(),
+                            sig.tupled_inputs_ty.into(),
+                            args.tupled_upvars_ty().into(),
+                            args.coroutine_captures_by_ref_ty().into(),
+                        ],
+                    );
                     sig.to_coroutine(
                         tcx,
                         args.parent_args(),
@@ -1795,14 +1799,18 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                         // will project to the right upvars for the generator, appending the inputs and
                         // coroutine upvars respecting the closure kind.
                         // N.B. No need to register a `AsyncFnKindHelper` goal here, it's already in `nested`.
-                        let tupled_upvars_ty = Ty::new_projection(tcx, upvars_projection_def_id, [
-                            ty::GenericArg::from(kind_ty),
-                            Ty::from_closure_kind(tcx, goal_kind).into(),
-                            env_region.into(),
-                            sig.tupled_inputs_ty.into(),
-                            args.tupled_upvars_ty().into(),
-                            args.coroutine_captures_by_ref_ty().into(),
-                        ]);
+                        let tupled_upvars_ty = Ty::new_projection(
+                            tcx,
+                            upvars_projection_def_id,
+                            [
+                                ty::GenericArg::from(kind_ty),
+                                Ty::from_closure_kind(tcx, goal_kind).into(),
+                                env_region.into(),
+                                sig.tupled_inputs_ty.into(),
+                                args.tupled_upvars_ty().into(),
+                                args.coroutine_captures_by_ref_ty().into(),
+                            ],
+                        );
                         sig.to_coroutine(
                             tcx,
                             args.parent_args(),
@@ -1816,17 +1824,16 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                 name => bug!("no such associated type: {name}"),
             };
             let projection_term = match item_name {
-                sym::CallOnceFuture | sym::Output => {
-                    ty::AliasTerm::new(tcx, obligation.predicate.def_id, [
-                        self_ty,
-                        sig.tupled_inputs_ty,
-                    ])
-                }
-                sym::CallRefFuture => ty::AliasTerm::new(tcx, obligation.predicate.def_id, [
-                    ty::GenericArg::from(self_ty),
-                    sig.tupled_inputs_ty.into(),
-                    env_region.into(),
-                ]),
+                sym::CallOnceFuture | sym::Output => ty::AliasTerm::new(
+                    tcx,
+                    obligation.predicate.def_id,
+                    [self_ty, sig.tupled_inputs_ty],
+                ),
+                sym::CallRefFuture => ty::AliasTerm::new(
+                    tcx,
+                    obligation.predicate.def_id,
+                    [ty::GenericArg::from(self_ty), sig.tupled_inputs_ty.into(), env_region.into()],
+                ),
                 name => bug!("no such associated type: {name}"),
             };
 
@@ -1846,17 +1853,20 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                 name => bug!("no such associated type: {name}"),
             };
             let projection_term = match item_name {
-                sym::CallOnceFuture | sym::Output => {
-                    ty::AliasTerm::new(tcx, obligation.predicate.def_id, [
-                        self_ty,
-                        Ty::new_tup(tcx, sig.inputs()),
-                    ])
-                }
-                sym::CallRefFuture => ty::AliasTerm::new(tcx, obligation.predicate.def_id, [
-                    ty::GenericArg::from(self_ty),
-                    Ty::new_tup(tcx, sig.inputs()).into(),
-                    env_region.into(),
-                ]),
+                sym::CallOnceFuture | sym::Output => ty::AliasTerm::new(
+                    tcx,
+                    obligation.predicate.def_id,
+                    [self_ty, Ty::new_tup(tcx, sig.inputs())],
+                ),
+                sym::CallRefFuture => ty::AliasTerm::new(
+                    tcx,
+                    obligation.predicate.def_id,
+                    [
+                        ty::GenericArg::from(self_ty),
+                        Ty::new_tup(tcx, sig.inputs()).into(),
+                        env_region.into(),
+                    ],
+                ),
                 name => bug!("no such associated type: {name}"),
             };
 
@@ -1879,11 +1889,11 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
                 sym::CallOnceFuture | sym::Output => {
                     ty::AliasTerm::new(tcx, obligation.predicate.def_id, [self_ty, sig.inputs()[0]])
                 }
-                sym::CallRefFuture => ty::AliasTerm::new(tcx, obligation.predicate.def_id, [
-                    ty::GenericArg::from(self_ty),
-                    sig.inputs()[0].into(),
-                    env_region.into(),
-                ]),
+                sym::CallRefFuture => ty::AliasTerm::new(
+                    tcx,
+                    obligation.predicate.def_id,
+                    [ty::GenericArg::from(self_ty), sig.inputs()[0].into(), env_region.into()],
+                ),
                 name => bug!("no such associated type: {name}"),
             };
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 92098e20448..f04a5feba30 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -2,12 +2,13 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_infer::traits::query::type_op::DropckOutlives;
 use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
-use rustc_span::{DUMMY_SP, Span};
+use rustc_span::Span;
 use tracing::{debug, instrument};
 
+use crate::solve::NextSolverError;
 use crate::traits::query::NoSolution;
 use crate::traits::query::normalize::QueryNormalizeExt;
-use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
+use crate::traits::{FromSolverError, Normalized, ObligationCause, ObligationCtxt};
 
 /// This returns true if the type `ty` is "trivial" for
 /// dropck-outlives -- that is, if it doesn't require any types to
@@ -93,6 +94,20 @@ pub fn compute_dropck_outlives_inner<'tcx>(
     goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
     span: Span,
 ) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
+    match compute_dropck_outlives_with_errors(ocx, goal, span) {
+        Ok(r) => Ok(r),
+        Err(_) => Err(NoSolution),
+    }
+}
+
+pub fn compute_dropck_outlives_with_errors<'tcx, E>(
+    ocx: &ObligationCtxt<'_, 'tcx, E>,
+    goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
+    span: Span,
+) -> Result<DropckOutlivesResult<'tcx>, Vec<E>>
+where
+    E: FromSolverError<'tcx, NextSolverError<'tcx>>,
+{
     let tcx = ocx.infcx.tcx;
     let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal;
 
@@ -149,11 +164,11 @@ pub fn compute_dropck_outlives_inner<'tcx>(
         dtorck_constraint_for_ty_inner(
             tcx,
             ocx.infcx.typing_env(param_env),
-            DUMMY_SP,
+            span,
             depth,
             ty,
             &mut constraints,
-        )?;
+        );
 
         // "outlives" represent types/regions that may be touched
         // by a destructor.
@@ -173,11 +188,20 @@ pub fn compute_dropck_outlives_inner<'tcx>(
         // do not themselves define a destructor", more or less. We have
         // to push them onto the stack to be expanded.
         for ty in constraints.dtorck_types.drain(..) {
-            let Normalized { value: ty, obligations } =
-                ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
-            ocx.register_obligations(obligations);
+            let ty = if let Ok(Normalized { value: ty, obligations }) =
+                ocx.infcx.at(&cause, param_env).query_normalize(ty)
+            {
+                ocx.register_obligations(obligations);
+
+                debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+                ty
+            } else {
+                ocx.deeply_normalize(&cause, param_env, ty)?;
 
-            debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+                let errors = ocx.select_where_possible();
+                debug!("normalize errors: {ty} ~> {errors:#?}");
+                return Err(errors);
+            };
 
             match ty.kind() {
                 // All parameters live for the duration of the
@@ -213,14 +237,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
     depth: usize,
     ty: Ty<'tcx>,
     constraints: &mut DropckConstraint<'tcx>,
-) -> Result<(), NoSolution> {
+) {
     if !tcx.recursion_limit().value_within_limit(depth) {
         constraints.overflows.push(ty);
-        return Ok(());
+        return;
     }
 
     if trivial_dropck_outlives(tcx, ty) {
-        return Ok(());
+        return;
     }
 
     match ty.kind() {
@@ -244,22 +268,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             // single-element containers, behave like their element
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
                 dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints)
-            })?;
+            });
         }
 
         ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
             for ty in tys.iter() {
-                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
             }
-            Ok::<_, NoSolution>(())
-        })?,
+        }),
 
         ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
             for ty in args.as_closure().upvar_tys() {
-                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
+                dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
             }
-            Ok::<_, NoSolution>(())
-        })?,
+        }),
 
         ty::CoroutineClosure(_, args) => {
             rustc_data_structures::stack::ensure_sufficient_stack(|| {
@@ -271,10 +293,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
                         depth + 1,
                         ty,
                         constraints,
-                    )?;
+                    );
                 }
-                Ok::<_, NoSolution>(())
-            })?
+            })
         }
 
         ty::Coroutine(_, args) => {
@@ -313,7 +334,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
 
         ty::Adt(def, args) => {
             let DropckConstraint { dtorck_types, outlives, overflows } =
-                tcx.at(span).adt_dtorck_constraint(def.did())?;
+                tcx.at(span).adt_dtorck_constraint(def.did());
             // FIXME: we can try to recursively `dtorck_constraint_on_ty`
             // there, but that needs some way to handle cycles.
             constraints
@@ -346,9 +367,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
         ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
-            return Err(NoSolution);
+            tcx.dcx().span_delayed_bug(span, format!("Unresolved type in dropck: {:?}.", ty));
         }
     }
-
-    Ok(())
 }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index e8c2528aa6e..2f6bbd7f4cf 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -2,7 +2,7 @@ use std::fmt;
 
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::traits::query::NoSolution;
-pub use rustc_middle::traits::query::type_op::Normalize;
+pub use rustc_middle::traits::query::type_op::{DeeplyNormalize, Normalize};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::Span;
@@ -28,12 +28,53 @@ where
     }
 
     fn perform_locally_with_next_solver(
+        _ocx: &ObligationCtxt<'_, 'tcx>,
+        key: ParamEnvAnd<'tcx, Self>,
+        _span: Span,
+    ) -> Result<Self::QueryResponse, NoSolution> {
+        Ok(key.value.value)
+    }
+}
+
+impl<'tcx, T> super::QueryTypeOp<'tcx> for DeeplyNormalize<T>
+where
+    T: Normalizable<'tcx> + 'tcx,
+{
+    type QueryResponse = T;
+
+    fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> {
+        if !key.value.value.has_aliases() { Some(key.value.value) } else { None }
+    }
+
+    fn perform_query(
+        tcx: TyCtxt<'tcx>,
+        canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
+    ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
+        T::type_op_method(
+            tcx,
+            CanonicalQueryInput {
+                typing_mode: canonicalized.typing_mode,
+                canonical: canonicalized.canonical.unchecked_map(
+                    |ty::ParamEnvAnd { param_env, value }| ty::ParamEnvAnd {
+                        param_env,
+                        value: Normalize { value: value.value },
+                    },
+                ),
+            },
+        )
+    }
+
+    fn perform_locally_with_next_solver(
         ocx: &ObligationCtxt<'_, 'tcx>,
         key: ParamEnvAnd<'tcx, Self>,
         span: Span,
     ) -> Result<Self::QueryResponse, NoSolution> {
-        // FIXME(-Znext-solver): shouldn't be using old normalizer
-        Ok(ocx.normalize(&ObligationCause::dummy_with_span(span), key.param_env, key.value.value))
+        ocx.deeply_normalize(
+            &ObligationCause::dummy_with_span(span),
+            key.param_env,
+            key.value.value,
+        )
+        .map_err(|_| NoSolution)
     }
 }
 
@@ -81,3 +122,14 @@ impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> {
         tcx.type_op_normalize_fn_sig(canonicalized)
     }
 }
+
+/// This impl is not needed, since we never normalize type outlives predicates
+/// in the old solver, but is required by trait bounds to be happy.
+impl<'tcx> Normalizable<'tcx> for ty::PolyTypeOutlivesPredicate<'tcx> {
+    fn type_op_method(
+        _tcx: TyCtxt<'tcx>,
+        _canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
+    ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
+        unreachable!("we never normalize PolyTypeOutlivesPredicate")
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 13a6744c2e9..5b362b2356e 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -12,9 +12,7 @@ use hir::LangItem;
 use hir::def_id::DefId;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_hir as hir;
-use rustc_infer::traits::{
-    Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError,
-};
+use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode};
 use rustc_middle::{bug, span_bug};
@@ -23,8 +21,6 @@ use tracing::{debug, instrument, trace};
 
 use super::SelectionCandidate::*;
 use super::{BuiltinImplConditions, SelectionCandidateSet, SelectionContext, TraitObligationStack};
-use crate::traits;
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::util;
 
 impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
@@ -106,6 +102,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 self.assemble_candidate_for_tuple(obligation, &mut candidates);
             } else if tcx.is_lang_item(def_id, LangItem::FnPtrTrait) {
                 self.assemble_candidates_for_fn_ptr_trait(obligation, &mut candidates);
+            } else if tcx.is_lang_item(def_id, LangItem::BikeshedGuaranteedNoDrop) {
+                self.assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
+                    obligation,
+                    &mut candidates,
+                );
             } else {
                 if tcx.is_lang_item(def_id, LangItem::Clone) {
                     // Same builtin conditions as `Copy`, i.e., every type which has builtin support
@@ -904,54 +905,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         })
     }
 
-    /// Temporary migration for #89190
-    fn need_migrate_deref_output_trait_object(
-        &mut self,
-        ty: Ty<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: &ObligationCause<'tcx>,
-    ) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
-        // Don't drop any candidates in intercrate mode, as it's incomplete.
-        // (Not that it matters, since `Unsize` is not a stable trait.)
-        //
-        // FIXME(@lcnr): This should probably only trigger during analysis,
-        // disabling candidates during codegen is also questionable.
-        if let TypingMode::Coherence = self.infcx.typing_mode() {
-            return None;
-        }
-
-        let tcx = self.tcx();
-        if tcx.features().trait_upcasting() {
-            return None;
-        }
-
-        // <ty as Deref>
-        let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
-
-        let obligation =
-            traits::Obligation::new(tcx, cause.clone(), param_env, ty::Binder::dummy(trait_ref));
-        if !self.infcx.predicate_may_hold(&obligation) {
-            return None;
-        }
-
-        self.infcx.probe(|_| {
-            let ty = traits::normalize_projection_ty(
-                self,
-                param_env,
-                ty::AliasTy::new_from_args(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
-                cause.clone(),
-                0,
-                // We're *intentionally* throwing these away,
-                // since we don't actually use them.
-                &mut PredicateObligations::new(),
-            )
-            .as_type()
-            .unwrap();
-
-            if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
-        })
-    }
-
     /// Searches for unsizing that might apply to `obligation`.
     fn assemble_candidates_for_unsizing(
         &mut self,
@@ -972,11 +925,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         //     T: Trait
         // so it seems ok if we (conservatively) fail to accept that `Unsize`
         // obligation above. Should be possible to extend this in the future.
-        let Some(source) = obligation.self_ty().no_bound_vars() else {
+        let Some(trait_pred) = obligation.predicate.no_bound_vars() else {
             // Don't add any candidates if there are bound regions.
             return;
         };
-        let target = obligation.predicate.skip_binder().trait_ref.args.type_at(1);
+        let source = trait_pred.self_ty();
+        let target = trait_pred.trait_ref.args.type_at(1);
 
         debug!(?source, ?target, "assemble_candidates_for_unsizing");
 
@@ -1019,15 +973,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     let principal_a = a_data.principal().unwrap();
                     let target_trait_did = principal_def_id_b.unwrap();
                     let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
-                    if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
-                        source,
-                        obligation.param_env,
-                        &obligation.cause,
-                    ) {
-                        if deref_trait_ref.def_id() == target_trait_did {
-                            return;
-                        }
-                    }
 
                     for (idx, upcast_trait_ref) in
                         util::supertraits(self.tcx(), source_trait_ref).enumerate()
@@ -1244,4 +1189,48 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         }
     }
+
+    fn assemble_candidates_for_bikeshed_guaranteed_no_drop_trait(
+        &mut self,
+        obligation: &PolyTraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        match obligation.predicate.self_ty().skip_binder().kind() {
+            ty::Ref(..)
+            | ty::Adt(..)
+            | ty::Tuple(_)
+            | ty::Array(..)
+            | ty::FnDef(..)
+            | ty::FnPtr(..)
+            | ty::Error(_)
+            | ty::Uint(_)
+            | ty::Int(_)
+            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
+            | ty::Bool
+            | ty::Float(_)
+            | ty::Char
+            | ty::RawPtr(..)
+            | ty::Never
+            | ty::Pat(..)
+            | ty::Dynamic(..)
+            | ty::Str
+            | ty::Slice(_)
+            | ty::Foreign(..)
+            | ty::Alias(..)
+            | ty::Param(_)
+            | ty::Placeholder(..)
+            | ty::Closure(..)
+            | ty::CoroutineClosure(..)
+            | ty::Coroutine(..)
+            | ty::UnsafeBinder(_)
+            | ty::CoroutineWitness(..)
+            | ty::Bound(..) => {
+                candidates.vec.push(BikeshedGuaranteedNoDropCandidate);
+            }
+
+            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+                candidates.ambiguous = true;
+            }
+        }
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 729ae3f2c2a..32cbb97e314 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -20,6 +20,7 @@ use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, Upcast};
 use rustc_middle::{bug, span_bug};
 use rustc_span::def_id::DefId;
 use rustc_type_ir::elaborate;
+use thin_vec::thin_vec;
 use tracing::{debug, instrument};
 
 use super::SelectionCandidate::{self, *};
@@ -130,6 +131,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             TraitUpcastingUnsizeCandidate(idx) => {
                 self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?
             }
+
+            BikeshedGuaranteedNoDropCandidate => {
+                self.confirm_bikeshed_guaranteed_no_drop_candidate(obligation)
+            }
         };
 
         // The obligations returned by confirmation are recursively evaluated
@@ -301,11 +306,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             let make_transmute_obl = |src, dst| {
                 let transmute_trait = obligation.predicate.def_id();
                 let assume = obligation.predicate.skip_binder().trait_ref.args.const_at(2);
-                let trait_ref = ty::TraitRef::new(tcx, transmute_trait, [
-                    ty::GenericArg::from(dst),
-                    ty::GenericArg::from(src),
-                    ty::GenericArg::from(assume),
-                ]);
+                let trait_ref = ty::TraitRef::new(
+                    tcx,
+                    transmute_trait,
+                    [
+                        ty::GenericArg::from(dst),
+                        ty::GenericArg::from(src),
+                        ty::GenericArg::from(assume),
+                    ],
+                );
                 Obligation::with_depth(
                     tcx,
                     obligation.cause.clone(),
@@ -316,10 +325,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             };
 
             let make_freeze_obl = |ty| {
-                let trait_ref =
-                    ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Freeze, None), [
-                        ty::GenericArg::from(ty),
-                    ]);
+                let trait_ref = ty::TraitRef::new(
+                    tcx,
+                    tcx.require_lang_item(LangItem::Freeze, None),
+                    [ty::GenericArg::from(ty)],
+                );
                 Obligation::with_depth(
                     tcx,
                     obligation.cause.clone(),
@@ -863,10 +873,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
             ty::CoroutineClosure(_, args) => {
                 args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
-                    ty::TraitRef::new(self.tcx(), obligation.predicate.def_id(), [
-                        self_ty,
-                        sig.tupled_inputs_ty,
-                    ])
+                    ty::TraitRef::new(
+                        self.tcx(),
+                        obligation.predicate.def_id(),
+                        [self_ty, sig.tupled_inputs_ty],
+                    )
                 })
             }
             _ => {
@@ -892,10 +903,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::CoroutineClosure(_, args) => {
                 let args = args.as_coroutine_closure();
                 let trait_ref = args.coroutine_closure_sig().map_bound(|sig| {
-                    ty::TraitRef::new(self.tcx(), obligation.predicate.def_id(), [
-                        self_ty,
-                        sig.tupled_inputs_ty,
-                    ])
+                    ty::TraitRef::new(
+                        self.tcx(),
+                        obligation.predicate.def_id(),
+                        [self_ty, sig.tupled_inputs_ty],
+                    )
                 });
 
                 // Note that unlike below, we don't need to check `Future + Sized` for
@@ -906,10 +918,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::FnDef(..) | ty::FnPtr(..) => {
                 let sig = self_ty.fn_sig(tcx);
                 let trait_ref = sig.map_bound(|sig| {
-                    ty::TraitRef::new(self.tcx(), obligation.predicate.def_id(), [
-                        self_ty,
-                        Ty::new_tup(tcx, sig.inputs()),
-                    ])
+                    ty::TraitRef::new(
+                        self.tcx(),
+                        obligation.predicate.def_id(),
+                        [self_ty, Ty::new_tup(tcx, sig.inputs())],
+                    )
                 });
 
                 // We must additionally check that the return type impls `Future + Sized`.
@@ -934,10 +947,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let args = args.as_closure();
                 let sig = args.sig();
                 let trait_ref = sig.map_bound(|sig| {
-                    ty::TraitRef::new(self.tcx(), obligation.predicate.def_id(), [
-                        self_ty,
-                        sig.inputs()[0],
-                    ])
+                    ty::TraitRef::new(
+                        self.tcx(),
+                        obligation.predicate.def_id(),
+                        [self_ty, sig.inputs()[0]],
+                    )
                 });
 
                 // We must additionally check that the return type impls `Future + Sized`.
@@ -1295,10 +1309,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // Construct the nested `TailField<T>: Unsize<TailField<U>>` predicate.
                 let tail_unsize_obligation = obligation.with(
                     tcx,
-                    ty::TraitRef::new(tcx, obligation.predicate.def_id(), [
-                        source_tail,
-                        target_tail,
-                    ]),
+                    ty::TraitRef::new(
+                        tcx,
+                        obligation.predicate.def_id(),
+                        [source_tail, target_tail],
+                    ),
                 );
                 nested.push(tail_unsize_obligation);
 
@@ -1336,6 +1351,93 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             _ => bug!("source: {source}, target: {target}"),
         })
     }
+
+    fn confirm_bikeshed_guaranteed_no_drop_candidate(
+        &mut self,
+        obligation: &PolyTraitObligation<'tcx>,
+    ) -> ImplSource<'tcx, PredicateObligation<'tcx>> {
+        let mut obligations = thin_vec![];
+
+        let tcx = self.tcx();
+        let self_ty = obligation.predicate.self_ty();
+        match *self_ty.skip_binder().kind() {
+            // `&mut T` and `&T` always implement `BikeshedGuaranteedNoDrop`.
+            ty::Ref(..) => {}
+            // `ManuallyDrop<T>` always implements `BikeshedGuaranteedNoDrop`.
+            ty::Adt(def, _) if def.is_manually_drop() => {}
+            // Arrays and tuples implement `BikeshedGuaranteedNoDrop` only if
+            // their constituent types implement `BikeshedGuaranteedNoDrop`.
+            ty::Tuple(tys) => {
+                obligations.extend(tys.iter().map(|elem_ty| {
+                    obligation.with(
+                        tcx,
+                        self_ty.rebind(ty::TraitRef::new(
+                            tcx,
+                            obligation.predicate.def_id(),
+                            [elem_ty],
+                        )),
+                    )
+                }));
+            }
+            ty::Array(elem_ty, _) => {
+                obligations.push(obligation.with(
+                    tcx,
+                    self_ty.rebind(ty::TraitRef::new(
+                        tcx,
+                        obligation.predicate.def_id(),
+                        [elem_ty],
+                    )),
+                ));
+            }
+
+            // All other types implement `BikeshedGuaranteedNoDrop` only if
+            // they implement `Copy`. We could be smart here and short-circuit
+            // some trivially `Copy`/`!Copy` types, but there's no benefit.
+            ty::FnDef(..)
+            | ty::FnPtr(..)
+            | ty::Error(_)
+            | ty::Uint(_)
+            | ty::Int(_)
+            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
+            | ty::Bool
+            | ty::Float(_)
+            | ty::Char
+            | ty::RawPtr(..)
+            | ty::Never
+            | ty::Pat(..)
+            | ty::Dynamic(..)
+            | ty::Str
+            | ty::Slice(_)
+            | ty::Foreign(..)
+            | ty::Adt(..)
+            | ty::Alias(..)
+            | ty::Param(_)
+            | ty::Placeholder(..)
+            | ty::Closure(..)
+            | ty::CoroutineClosure(..)
+            | ty::Coroutine(..)
+            | ty::UnsafeBinder(_)
+            | ty::CoroutineWitness(..)
+            | ty::Bound(..) => {
+                obligations.push(obligation.with(
+                    tcx,
+                    self_ty.map_bound(|ty| {
+                        ty::TraitRef::new(
+                            tcx,
+                            tcx.require_lang_item(LangItem::Copy, Some(obligation.cause.span)),
+                            [ty],
+                        )
+                    }),
+                ));
+            }
+
+            ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+                panic!("unexpected type `{self_ty:?}`")
+            }
+        }
+
+        ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
+    }
 }
 
 /// Compute a goal that some RPITIT (right now, only RPITITs corresponding to Futures)
@@ -1359,10 +1461,11 @@ fn pointer_like_goal_for_rpitit<'tcx>(
         ty::GenericParamDefKind::Lifetime => {
             let kind = ty::BoundRegionKind::Named(arg.def_id, tcx.item_name(arg.def_id));
             bound_vars.push(ty::BoundVariableKind::Region(kind));
-            ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
-                var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                kind,
-            })
+            ty::Region::new_bound(
+                tcx,
+                ty::INNERMOST,
+                ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+            )
             .into()
         }
         ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Const { .. } => {
@@ -1371,9 +1474,11 @@ fn pointer_like_goal_for_rpitit<'tcx>(
     });
 
     ty::Binder::bind_with_vars(
-        ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::PointerLike, Some(cause.span)), [
-            Ty::new_projection_from_args(tcx, rpitit_item, args),
-        ]),
+        ty::TraitRef::new(
+            tcx,
+            tcx.require_lang_item(LangItem::PointerLike, Some(cause.span)),
+            [Ty::new_projection_from_args(tcx, rpitit_item, args)],
+        ),
         tcx.mk_bound_variable_kinds(&bound_vars),
     )
 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 99ce1fd9fb4..436ce3dddd9 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1949,7 +1949,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 | TraitAliasCandidate
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate => false,
+                | BuiltinUnsizeCandidate
+                | BikeshedGuaranteedNoDropCandidate => false,
                 // Non-global param candidates have already been handled, global
                 // where-bounds get ignored.
                 ParamCandidate(_) | ImplCandidate(_) => true,
@@ -2422,9 +2423,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 } else {
                     // If this is an ill-formed auto/built-in trait, then synthesize
                     // new error args for the missing generics.
-                    let err_args = ty::GenericArgs::extend_with_error(tcx, trait_def_id, &[
-                        normalized_ty.into(),
-                    ]);
+                    let err_args = ty::GenericArgs::extend_with_error(
+                        tcx,
+                        trait_def_id,
+                        &[normalized_ty.into()],
+                    );
                     ty::TraitRef::new_from_args(tcx, trait_def_id, err_args)
                 };
 
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
index f39c611d19f..19d3561dd59 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -200,15 +200,12 @@ impl<'tcx> Children {
     }
 }
 
-fn iter_children(children: &Children) -> impl Iterator<Item = DefId> + '_ {
+fn iter_children(children: &Children) -> impl Iterator<Item = DefId> {
     let nonblanket = children.non_blanket_impls.iter().flat_map(|(_, v)| v.iter());
     children.blanket_impls.iter().chain(nonblanket).cloned()
 }
 
-fn filtered_children(
-    children: &mut Children,
-    st: SimplifiedType,
-) -> impl Iterator<Item = DefId> + '_ {
+fn filtered_children(children: &mut Children, st: SimplifiedType) -> impl Iterator<Item = DefId> {
     let nonblanket = children.non_blanket_impls.entry(st).or_default().iter();
     children.blanket_impls.iter().chain(nonblanket).cloned()
 }
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index d30363ec158..15f5cf916a4 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -47,11 +47,11 @@ pub fn expand_trait_aliases<'tcx>(
                     queue.extend(
                         tcx.explicit_super_predicates_of(trait_pred.def_id())
                             .iter_identity_copied()
-                            .map(|(clause, span)| {
+                            .map(|(super_clause, span)| {
                                 let mut spans = spans.clone();
                                 spans.push(span);
                                 (
-                                    clause.instantiate_supertrait(
+                                    super_clause.instantiate_supertrait(
                                         tcx,
                                         clause.kind().rebind(trait_pred.trait_ref),
                                     ),
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
index 000e6a765d3..165174c0bcc 100644
--- a/compiler/rustc_trait_selection/src/traits/vtable.rs
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -196,7 +196,7 @@ fn own_existential_vtable_entries(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &[Def
 fn own_existential_vtable_entries_iter(
     tcx: TyCtxt<'_>,
     trait_def_id: DefId,
-) -> impl Iterator<Item = DefId> + '_ {
+) -> impl Iterator<Item = DefId> {
     let trait_methods = tcx
         .associated_items(trait_def_id)
         .in_definition_order()
@@ -318,9 +318,17 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe
         bug!();
     };
     let source_principal = tcx.instantiate_bound_regions_with_erased(
-        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self),
+        source.principal().unwrap().with_self_ty(tcx, key.self_ty()),
     );
 
+    // We're monomorphizing a call to a dyn trait object that can never be constructed.
+    if tcx.instantiate_and_check_impossible_predicates((
+        source_principal.def_id,
+        source_principal.args,
+    )) {
+        return 0;
+    }
+
     let target_principal = ty::ExistentialTraitRef::erase_self_ty(tcx, key);
 
     let vtable_segment_callback = {
@@ -373,19 +381,27 @@ pub(crate) fn supertrait_vtable_slot<'tcx>(
     let (source, target) = key;
 
     // If the target principal is `None`, we can just return `None`.
-    let ty::Dynamic(target, _, _) = *target.kind() else {
+    let ty::Dynamic(target_data, _, _) = *target.kind() else {
         bug!();
     };
-    let target_principal = tcx.instantiate_bound_regions_with_erased(target.principal()?);
+    let target_principal = tcx.instantiate_bound_regions_with_erased(target_data.principal()?);
 
     // Given that we have a target principal, it is a bug for there not to be a source principal.
-    let ty::Dynamic(source, _, _) = *source.kind() else {
+    let ty::Dynamic(source_data, _, _) = *source.kind() else {
         bug!();
     };
     let source_principal = tcx.instantiate_bound_regions_with_erased(
-        source.principal().unwrap().with_self_ty(tcx, tcx.types.trait_object_dummy_self),
+        source_data.principal().unwrap().with_self_ty(tcx, source),
     );
 
+    // We're monomorphizing a dyn trait object upcast that can never be constructed.
+    if tcx.instantiate_and_check_impossible_predicates((
+        source_principal.def_id,
+        source_principal.args,
+    )) {
+        return None;
+    }
+
     let vtable_segment_callback = {
         let mut vptr_offset = 0;
         move |segment| {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 96051ad0aa5..7f3e3ce4781 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -8,8 +8,9 @@ use rustc_middle::ty::{
     self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable,
     TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
-use rustc_span::Span;
+use rustc_session::parse::feature_err;
 use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::{Span, sym};
 use tracing::{debug, instrument, trace};
 
 use crate::infer::InferCtxt;
@@ -288,7 +289,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             && let Some(impl_item) =
                 items.iter().find(|item| item.id.owner_id.to_def_id() == impl_item_id)
         {
-            Some(tcx.hir().impl_item(impl_item.id).expect_type().span)
+            Some(tcx.hir_impl_item(impl_item.id).expect_type().span)
         } else {
             None
         }
@@ -704,8 +705,47 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 ));
             }
 
-            ty::Pat(subty, _) => {
+            ty::Pat(subty, pat) => {
                 self.require_sized(subty, ObligationCauseCode::Misc);
+                match *pat {
+                    ty::PatternKind::Range { start, end, include_end: _ } => {
+                        let mut check = |c| {
+                            let cause = self.cause(ObligationCauseCode::Misc);
+                            self.out.push(traits::Obligation::with_depth(
+                                tcx,
+                                cause.clone(),
+                                self.recursion_depth,
+                                self.param_env,
+                                ty::Binder::dummy(ty::PredicateKind::Clause(
+                                    ty::ClauseKind::ConstArgHasType(c, subty),
+                                )),
+                            ));
+                            if !tcx.features().generic_pattern_types() {
+                                if c.has_param() {
+                                    if self.span.is_dummy() {
+                                        self.tcx().dcx().delayed_bug(
+                                            "feature error should be reported elsewhere, too",
+                                        );
+                                    } else {
+                                        feature_err(
+                                            &self.tcx().sess,
+                                            sym::generic_pattern_types,
+                                            self.span,
+                                            "wraparound pattern type ranges cause monomorphization time errors",
+                                        )
+                                        .emit();
+                                    }
+                                }
+                            }
+                        };
+                        if let Some(start) = start {
+                            check(start)
+                        }
+                        if let Some(end) = end {
+                            check(end)
+                        }
+                    }
+                }
             }
 
             ty::Tuple(tys) => {
@@ -841,7 +881,10 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                         ty.map_bound(|ty| {
                             ty::TraitRef::new(
                                 self.tcx(),
-                                self.tcx().require_lang_item(LangItem::Copy, Some(self.span)),
+                                self.tcx().require_lang_item(
+                                    LangItem::BikeshedGuaranteedNoDrop,
+                                    Some(self.span),
+                                ),
                                 [ty],
                             )
                         }),