about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-02-22 03:05:26 +0000
committerbors <bors@rust-lang.org>2025-02-22 03:05:26 +0000
commitb87eda7fdf8034c52b3abef52b443b8573484eda (patch)
tree47e409359bdedd9dce803ae25caf3ddad85560d3
parentdc37ff82e861428d537ae28e7b92296c4583fb5a (diff)
parent63520442697e523ca2834a5ad81102a1db59c832 (diff)
downloadrust-b87eda7fdf8034c52b3abef52b443b8573484eda.tar.gz
rust-b87eda7fdf8034c52b3abef52b443b8573484eda.zip
Auto merge of #137406 - matthiaskrgr:rollup-9nknrsb, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #136458 (Do not deduplicate list of associated types provided by dyn principal)
 - #136474 ([`compiletest`-related cleanups 3/7] Make the distinction between sources root vs test suite sources root in compiletest less confusing)
 - #136592 (Make sure we don't overrun the stack in canonicalizer)
 - #136787 (Remove `lifetime_capture_rules_2024` feature)
 - #137207 (Add #[track_caller] to Duration Div impl)
 - #137245 (Tweak E0277 when predicate comes indirectly from ?)
 - #137257 (Ignore fake borrows for packed field check)
 - #137399 (fix ICE in layout computation with unnormalizable const)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs33
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs127
-rw-r--r--compiler/rustc_lint/src/impl_trait_overcaptures.rs6
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs8
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs21
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs30
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs126
-rw-r--r--compiler/rustc_traits/src/codegen.rs16
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs1
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs15
-rw-r--r--compiler/rustc_type_ir/src/elaborate.rs15
-rw-r--r--library/core/src/time.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs4
-rw-r--r--src/tools/compiletest/src/common.rs6
-rw-r--r--src/tools/compiletest/src/header.rs15
-rw-r--r--src/tools/compiletest/src/header/tests.rs3
-rw-r--r--src/tools/compiletest/src/lib.rs69
-rw-r--r--src/tools/compiletest/src/runtest.rs6
-rw-r--r--src/tools/compiletest/src/runtest/debuginfo.rs29
-rw-r--r--src/tools/compiletest/src/runtest/js_doc.rs3
-rw-r--r--src/tools/compiletest/src/runtest/run_make.rs35
-rw-r--r--src/tools/compiletest/src/runtest/rustdoc.rs5
-rw-r--r--tests/crashes/125957.rs20
-rw-r--r--tests/crashes/132330.rs28
-rw-r--r--tests/ui/associated-consts/issue-93775.rs67
-rw-r--r--tests/ui/associated-types/associated-types-overridden-binding-2.rs2
-rw-r--r--tests/ui/associated-types/associated-types-overridden-binding-2.stderr14
-rw-r--r--tests/ui/associated-types/associated-types-overridden-binding.rs1
-rw-r--r--tests/ui/associated-types/associated-types-overridden-binding.stderr13
-rw-r--r--tests/ui/async-await/issue-84841.stderr2
-rw-r--r--tests/ui/async-await/try-on-option-in-async.stderr6
-rw-r--r--tests/ui/closures/deduce-from-object-supertrait.rs18
-rw-r--r--tests/ui/dyn-compatibility/multiple-supers-should-work.rs21
-rw-r--r--tests/ui/impl-trait/implicit-capture-late.rs6
-rw-r--r--tests/ui/impl-trait/implicit-capture-late.stderr6
-rw-r--r--tests/ui/impl-trait/precise-capturing/higher-ranked.rs3
-rw-r--r--tests/ui/impl-trait/precise-capturing/outlives.rs3
-rw-r--r--tests/ui/impl-trait/variance.e2024.stderr8
-rw-r--r--tests/ui/impl-trait/variance.new.stderr26
-rw-r--r--tests/ui/impl-trait/variance.old.stderr8
-rw-r--r--tests/ui/impl-trait/variance.rs10
-rw-r--r--tests/ui/layout/gce-rigid-const-in-array-len.rs27
-rw-r--r--tests/ui/layout/gce-rigid-const-in-array-len.stderr17
-rw-r--r--tests/ui/layout/unconstrained-param-ice-137308.rs18
-rw-r--r--tests/ui/layout/unconstrained-param-ice-137308.stderr15
-rw-r--r--tests/ui/lint/unaligned_references_fake_borrow.rs27
-rw-r--r--tests/ui/return/return-from-residual-sugg-issue-125997.stderr6
-rw-r--r--tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs (renamed from tests/crashes/126944.rs)17
-rw-r--r--tests/ui/traits/object/incomplete-multiple-super-projection.rs32
-rw-r--r--tests/ui/traits/object/incomplete-multiple-super-projection.stderr12
-rw-r--r--tests/ui/traits/object/infer-shadows-implied-projection.rs (renamed from tests/crashes/79590.rs)2
-rw-r--r--tests/ui/traits/object/outlives-super-proj.rs24
-rw-r--r--tests/ui/traits/object/pretty.stderr6
-rw-r--r--tests/ui/traits/object/redundant.rs12
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr12
-rw-r--r--tests/ui/try-trait/bad-question-mark-on-trait-object.rs29
-rw-r--r--tests/ui/try-trait/bad-question-mark-on-trait-object.stderr43
-rw-r--r--tests/ui/try-trait/option-to-result.stderr6
-rw-r--r--tests/ui/try-trait/try-on-option-diagnostics.stderr8
-rw-r--r--tests/ui/try-trait/try-on-option.stderr5
-rw-r--r--tests/ui/try-trait/try-operator-on-main.stderr3
65 files changed, 785 insertions, 386 deletions
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 2fb0c8e4344..60e7788f2c0 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -135,6 +135,8 @@ declare_features! (
      Some("removed as it caused some confusion and discussion was inactive for years")),
     /// Lazily evaluate constants. This allows constants to depend on type parameters.
     (removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
+    /// Changes `impl Trait` to capture all lifetimes in scope.
+    (removed, lifetime_capture_rules_2024, "1.76.0", None, Some("unnecessary -- use edition 2024 instead")),
     /// Allows using the `#[link_args]` attribute.
     (removed, link_args, "1.53.0", Some(29596),
      Some("removed in favor of using `-C link-arg=ARG` on command line, \
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index e852f239aa2..c7b44cecb9e 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -214,8 +214,6 @@ declare_features! (
     (internal, intrinsics, "1.0.0", None),
     /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
     (internal, lang_items, "1.0.0", None),
-    /// Changes `impl Trait` to capture all lifetimes in scope.
-    (unstable, lifetime_capture_rules_2024, "1.76.0", None),
     /// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
     (internal, link_cfg, "1.14.0", None),
     /// Allows using `?Trait` trait bounds in more contexts.
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 759c981a8f7..fee3c6088ed 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -305,21 +305,15 @@ fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVaria
 }
 
 /// Whether this opaque always captures lifetimes in scope.
-/// Right now, this is all RPITIT and TAITs, and when `lifetime_capture_rules_2024`
-/// is enabled. We don't check the span of the edition, since this is done
-/// on a per-opaque basis to account for nested opaques.
-fn opaque_captures_all_in_scope_lifetimes<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    opaque: &'tcx hir::OpaqueTy<'tcx>,
-) -> bool {
+/// Right now, this is all RPITIT and TAITs, and when the opaque
+/// is coming from a span corresponding to edition 2024.
+fn opaque_captures_all_in_scope_lifetimes<'tcx>(opaque: &'tcx hir::OpaqueTy<'tcx>) -> bool {
     match opaque.origin {
         // if the opaque has the `use<...>` syntax, the user is telling us that they only want
         // to account for those lifetimes, so do not try to be clever.
         _ if opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..))) => false,
         hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => true,
-        _ if tcx.features().lifetime_capture_rules_2024() || opaque.span.at_least_rust_2024() => {
-            true
-        }
+        _ if opaque.span.at_least_rust_2024() => true,
         hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
     }
 }
@@ -519,8 +513,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     fn visit_opaque_ty(&mut self, opaque: &'tcx rustc_hir::OpaqueTy<'tcx>) {
         let captures = RefCell::new(FxIndexMap::default());
 
-        let capture_all_in_scope_lifetimes =
-            opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
+        let capture_all_in_scope_lifetimes = opaque_captures_all_in_scope_lifetimes(opaque);
         if capture_all_in_scope_lifetimes {
             let lifetime_ident = |def_id: LocalDefId| {
                 let name = self.tcx.item_name(def_id.to_def_id());
@@ -2276,7 +2269,7 @@ fn is_late_bound_map(
     }
 
     let mut appears_in_output =
-        AllCollector { tcx, has_fully_capturing_opaque: false, regions: Default::default() };
+        AllCollector { has_fully_capturing_opaque: false, regions: Default::default() };
     intravisit::walk_fn_ret_ty(&mut appears_in_output, &sig.decl.output);
     if appears_in_output.has_fully_capturing_opaque {
         appears_in_output.regions.extend(generics.params.iter().map(|param| param.def_id));
@@ -2289,7 +2282,7 @@ fn is_late_bound_map(
     // Subtle point: because we disallow nested bindings, we can just
     // ignore binders here and scrape up all names we see.
     let mut appears_in_where_clause =
-        AllCollector { tcx, has_fully_capturing_opaque: true, regions: Default::default() };
+        AllCollector { has_fully_capturing_opaque: true, regions: Default::default() };
     appears_in_where_clause.visit_generics(generics);
     debug!(?appears_in_where_clause.regions);
 
@@ -2455,23 +2448,21 @@ fn is_late_bound_map(
         }
     }
 
-    struct AllCollector<'tcx> {
-        tcx: TyCtxt<'tcx>,
+    struct AllCollector {
         has_fully_capturing_opaque: bool,
         regions: FxHashSet<LocalDefId>,
     }
 
-    impl<'v> Visitor<'v> for AllCollector<'v> {
-        fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
+    impl<'tcx> Visitor<'tcx> for AllCollector {
+        fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
             if let hir::LifetimeName::Param(def_id) = lifetime_ref.res {
                 self.regions.insert(def_id);
             }
         }
 
-        fn visit_opaque_ty(&mut self, opaque: &'v hir::OpaqueTy<'v>) {
+        fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) {
             if !self.has_fully_capturing_opaque {
-                self.has_fully_capturing_opaque =
-                    opaque_captures_all_in_scope_lifetimes(self.tcx, opaque);
+                self.has_fully_capturing_opaque = opaque_captures_all_in_scope_lifetimes(opaque);
             }
             intravisit::walk_opaque_ty(self, opaque);
         }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
index 830dca0d3cd..3eb4945ebf8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::struct_span_code_err;
 use rustc_hir as hir;
@@ -58,9 +58,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
         }
 
-        let (trait_bounds, mut projection_bounds) =
+        let (elaborated_trait_bounds, elaborated_projection_bounds) =
             traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
-        let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds
+        let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = elaborated_trait_bounds
             .into_iter()
             .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
 
@@ -103,29 +103,81 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
         }
 
+        // Map the projection bounds onto a key that makes it easy to remove redundant
+        // bounds that are constrained by supertraits of the principal def id.
+        //
+        // Also make sure we detect conflicting bounds from expanding a trait alias and
+        // also specifying it manually, like:
+        // ```
+        // type Alias = Trait<Assoc = i32>;
+        // let _: &dyn Alias<Assoc = u32> = /* ... */;
+        // ```
+        let mut projection_bounds = FxIndexMap::default();
+        for (proj, proj_span) in elaborated_projection_bounds {
+            let key = (
+                proj.skip_binder().projection_term.def_id,
+                tcx.anonymize_bound_vars(
+                    proj.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
+                ),
+            );
+            if let Some((old_proj, old_proj_span)) =
+                projection_bounds.insert(key, (proj, proj_span))
+                && tcx.anonymize_bound_vars(proj) != tcx.anonymize_bound_vars(old_proj)
+            {
+                let item = tcx.item_name(proj.item_def_id());
+                self.dcx()
+                    .struct_span_err(
+                        span,
+                        format!(
+                            "conflicting associated type bounds for `{item}` when \
+                            expanding trait alias"
+                        ),
+                    )
+                    .with_span_label(
+                        old_proj_span,
+                        format!("`{item}` is specified to be `{}` here", old_proj.term()),
+                    )
+                    .with_span_label(
+                        proj_span,
+                        format!("`{item}` is specified to be `{}` here", proj.term()),
+                    )
+                    .emit();
+            }
+        }
+
         let principal_trait = regular_traits.into_iter().next();
 
-        let mut needed_associated_types = FxIndexSet::default();
-        if let Some((principal_trait, spans)) = &principal_trait {
-            let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx);
-            for ClauseWithSupertraitSpan { pred, supertrait_span } in traits::elaborate(
+        let mut needed_associated_types = vec![];
+        if let Some((principal_trait, ref spans)) = principal_trait {
+            let principal_trait = principal_trait.map_bound(|trait_pred| {
+                assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
+                trait_pred.trait_ref
+            });
+
+            for ClauseWithSupertraitSpan { clause, supertrait_span } in traits::elaborate(
                 tcx,
-                [ClauseWithSupertraitSpan::new(pred, *spans.last().unwrap())],
+                [ClauseWithSupertraitSpan::new(
+                    ty::TraitRef::identity(tcx, principal_trait.def_id()).upcast(tcx),
+                    *spans.last().unwrap(),
+                )],
             )
             .filter_only_self()
             {
-                debug!("observing object predicate `{pred:?}`");
+                let clause = clause.instantiate_supertrait(tcx, principal_trait);
+                debug!("observing object predicate `{clause:?}`");
 
-                let bound_predicate = pred.kind();
+                let bound_predicate = clause.kind();
                 match bound_predicate.skip_binder() {
-                    ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
+                    ty::ClauseKind::Trait(pred) => {
                         // FIXME(negative_bounds): Handle this correctly...
                         let trait_ref =
                             tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
                         needed_associated_types.extend(
-                            tcx.associated_items(trait_ref.def_id())
+                            tcx.associated_items(pred.trait_ref.def_id)
                                 .in_definition_order()
+                                // We only care about associated types.
                                 .filter(|item| item.kind == ty::AssocKind::Type)
+                                // No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit.
                                 .filter(|item| !item.is_impl_trait_in_trait())
                                 // If the associated type has a `where Self: Sized` bound,
                                 // we do not need to constrain the associated type.
@@ -133,7 +185,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                 .map(|item| (item.def_id, trait_ref)),
                         );
                     }
-                    ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
+                    ty::ClauseKind::Projection(pred) => {
                         let pred = bound_predicate.rebind(pred);
                         // A `Self` within the original bound will be instantiated with a
                         // `trait_object_dummy_self`, so check for that.
@@ -161,8 +213,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
                         // the discussion in #56288 for alternatives.
                         if !references_self {
-                            // Include projections defined on supertraits.
-                            projection_bounds.push((pred, supertrait_span));
+                            let key = (
+                                pred.skip_binder().projection_term.def_id,
+                                tcx.anonymize_bound_vars(
+                                    pred.map_bound(|proj| proj.projection_term.trait_ref(tcx)),
+                                ),
+                            );
+                            if !projection_bounds.contains_key(&key) {
+                                projection_bounds.insert(key, (pred, supertrait_span));
+                            }
                         }
 
                         self.check_elaborated_projection_mentions_input_lifetimes(
@@ -182,12 +241,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         // types that we expect to be provided by the user, so the following loop
         // removes all the associated types that have a corresponding `Projection`
         // clause, either from expanding trait aliases or written by the user.
-        for &(projection_bound, span) in &projection_bounds {
+        for &(projection_bound, span) in projection_bounds.values() {
             let def_id = projection_bound.item_def_id();
-            let trait_ref = tcx.anonymize_bound_vars(
-                projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)),
-            );
-            needed_associated_types.swap_remove(&(def_id, trait_ref));
             if tcx.generics_require_sized_self(def_id) {
                 tcx.emit_node_span_lint(
                     UNUSED_ASSOCIATED_TYPE_BOUNDS,
@@ -198,9 +253,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             }
         }
 
+        let mut missing_assoc_types = FxIndexSet::default();
+        let projection_bounds: Vec<_> = needed_associated_types
+            .into_iter()
+            .filter_map(|key| {
+                if let Some(assoc) = projection_bounds.get(&key) {
+                    Some(*assoc)
+                } else {
+                    missing_assoc_types.insert(key);
+                    None
+                }
+            })
+            .collect();
+
         if let Err(guar) = self.check_for_required_assoc_tys(
             principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()),
-            needed_associated_types,
+            missing_assoc_types,
             potential_assoc_types,
             hir_bounds,
         ) {
@@ -266,7 +334,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             })
         });
 
-        let existential_projections = projection_bounds.iter().map(|(bound, _)| {
+        let existential_projections = projection_bounds.into_iter().map(|(bound, _)| {
             bound.map_bound(|mut b| {
                 assert_eq!(b.projection_term.self_ty(), dummy_self);
 
@@ -291,12 +359,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             })
         });
 
-        let auto_trait_predicates = auto_traits.into_iter().map(|(trait_pred, _)| {
-            assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
-            assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
+        let mut auto_trait_predicates: Vec<_> = auto_traits
+            .into_iter()
+            .map(|(trait_pred, _)| {
+                assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive);
+                assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self);
 
-            ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
-        });
+                ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id()))
+            })
+            .collect();
+        auto_trait_predicates.dedup();
 
         // N.b. principal, projections, auto traits
         // FIXME: This is actually wrong with multiple principals in regards to symbol mangling
@@ -306,7 +378,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             .chain(auto_trait_predicates)
             .collect::<SmallVec<[_; 8]>>();
         v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
-        v.dedup();
         let existential_predicates = tcx.mk_poly_existential_predicates(&v);
 
         // Use explicitly-specified region bound, unless the bound is missing.
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index d2956d94685..0b3af7d6aba 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -86,8 +86,7 @@ declare_lint! {
     ///
     /// ### Example
     ///
-    /// ```rust,compile_fail
-    /// # #![feature(lifetime_capture_rules_2024)]
+    /// ```rust,edition2024,compile_fail
     /// # #![deny(impl_trait_redundant_captures)]
     /// fn test<'a>(x: &'a i32) -> impl Sized + use<'a> { x }
     /// ```
@@ -268,8 +267,7 @@ where
             && parent == self.parent_def_id
         {
             let opaque_span = self.tcx.def_span(opaque_def_id);
-            let new_capture_rules = opaque_span.at_least_rust_2024()
-                || self.tcx.features().lifetime_capture_rules_2024();
+            let new_capture_rules = opaque_span.at_least_rust_2024();
             if !new_capture_rules
                 && !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
             {
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 98e8f269c57..af09a6d570b 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -1364,13 +1364,13 @@ impl PlaceContext {
         matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
     }
 
-    /// Returns `true` if this place context represents a borrow.
+    /// Returns `true` if this place context represents a borrow, excluding fake borrows
+    /// (which are an artifact of borrowck and not actually borrows in runtime MIR).
     pub fn is_borrow(self) -> bool {
         matches!(
             self,
-            PlaceContext::NonMutatingUse(
-                NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow
-            ) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
+                | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
         )
     }
 
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 53bc9eb7e46..54cd8cc3efe 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -12,7 +12,7 @@ use std::borrow::Cow;
 use std::hash::{Hash, Hasher};
 use std::sync::Arc;
 
-use rustc_errors::{Applicability, Diag, EmissionGuarantee};
+use rustc_errors::{Applicability, Diag, EmissionGuarantee, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::HirId;
 use rustc_hir::def_id::DefId;
@@ -996,4 +996,7 @@ pub enum CodegenObligationError {
     /// but was included during typeck due to the trivial_bounds feature.
     Unimplemented,
     FulfillmentError,
+    /// The selected impl has unconstrained generic parameters. This will emit an error
+    /// during impl WF checking.
+    UnconstrainedParam(ErrorGuaranteed),
 }
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index afdec7a86d4..839c1c346a4 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -79,20 +79,14 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
         b: Self,
     ) -> RelateResult<'tcx, Self> {
         let tcx = relation.cx();
-
-        // FIXME: this is wasteful, but want to do a perf run to see how slow it is.
-        // We need to perform this deduplication as we sometimes generate duplicate projections
-        // in `a`.
-        let mut a_v: Vec<_> = a.into_iter().collect();
-        let mut b_v: Vec<_> = b.into_iter().collect();
-        a_v.dedup();
-        b_v.dedup();
-        if a_v.len() != b_v.len() {
+        // Fast path for when the auto traits do not match, or if the principals
+        // are from different traits and therefore the projections definitely don't
+        // match up.
+        if a.len() != b.len() {
             return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
         }
-
-        let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
-            match (ep_a.skip_binder(), ep_b.skip_binder()) {
+        let v =
+            iter::zip(a, b).map(|(ep_a, ep_b)| match (ep_a.skip_binder(), ep_b.skip_binder()) {
                 (ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
                     Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
                         relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
@@ -109,8 +103,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<
                     ty::ExistentialPredicate::AutoTrait(b),
                 ) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
                 _ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
-            }
-        });
+            });
         tcx.mk_poly_existential_predicates_from_iter(v)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 8a31b296018..9eda7608707 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -18,7 +18,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 use rustc_type_ir::TyKind::*;
 use rustc_type_ir::visit::TypeVisitableExt;
-use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind};
+use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, elaborate};
 use tracing::instrument;
 use ty::util::{AsyncDropGlueMorphology, IntTypeExt};
 
@@ -720,6 +720,34 @@ impl<'tcx> Ty<'tcx> {
         reg: ty::Region<'tcx>,
         repr: DynKind,
     ) -> Ty<'tcx> {
+        if cfg!(debug_assertions) {
+            let projection_count = obj.projection_bounds().count();
+            let expected_count: usize = obj
+                .principal_def_id()
+                .into_iter()
+                .flat_map(|principal_def_id| {
+                    // NOTE: This should agree with `needed_associated_types` in
+                    // dyn trait lowering, or else we'll have ICEs.
+                    elaborate::supertraits(
+                        tcx,
+                        ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)),
+                    )
+                    .map(|principal| {
+                        tcx.associated_items(principal.def_id())
+                            .in_definition_order()
+                            .filter(|item| item.kind == ty::AssocKind::Type)
+                            .filter(|item| !item.is_impl_trait_in_trait())
+                            .filter(|item| !tcx.generics_require_sized_self(item.def_id))
+                            .count()
+                    })
+                })
+                .sum();
+            assert_eq!(
+                projection_count, expected_count,
+                "expected {obj:?} to have {expected_count} projections, \
+                but it has {projection_count}"
+            );
+        }
         Ty::new(tcx, Dynamic(obj, reg, repr))
     }
 
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 7eeed721d5a..9cae7f27947 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -1,6 +1,6 @@
 use std::cmp::Ordering;
 
-use rustc_type_ir::data_structures::HashMap;
+use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
 use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::solve::{Goal, QueryInput};
@@ -389,7 +389,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
             | ty::Alias(_, _)
             | ty::Bound(_, _)
             | ty::Error(_) => {
-                return t.super_fold_with(self);
+                return ensure_sufficient_stack(|| t.super_fold_with(self));
             }
         };
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index a8ee4d61e65..c92dfa24f85 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -192,19 +192,38 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
                         let have_alt_message = message.is_some() || label.is_some();
                         let is_try_conversion = self.is_try_conversion(span, main_trait_predicate.def_id());
+                        let is_question_mark = matches!(
+                            root_obligation.cause.code().peel_derives(),
+                            ObligationCauseCode::QuestionMark,
+                        ) && !(
+                            self.tcx.is_diagnostic_item(sym::FromResidual, main_trait_predicate.def_id())
+                                || self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::Try)
+                        );
                         let is_unsize =
                             self.tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Unsize);
+                        let question_mark_message = "the question mark operation (`?`) implicitly \
+                                                     performs a conversion on the error value \
+                                                     using the `From` trait";
                         let (message, notes, append_const_msg) = if is_try_conversion {
+                            // We have a `-> Result<_, E1>` and `gives_E2()?`.
                             (
                                 Some(format!(
                                     "`?` couldn't convert the error to `{}`",
                                     main_trait_predicate.skip_binder().self_ty(),
                                 )),
-                                vec![
-                                    "the question mark operation (`?`) implicitly performs a \
-                                     conversion on the error value using the `From` trait"
-                                        .to_owned(),
-                                ],
+                                vec![question_mark_message.to_owned()],
+                                Some(AppendConstMessage::Default),
+                            )
+                        } else if is_question_mark {
+                            // Similar to the case above, but in this case the conversion is for a
+                            // trait object: `-> Result<_, Box<dyn Error>` and `gives_E()?` when
+                            // `E: Error` isn't met.
+                            (
+                                Some(format!(
+                                    "`?` couldn't convert the error: `{main_trait_predicate}` is \
+                                     not satisfied",
+                                )),
+                                vec![question_mark_message.to_owned()],
                                 Some(AppendConstMessage::Default),
                             )
                         } else {
@@ -220,8 +239,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             &mut long_ty_file,
                         );
 
-                        let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(main_trait_predicate.def_id(), LangItem::TransmuteTrait)
-                        {
+                        let (err_msg, safe_transmute_explanation) = if self.tcx.is_lang_item(
+                            main_trait_predicate.def_id(),
+                            LangItem::TransmuteTrait,
+                        ) {
                             // Recompute the safe transmute reason and use that for the error reporting
                             match self.get_safe_transmute_error_and_reason(
                                 obligation.clone(),
@@ -249,18 +270,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         *err.long_ty_path() = long_ty_file;
 
                         let mut suggested = false;
-                        if is_try_conversion {
+                        if is_try_conversion || is_question_mark {
                             suggested = self.try_conversion_context(&obligation, main_trait_predicate, &mut err);
                         }
 
-                        if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
-                            err.span_label(
-                                ret_span,
-                                format!(
-                                    "expected `{}` because of this",
-                                    main_trait_predicate.skip_binder().self_ty()
-                                ),
-                            );
+                        if let Some(ret_span) = self.return_type_span(&obligation) {
+                            if is_try_conversion {
+                                err.span_label(
+                                    ret_span,
+                                    format!(
+                                        "expected `{}` because of this",
+                                        main_trait_predicate.skip_binder().self_ty()
+                                    ),
+                                );
+                            } else if is_question_mark {
+                                err.span_label(ret_span, format!("required `{main_trait_predicate}` because of this"));
+                            }
                         }
 
                         if tcx.is_lang_item(leaf_trait_predicate.def_id(), LangItem::Tuple) {
@@ -302,10 +327,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             // If it has a custom `#[rustc_on_unimplemented]`
                             // error message, let's display it as the label!
                             err.span_label(span, s);
-                            if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_)) {
+                            if !matches!(leaf_trait_predicate.skip_binder().self_ty().kind(), ty::Param(_))
                                 // When the self type is a type param We don't need to "the trait
                                 // `std::marker::Sized` is not implemented for `T`" as we will point
                                 // at the type param with a label to suggest constraining it.
+                                && !self.tcx.is_diagnostic_item(sym::FromResidual, leaf_trait_predicate.def_id())
+                                    // Don't say "the trait `FromResidual<Option<Infallible>>` is
+                                    // not implemented for `Result<T, E>`".
+                            {
                                 err.help(explanation);
                             }
                         } else if let Some(custom_explanation) = safe_transmute_explanation {
@@ -932,16 +961,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         let Some(typeck) = &self.typeck_results else {
             return false;
         };
-        let Some((ObligationCauseCode::QuestionMark, Some(y))) =
-            obligation.cause.code().parent_with_predicate()
-        else {
+        let ObligationCauseCode::QuestionMark = obligation.cause.code().peel_derives() else {
             return false;
         };
-        if !self.tcx.is_diagnostic_item(sym::FromResidual, y.def_id()) {
-            return false;
-        }
         let self_ty = trait_pred.skip_binder().self_ty();
         let found_ty = trait_pred.skip_binder().trait_ref.args.get(1).and_then(|a| a.as_type());
+        self.note_missing_impl_for_question_mark(err, self_ty, found_ty, trait_pred);
 
         let mut prev_ty = self.resolve_vars_if_possible(
             typeck.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(self.tcx)),
@@ -1106,6 +1131,56 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         suggested
     }
 
+    fn note_missing_impl_for_question_mark(
+        &self,
+        err: &mut Diag<'_>,
+        self_ty: Ty<'_>,
+        found_ty: Option<Ty<'_>>,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
+    ) {
+        match (self_ty.kind(), found_ty) {
+            (ty::Adt(def, _), Some(ty))
+                if let ty::Adt(found, _) = ty.kind()
+                    && def.did().is_local()
+                    && found.did().is_local() =>
+            {
+                err.span_note(
+                    self.tcx.def_span(def.did()),
+                    format!("`{self_ty}` needs to implement `From<{ty}>`"),
+                );
+                err.span_note(
+                    self.tcx.def_span(found.did()),
+                    format!("alternatively, `{ty}` needs to implement `Into<{self_ty}>`"),
+                );
+            }
+            (ty::Adt(def, _), None) if def.did().is_local() => {
+                err.span_note(
+                    self.tcx.def_span(def.did()),
+                    format!(
+                        "`{self_ty}` needs to implement `{}`",
+                        trait_pred.skip_binder().trait_ref.print_only_trait_path(),
+                    ),
+                );
+            }
+            (ty::Adt(def, _), Some(ty)) if def.did().is_local() => {
+                err.span_note(
+                    self.tcx.def_span(def.did()),
+                    format!("`{self_ty}` needs to implement `From<{ty}>`"),
+                );
+            }
+            (_, Some(ty))
+                if let ty::Adt(def, _) = ty.kind()
+                    && def.did().is_local() =>
+            {
+                err.span_note(
+                    self.tcx.def_span(def.did()),
+                    format!("`{ty}` needs to implement `Into<{self_ty}>`"),
+                );
+            }
+            _ => {}
+        }
+    }
+
     fn report_const_param_not_wf(
         &self,
         ty: Ty<'tcx>,
@@ -2035,6 +2110,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 return false;
             }
             if let &[cand] = &candidates[..] {
+                if self.tcx.is_diagnostic_item(sym::FromResidual, cand.def_id)
+                    && !self.tcx.features().enabled(sym::try_trait_v2)
+                {
+                    return false;
+                }
                 let (desc, mention_castable) =
                     match (cand.self_ty().kind(), trait_pred.self_ty().skip_binder().kind()) {
                         (ty::FnPtr(..), ty::FnDef(..)) => {
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index e5276e6d515..cc329ca3328 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -80,16 +80,14 @@ pub(crate) fn codegen_select_candidate<'tcx>(
         // but never resolved, causing the return value of a query to contain inference
         // vars. We do not have a concept for this and will in fact ICE in stable hashing
         // of the return value. So bail out instead.
-        match impl_source {
-            ImplSource::UserDefined(impl_) => {
-                tcx.dcx().span_delayed_bug(
-                    tcx.def_span(impl_.impl_def_id),
-                    "this impl has unconstrained generic parameters",
-                );
-            }
+        let guar = match impl_source {
+            ImplSource::UserDefined(impl_) => tcx.dcx().span_delayed_bug(
+                tcx.def_span(impl_.impl_def_id),
+                "this impl has unconstrained generic parameters",
+            ),
             _ => unreachable!(),
-        }
-        return Err(CodegenObligationError::FulfillmentError);
+        };
+        return Err(CodegenObligationError::UnconstrainedParam(guar));
     }
 
     Ok(&*tcx.arena.alloc(impl_source))
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 8c6e3c86bf5..d059d6dcd13 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -112,6 +112,7 @@ fn resolve_associated_item<'tcx>(
             | CodegenObligationError::Unimplemented
             | CodegenObligationError::FulfillmentError,
         ) => return Ok(None),
+        Err(CodegenObligationError::UnconstrainedParam(guar)) => return Err(guar),
     };
 
     // Now that we know which impl is being used, we can dispatch to
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index b6a14d147ca..c8b3c8a796f 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -147,12 +147,25 @@ fn extract_const_value<'tcx>(
 ) -> Result<ty::Value<'tcx>, &'tcx LayoutError<'tcx>> {
     match ct.kind() {
         ty::ConstKind::Value(cv) => Ok(cv),
-        ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => {
+        ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => {
             if !ct.has_param() {
                 bug!("failed to normalize const, but it is not generic: {ct:?}");
             }
             Err(error(cx, LayoutError::TooGeneric(ty)))
         }
+        ty::ConstKind::Unevaluated(_) => {
+            let err = if ct.has_param() {
+                LayoutError::TooGeneric(ty)
+            } else {
+                // This case is reachable with unsatisfiable predicates and GCE (which will
+                // cause anon consts to inherit the unsatisfiable predicates). For example
+                // if we have an unsatisfiable `u8: Trait` bound, then it's not a compile
+                // error to mention `[u8; <u8 as Trait>::CONST]`, but we can't compute its
+                // layout.
+                LayoutError::Unknown(ty)
+            };
+            Err(error(cx, err))
+        }
         ty::ConstKind::Infer(_)
         | ty::ConstKind::Bound(..)
         | ty::ConstKind::Placeholder(_)
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index 923b74abdfd..b11bcff1d8b 100644
--- a/compiler/rustc_type_ir/src/elaborate.rs
+++ b/compiler/rustc_type_ir/src/elaborate.rs
@@ -44,25 +44,22 @@ pub trait Elaboratable<I: Interner> {
 }
 
 pub struct ClauseWithSupertraitSpan<I: Interner> {
-    pub pred: I::Predicate,
+    pub clause: I::Clause,
     // Span of the supertrait predicatae that lead to this clause.
     pub supertrait_span: I::Span,
 }
 impl<I: Interner> ClauseWithSupertraitSpan<I> {
-    pub fn new(pred: I::Predicate, span: I::Span) -> Self {
-        ClauseWithSupertraitSpan { pred, supertrait_span: span }
+    pub fn new(clause: I::Clause, span: I::Span) -> Self {
+        ClauseWithSupertraitSpan { clause, supertrait_span: span }
     }
 }
 impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
     fn predicate(&self) -> <I as Interner>::Predicate {
-        self.pred
+        self.clause.as_predicate()
     }
 
     fn child(&self, clause: <I as Interner>::Clause) -> Self {
-        ClauseWithSupertraitSpan {
-            pred: clause.as_predicate(),
-            supertrait_span: self.supertrait_span,
-        }
+        ClauseWithSupertraitSpan { clause, supertrait_span: self.supertrait_span }
     }
 
     fn child_with_derived_cause(
@@ -72,7 +69,7 @@ impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
         _parent_trait_pred: crate::Binder<I, crate::TraitPredicate<I>>,
         _index: usize,
     ) -> Self {
-        ClauseWithSupertraitSpan { pred: clause.as_predicate(), supertrait_span }
+        ClauseWithSupertraitSpan { clause, supertrait_span }
     }
 }
 
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 22bd46c567e..8b211b442ea 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -1168,6 +1168,7 @@ impl Div<u32> for Duration {
     type Output = Duration;
 
     #[inline]
+    #[track_caller]
     fn div(self, rhs: u32) -> Duration {
         self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar")
     }
@@ -1176,6 +1177,7 @@ impl Div<u32> for Duration {
 #[stable(feature = "time_augmented_assignment", since = "1.9.0")]
 impl DivAssign<u32> for Duration {
     #[inline]
+    #[track_caller]
     fn div_assign(&mut self, rhs: u32) {
         *self = *self / rhs;
     }
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index b3f4a7bad99..5fc3e8469bb 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1762,7 +1762,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
             cmd.arg("--coverage-dump-path").arg(coverage_dump);
         }
 
-        cmd.arg("--src-base").arg(builder.src.join("tests").join(suite));
+        cmd.arg("--src-root").arg(&builder.src);
+        cmd.arg("--src-test-suite-root").arg(builder.src.join("tests").join(suite));
+
         cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
 
         // When top stage is 0, that means that we're testing an externally provided compiler.
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 1614c35cb1c..98ab7adf5a7 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -215,8 +215,10 @@ pub struct Config {
     /// `None` then these tests will be ignored.
     pub run_clang_based_tests_with: Option<String>,
 
-    /// The directory containing the tests to run
-    pub src_base: PathBuf,
+    /// The directory containing the sources.
+    pub src_root: PathBuf,
+    /// The directory containing the test suite sources. Must be a subdirectory of `src_root`.
+    pub src_test_suite_root: PathBuf,
 
     /// The directory where programs should be built
     pub build_base: PathBuf,
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 452a2e9a9d5..3bdf37a1f29 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -1026,19 +1026,6 @@ impl Config {
         }
     }
 
-    pub fn find_rust_src_root(&self) -> Option<PathBuf> {
-        let mut path = self.src_base.clone();
-        let path_postfix = Path::new("src/etc/lldb_batchmode.py");
-
-        while path.pop() {
-            if path.join(&path_postfix).is_file() {
-                return Some(path);
-            }
-        }
-
-        None
-    }
-
     fn parse_edition(&self, line: &str) -> Option<String> {
         self.parse_name_value_directive(line, "edition")
     }
@@ -1098,7 +1085,7 @@ fn expand_variables(mut value: String, config: &Config) -> String {
     }
 
     if value.contains(SRC_BASE) {
-        value = value.replace(SRC_BASE, &config.src_base.to_string_lossy());
+        value = value.replace(SRC_BASE, &config.src_test_suite_root.to_str().unwrap());
     }
 
     if value.contains(BUILD_BASE) {
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index c65f10a52bd..c9536b7a19b 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -153,7 +153,8 @@ impl ConfigBuilder {
             "--run-lib-path=",
             "--python=",
             "--jsondocck-path=",
-            "--src-base=",
+            "--src-root=",
+            "--src-test-suite-root=",
             "--build-base=",
             "--sysroot-base=",
             "--cc=c",
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index d0a83cab9cd..97982170138 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -61,7 +61,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
         .optopt("", "jsondoclint-path", "path to jsondoclint to use for doc tests", "PATH")
         .optopt("", "run-clang-based-tests-with", "path to Clang executable", "PATH")
         .optopt("", "llvm-filecheck", "path to LLVM's FileCheck binary", "DIR")
-        .reqopt("", "src-base", "directory to scan for test files", "PATH")
+        .reqopt("", "src-root", "directory containing sources", "PATH")
+        .reqopt("", "src-test-suite-root", "directory containing test suite sources", "PATH")
         .reqopt("", "build-base", "directory to deposit test outputs", "PATH")
         .reqopt("", "sysroot-base", "directory containing the compiler sysroot", "PATH")
         .reqopt("", "stage", "stage number under test", "N")
@@ -243,7 +244,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
             || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
         );
 
-    let src_base = opt_path(matches, "src-base");
     let run_ignored = matches.opt_present("ignored");
     let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
     let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions");
@@ -300,6 +300,15 @@ pub fn parse_config(args: Vec<String>) -> Config {
         None => panic!("`--stage` is required"),
     };
 
+    let src_root = opt_path(matches, "src-root");
+    let src_test_suite_root = opt_path(matches, "src-test-suite-root");
+    assert!(
+        src_test_suite_root.starts_with(&src_root),
+        "`src-root` must be a parent of `src-test-suite-root`: `src-root`=`{}`, `src-test-suite-root` = `{}`",
+        src_root.display(),
+        src_test_suite_root.display()
+    );
+
     Config {
         bless: matches.opt_present("bless"),
         compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
@@ -314,7 +323,10 @@ pub fn parse_config(args: Vec<String>) -> Config {
         run_clang_based_tests_with: matches.opt_str("run-clang-based-tests-with"),
         llvm_filecheck: matches.opt_str("llvm-filecheck").map(PathBuf::from),
         llvm_bin_dir: matches.opt_str("llvm-bin-dir").map(PathBuf::from),
-        src_base,
+
+        src_root,
+        src_test_suite_root,
+
         build_base: opt_path(matches, "build-base"),
         sysroot_base: opt_path(matches, "sysroot-base"),
 
@@ -422,7 +434,10 @@ pub fn log_config(config: &Config) {
     logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
     logv(c, format!("cargo_path: {:?}", config.cargo_path));
     logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
-    logv(c, format!("src_base: {:?}", config.src_base.display()));
+
+    logv(c, format!("src_root: {}", config.src_root.display()));
+    logv(c, format!("src_test_suite_root: {}", config.src_test_suite_root.display()));
+
     logv(c, format!("build_base: {:?}", config.build_base.display()));
     logv(c, format!("stage: {}", config.stage));
     logv(c, format!("stage_id: {}", config.stage_id));
@@ -620,20 +635,29 @@ struct TestCollector {
 /// regardless of whether any filters/tests were specified on the command-line,
 /// because filtering is handled later by libtest.
 pub fn collect_and_make_tests(config: Arc<Config>) -> Vec<test::TestDescAndFn> {
-    debug!("making tests from {:?}", config.src_base.display());
+    debug!("making tests from {}", config.src_test_suite_root.display());
     let common_inputs_stamp = common_inputs_stamp(&config);
-    let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
-        panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
-    });
+    let modified_tests =
+        modified_tests(&config, &config.src_test_suite_root).unwrap_or_else(|err| {
+            panic!(
+                "modified_tests got error from dir: {}, error: {}",
+                config.src_test_suite_root.display(),
+                err
+            )
+        });
     let cache = HeadersCache::load(&config);
 
     let cx = TestCollectorCx { config, cache, common_inputs_stamp, modified_tests };
     let mut collector =
         TestCollector { tests: vec![], found_path_stems: HashSet::new(), poisoned: false };
 
-    collect_tests_from_dir(&cx, &mut collector, &cx.config.src_base, Path::new("")).unwrap_or_else(
-        |reason| panic!("Could not read tests from {}: {reason}", cx.config.src_base.display()),
-    );
+    collect_tests_from_dir(&cx, &mut collector, &cx.config.src_test_suite_root, Path::new(""))
+        .unwrap_or_else(|reason| {
+            panic!(
+                "Could not read tests from {}: {reason}",
+                cx.config.src_test_suite_root.display()
+            )
+        });
 
     let TestCollector { tests, found_path_stems, poisoned } = collector;
 
@@ -655,7 +679,7 @@ pub fn collect_and_make_tests(config: Arc<Config>) -> Vec<test::TestDescAndFn> {
 /// common to some subset of tests, and are hopefully unlikely to be modified
 /// while working on other tests.)
 fn common_inputs_stamp(config: &Config) -> Stamp {
-    let rust_src_dir = config.find_rust_src_root().expect("Could not find Rust source root");
+    let src_root = &config.src_root;
 
     let mut stamp = Stamp::from_path(&config.rustc_path);
 
@@ -670,17 +694,17 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
         "src/etc/lldb_providers.py",
     ];
     for file in &pretty_printer_files {
-        let path = rust_src_dir.join(file);
+        let path = src_root.join(file);
         stamp.add_path(&path);
     }
 
-    stamp.add_dir(&rust_src_dir.join("src/etc/natvis"));
+    stamp.add_dir(&src_root.join("src/etc/natvis"));
 
     stamp.add_dir(&config.run_lib_path);
 
     if let Some(ref rustdoc_path) = config.rustdoc_path {
         stamp.add_path(&rustdoc_path);
-        stamp.add_path(&rust_src_dir.join("src/etc/htmldocck.py"));
+        stamp.add_path(&src_root.join("src/etc/htmldocck.py"));
     }
 
     // Re-run coverage tests if the `coverage-dump` tool was modified,
@@ -689,10 +713,10 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
         stamp.add_path(coverage_dump_path)
     }
 
-    stamp.add_dir(&rust_src_dir.join("src/tools/run-make-support"));
+    stamp.add_dir(&src_root.join("src/tools/run-make-support"));
 
     // Compiletest itself.
-    stamp.add_dir(&rust_src_dir.join("src/tools/compiletest/"));
+    stamp.add_dir(&src_root.join("src/tools/compiletest"));
 
     stamp
 }
@@ -933,10 +957,7 @@ fn files_related_to_test(
     }
 
     // `minicore.rs` test auxiliary: we need to make sure tests get rerun if this changes.
-    //
-    // FIXME(jieyouxu): untangle these paths, we should provide both a path to root `tests/` or
-    // `tests/auxiliary/` and the test suite in question. `src_base` is also a terrible name.
-    related.push(config.src_base.parent().unwrap().join("auxiliary").join("minicore.rs"));
+    related.push(config.src_root.join("tests").join("auxiliary").join("minicore.rs"));
 
     related
 }
@@ -1026,10 +1047,8 @@ fn make_test_name(
     testpaths: &TestPaths,
     revision: Option<&str>,
 ) -> test::TestName {
-    // Print the name of the file, relative to the repository root.
-    // `src_base` looks like `/path/to/rust/tests/ui`
-    let root_directory = config.src_base.parent().unwrap().parent().unwrap();
-    let path = testpaths.file.strip_prefix(root_directory).unwrap();
+    // Print the name of the file, relative to the sources root.
+    let path = testpaths.file.strip_prefix(&config.src_root).unwrap();
     let debugger = match config.debugger {
         Some(d) => format!("-{}", d),
         None => String::new(),
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 0e2da2b02ca..536e19bc493 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1365,7 +1365,7 @@ impl<'test> TestCx<'test> {
         //
         // Note: avoid adding a subdirectory of an already filtered directory here, otherwise the
         // same slice of text will be double counted and the truncation might not happen.
-        add_path(&self.config.src_base);
+        add_path(&self.config.src_test_suite_root);
         add_path(&self.config.build_base);
 
         read2_abbreviated(child, &filter_paths_from_len).expect("failed to read output")
@@ -1471,7 +1471,7 @@ impl<'test> TestCx<'test> {
         // Similarly, vendored sources shouldn't be shown when running from a dist tarball.
         rustc.arg("-Z").arg(format!(
             "ignore-directory-in-diagnostics-source-blocks={}",
-            self.config.find_rust_src_root().unwrap().join("vendor").display(),
+            self.config.src_root.join("vendor").to_str().unwrap(),
         ));
 
         // Optionally prevent default --sysroot if specified in test compile-flags.
@@ -1632,7 +1632,7 @@ impl<'test> TestCx<'test> {
         if self.props.remap_src_base {
             rustc.arg(format!(
                 "--remap-path-prefix={}={}",
-                self.config.src_base.display(),
+                self.config.src_test_suite_root.to_str().unwrap(),
                 FAKE_SRC_BASE,
             ));
         }
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index b236b067569..170b8a80996 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -257,11 +257,8 @@ impl TestCx<'_> {
                 println!("Adb process is already finished.");
             }
         } else {
-            let rust_src_root =
-                self.config.find_rust_src_root().expect("Could not find Rust source root");
-            let rust_pp_module_rel_path = Path::new("./src/etc");
-            let rust_pp_module_abs_path =
-                rust_src_root.join(rust_pp_module_rel_path).to_str().unwrap().to_owned();
+            let rust_pp_module_abs_path = self.config.src_root.join("src").join("etc");
+            let rust_pp_module_abs_path = rust_pp_module_abs_path.to_str().unwrap();
             // write debugger script
             let mut script_str = String::with_capacity(2048);
             script_str.push_str(&format!("set charset {}\n", Self::charset()));
@@ -338,7 +335,7 @@ impl TestCx<'_> {
             let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
                 format!("{pp}:{rust_pp_module_abs_path}")
             } else {
-                rust_pp_module_abs_path
+                rust_pp_module_abs_path.to_string()
             };
             gdb.args(debugger_opts).env("PYTHONPATH", pythonpath);
 
@@ -407,11 +404,8 @@ impl TestCx<'_> {
         // Make LLDB emit its version, so we have it documented in the test output
         script_str.push_str("version\n");
 
-        // Switch LLDB into "Rust mode"
-        let rust_src_root =
-            self.config.find_rust_src_root().expect("Could not find Rust source root");
-        let rust_pp_module_rel_path = Path::new("./src/etc");
-        let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path);
+        // Switch LLDB into "Rust mode".
+        let rust_pp_module_abs_path = self.config.src_root.join("src/etc");
 
         script_str.push_str(&format!(
             "command script import {}/lldb_lookup.py\n",
@@ -445,7 +439,7 @@ impl TestCx<'_> {
         let debugger_script = self.make_out_name("debugger.script");
 
         // Let LLDB execute the script via lldb_batchmode.py
-        let debugger_run_result = self.run_lldb(&exe_file, &debugger_script, &rust_src_root);
+        let debugger_run_result = self.run_lldb(&exe_file, &debugger_script);
 
         if !debugger_run_result.status.success() {
             self.fatal_proc_rec("Error while running LLDB", &debugger_run_result);
@@ -456,18 +450,13 @@ impl TestCx<'_> {
         }
     }
 
-    fn run_lldb(
-        &self,
-        test_executable: &Path,
-        debugger_script: &Path,
-        rust_src_root: &Path,
-    ) -> ProcRes {
+    fn run_lldb(&self, test_executable: &Path, debugger_script: &Path) -> ProcRes {
         // Prepare the lldb_batchmode which executes the debugger script
-        let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
+        let lldb_script_path = self.config.src_root.join("src/etc/lldb_batchmode.py");
         let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
             format!("{pp}:{}", self.config.lldb_python_dir.as_ref().unwrap())
         } else {
-            self.config.lldb_python_dir.as_ref().unwrap().to_string()
+            self.config.lldb_python_dir.clone().unwrap()
         };
         self.run_command_to_procres(
             Command::new(&self.config.python)
diff --git a/src/tools/compiletest/src/runtest/js_doc.rs b/src/tools/compiletest/src/runtest/js_doc.rs
index a83bcd70c87..d630affbec1 100644
--- a/src/tools/compiletest/src/runtest/js_doc.rs
+++ b/src/tools/compiletest/src/runtest/js_doc.rs
@@ -9,12 +9,11 @@ impl TestCx<'_> {
 
             self.document(&out_dir, &self.testpaths);
 
-            let root = self.config.find_rust_src_root().unwrap();
             let file_stem =
                 self.testpaths.file.file_stem().and_then(|f| f.to_str()).expect("no file stem");
             let res = self.run_command_to_procres(
                 Command::new(&nodejs)
-                    .arg(root.join("src/tools/rustdoc-js/tester.js"))
+                    .arg(self.config.src_root.join("src/tools/rustdoc-js/tester.js"))
                     .arg("--doc-folder")
                     .arg(out_dir)
                     .arg("--crate-name")
diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
index 16c46fc1339..74e6af36ea1 100644
--- a/src/tools/compiletest/src/runtest/run_make.rs
+++ b/src/tools/compiletest/src/runtest/run_make.rs
@@ -21,8 +21,6 @@ impl TestCx<'_> {
 
     fn run_rmake_legacy_test(&self) {
         let cwd = env::current_dir().unwrap();
-        let src_root = self.config.src_base.parent().unwrap().parent().unwrap();
-        let src_root = cwd.join(&src_root);
 
         // FIXME(Zalathar): This should probably be `output_base_dir` to avoid
         // an unnecessary extra subdirectory, but since legacy Makefile tests
@@ -51,7 +49,7 @@ impl TestCx<'_> {
             .stderr(Stdio::piped())
             .env("TARGET", &self.config.target)
             .env("PYTHON", &self.config.python)
-            .env("S", src_root)
+            .env("S", &self.config.src_root)
             .env("RUST_BUILD_STAGE", &self.config.stage_id)
             .env("RUSTC", cwd.join(&self.config.rustc_path))
             .env("TMPDIR", &tmpdir)
@@ -181,28 +179,10 @@ impl TestCx<'_> {
         //    library.
         // 2. We need to run the recipe binary.
 
-        // So we assume the rust-lang/rust project setup looks like the following (our `.` is the
-        // top-level directory, irrelevant entries to our purposes omitted):
-        //
-        // ```
-        // .                               // <- `source_root`
-        // ├── build/                      // <- `build_root`
-        // ├── compiler/
-        // ├── library/
-        // ├── src/
-        // │  └── tools/
-        // │     └── run_make_support/
-        // └── tests
-        //    └── run-make/
-        // ```
-
-        // `source_root` is the top-level directory containing the rust-lang/rust checkout.
-        let source_root =
-            self.config.find_rust_src_root().expect("could not determine rust source root");
         // `self.config.build_base` is actually the build base folder + "test" + test suite name, it
         // looks like `build/<host_triple>/test/run-make`. But we want `build/<host_triple>/`. Note
         // that the `build` directory does not need to be called `build`, nor does it need to be
-        // under `source_root`, so we must compute it based off of `self.config.build_base`.
+        // under `src_root`, so we must compute it based off of `self.config.build_base`.
         let build_root =
             self.config.build_base.parent().and_then(Path::parent).unwrap().to_path_buf();
 
@@ -389,10 +369,9 @@ impl TestCx<'_> {
             .env("TARGET", &self.config.target)
             // Some tests unfortunately still need Python, so provide path to a Python interpreter.
             .env("PYTHON", &self.config.python)
-            // Provide path to checkout root. This is the top-level directory containing
-            // rust-lang/rust checkout.
-            .env("SOURCE_ROOT", &source_root)
-            // Path to the build directory. This is usually the same as `source_root.join("build").join("host")`.
+            // Provide path to sources root.
+            .env("SOURCE_ROOT", &self.config.src_root)
+            // Path to the host build directory.
             .env("BUILD_ROOT", &build_root)
             // Provide path to stage-corresponding rustc.
             .env("RUSTC", &self.config.rustc_path)
@@ -408,11 +387,11 @@ impl TestCx<'_> {
             .env("LLVM_COMPONENTS", &self.config.llvm_components);
 
         if let Some(ref cargo) = self.config.cargo_path {
-            cmd.env("CARGO", source_root.join(cargo));
+            cmd.env("CARGO", cargo);
         }
 
         if let Some(ref rustdoc) = self.config.rustdoc_path {
-            cmd.env("RUSTDOC", source_root.join(rustdoc));
+            cmd.env("RUSTDOC", rustdoc);
         }
 
         if let Some(ref node) = self.config.nodejs {
diff --git a/src/tools/compiletest/src/runtest/rustdoc.rs b/src/tools/compiletest/src/runtest/rustdoc.rs
index 3f33862d2cf..2583ae96a67 100644
--- a/src/tools/compiletest/src/runtest/rustdoc.rs
+++ b/src/tools/compiletest/src/runtest/rustdoc.rs
@@ -17,9 +17,10 @@ impl TestCx<'_> {
         if self.props.check_test_line_numbers_match {
             self.check_rustdoc_test_option(proc_res);
         } else {
-            let root = self.config.find_rust_src_root().unwrap();
             let mut cmd = Command::new(&self.config.python);
-            cmd.arg(root.join("src/etc/htmldocck.py")).arg(&out_dir).arg(&self.testpaths.file);
+            cmd.arg(self.config.src_root.join("src/etc/htmldocck.py"))
+                .arg(&out_dir)
+                .arg(&self.testpaths.file);
             if self.config.bless {
                 cmd.arg("--bless");
             }
diff --git a/tests/crashes/125957.rs b/tests/crashes/125957.rs
deleted file mode 100644
index e3abe5262eb..00000000000
--- a/tests/crashes/125957.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ known-bug: rust-lang/rust#125957
-#![feature(generic_const_exprs)]
-#![allow(incomplete_features)]
-#![feature(associated_const_equality)]
-
-pub struct Equal<const T: usize, const R: usize>();
-
-pub enum ParseMode {
-    Raw,
-}
-pub trait Parse {
-    const PARSE_MODE: ParseMode;
-}
-pub trait RenderRaw: Parse<PARSE_MODE = { ParseMode::Raw }> {}
-
-trait GenericVec<T> {
-    fn unwrap() -> dyn RenderRaw;
-}
-
-fn main() {}
diff --git a/tests/crashes/132330.rs b/tests/crashes/132330.rs
deleted file mode 100644
index 3432685749d..00000000000
--- a/tests/crashes/132330.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//@ known-bug: #132330
-//@compile-flags: -Znext-solver=globally
-
-trait Service {
-    type S;
-}
-
-trait Framing {
-    type F;
-}
-
-impl Framing for () {
-    type F = ();
-}
-
-trait HttpService<F: Framing>: Service<S = F::F> {}
-
-type BoxService = Box<dyn HttpService<(), S = ()>>;
-
-fn build_server<F: FnOnce() -> BoxService>(_: F) {}
-
-fn make_server<F: Framing>() -> Box<dyn HttpService<F, S = F::F>> {
-    unimplemented!()
-}
-
-fn main() {
-    build_server(|| make_server())
-}
diff --git a/tests/ui/associated-consts/issue-93775.rs b/tests/ui/associated-consts/issue-93775.rs
index 88e88b55987..a9b8d10a83f 100644
--- a/tests/ui/associated-consts/issue-93775.rs
+++ b/tests/ui/associated-consts/issue-93775.rs
@@ -2,11 +2,13 @@
 // Similar to stress testing, the test case requires a larger call stack,
 // so we ignore rustc's debug assertions.
 
-//@ build-pass
-// ignore-tidy-linelength
-
 // Regression for #93775, needs build-pass to test it.
 
+//@ build-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
 #![recursion_limit = "1001"]
 
 use std::marker::PhantomData;
@@ -14,7 +16,64 @@ use std::marker::PhantomData;
 struct Z;
 struct S<T>(PhantomData<T>);
 
-type Nested = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<Z>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
+type Nested = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S
+<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<Z>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;
 
 trait AsNum {
     const NUM: u32;
diff --git a/tests/ui/associated-types/associated-types-overridden-binding-2.rs b/tests/ui/associated-types/associated-types-overridden-binding-2.rs
index fed60ccf089..247724eaaf1 100644
--- a/tests/ui/associated-types/associated-types-overridden-binding-2.rs
+++ b/tests/ui/associated-types/associated-types-overridden-binding-2.rs
@@ -4,5 +4,5 @@ trait I32Iterator = Iterator<Item = i32>;
 
 fn main() {
     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
-    //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
+    //~^ ERROR conflicting associated type bounds
 }
diff --git a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr
index 4dfd275a190..71a4a2610aa 100644
--- a/tests/ui/associated-types/associated-types-overridden-binding-2.stderr
+++ b/tests/ui/associated-types/associated-types-overridden-binding-2.stderr
@@ -1,11 +1,13 @@
-error[E0271]: expected `IntoIter<u32>` to be an iterator that yields `i32`, but it yields `u32`
-  --> $DIR/associated-types-overridden-binding-2.rs:6:43
+error: conflicting associated type bounds for `Item` when expanding trait alias
+  --> $DIR/associated-types-overridden-binding-2.rs:6:13
    |
+LL | trait I32Iterator = Iterator<Item = i32>;
+   |                              ---------- `Item` is specified to be `i32` here
+...
 LL |     let _: &dyn I32Iterator<Item = u32> = &vec![42].into_iter();
-   |                                           ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
-   |
-   = note: required for the cast from `&std::vec::IntoIter<u32>` to `&dyn Iterator<Item = u32, Item = i32>`
+   |             ^^^^^^^^^^^^^^^^----------^
+   |                             |
+   |                             `Item` is specified to be `u32` here
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/associated-types/associated-types-overridden-binding.rs b/tests/ui/associated-types/associated-types-overridden-binding.rs
index 9a64a06c31b..333a3e30c7d 100644
--- a/tests/ui/associated-types/associated-types-overridden-binding.rs
+++ b/tests/ui/associated-types/associated-types-overridden-binding.rs
@@ -8,4 +8,5 @@ trait U32Iterator = I32Iterator<Item = u32>; //~ ERROR type annotations needed
 
 fn main() {
     let _: &dyn I32Iterator<Item = u32>;
+    //~^ ERROR conflicting associated type bounds
 }
diff --git a/tests/ui/associated-types/associated-types-overridden-binding.stderr b/tests/ui/associated-types/associated-types-overridden-binding.stderr
index dc087e4185f..3b20015dfca 100644
--- a/tests/ui/associated-types/associated-types-overridden-binding.stderr
+++ b/tests/ui/associated-types/associated-types-overridden-binding.stderr
@@ -22,6 +22,17 @@ note: required by a bound in `I32Iterator`
 LL | trait I32Iterator = Iterator<Item = i32>;
    |                              ^^^^^^^^^^ required by this bound in `I32Iterator`
 
-error: aborting due to 2 previous errors
+error: conflicting associated type bounds for `Item` when expanding trait alias
+  --> $DIR/associated-types-overridden-binding.rs:10:13
+   |
+LL | trait I32Iterator = Iterator<Item = i32>;
+   |                              ---------- `Item` is specified to be `i32` here
+...
+LL |     let _: &dyn I32Iterator<Item = u32>;
+   |             ^^^^^^^^^^^^^^^^----------^
+   |                             |
+   |                             `Item` is specified to be `u32` here
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/async-await/issue-84841.stderr b/tests/ui/async-await/issue-84841.stderr
index 69c1c882d60..0d008477310 100644
--- a/tests/ui/async-await/issue-84841.stderr
+++ b/tests/ui/async-await/issue-84841.stderr
@@ -17,8 +17,6 @@ LL | |     test()?;
 ...  |
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
-   |
-   = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/async-await/try-on-option-in-async.stderr b/tests/ui/async-await/try-on-option-in-async.stderr
index 9e0bb42a697..332f4d4ec0c 100644
--- a/tests/ui/async-await/try-on-option-in-async.stderr
+++ b/tests/ui/async-await/try-on-option-in-async.stderr
@@ -6,8 +6,6 @@ LL |     async {
 LL |         let x: Option<u32> = None;
 LL |         x?;
    |          ^ cannot use the `?` operator in an async block that returns `{integer}`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
 
 error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-in-async.rs:16:10
@@ -20,8 +18,6 @@ LL | |         x?;
 LL | |         22_u32
 LL | |     };
    | |_____- this function should return `Result` or `Option` to accept `?`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
 
 error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-in-async.rs:25:6
@@ -34,8 +30,6 @@ LL | |     x?;
 LL | |     22
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/closures/deduce-from-object-supertrait.rs b/tests/ui/closures/deduce-from-object-supertrait.rs
new file mode 100644
index 00000000000..aff750dc62e
--- /dev/null
+++ b/tests/ui/closures/deduce-from-object-supertrait.rs
@@ -0,0 +1,18 @@
+//@ check-pass
+
+// This test checks that we look at consider the super traits of trait objects
+// when deducing closure signatures.
+
+trait Foo: Fn(Bar) {}
+impl<T> Foo for T where T: Fn(Bar) {}
+
+struct Bar;
+impl Bar {
+    fn bar(&self) {}
+}
+
+fn main() {
+    let x: &dyn Foo = &|x| {
+        x.bar();
+    };
+}
diff --git a/tests/ui/dyn-compatibility/multiple-supers-should-work.rs b/tests/ui/dyn-compatibility/multiple-supers-should-work.rs
new file mode 100644
index 00000000000..6f381da9a22
--- /dev/null
+++ b/tests/ui/dyn-compatibility/multiple-supers-should-work.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+
+// We previously incorrectly deduplicated the list of projection bounds
+// of trait objects, causing us to incorrectly reject this code, cc #136458.
+
+trait Sup<T> {
+    type Assoc;
+}
+
+impl<T> Sup<T> for () {
+    type Assoc = T;
+}
+
+trait Trait<A, B>: Sup<A, Assoc = A> + Sup<B, Assoc = B> {}
+
+impl<T, U> Trait<T, U> for () {}
+
+fn main() {
+    let x: &dyn Trait<(), _> = &();
+    let y: &dyn Trait<_, ()> = x;
+}
diff --git a/tests/ui/impl-trait/implicit-capture-late.rs b/tests/ui/impl-trait/implicit-capture-late.rs
index 986620b101b..13cbcd66f8d 100644
--- a/tests/ui/impl-trait/implicit-capture-late.rs
+++ b/tests/ui/impl-trait/implicit-capture-late.rs
@@ -1,13 +1,13 @@
-//@ known-bug: #117647
+//@ edition: 2024
 
-#![feature(lifetime_capture_rules_2024)]
 #![feature(rustc_attrs)]
 #![allow(internal_features)]
 #![rustc_variance_of_opaques]
 
 use std::ops::Deref;
 
-fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
+fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> { //~ ['a: o]
+    //~^ ERROR cannot capture higher-ranked lifetime
     Box::new(x)
 }
 
diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr
index 3adf78322d2..085d3eaedd4 100644
--- a/tests/ui/impl-trait/implicit-capture-late.stderr
+++ b/tests/ui/impl-trait/implicit-capture-late.stderr
@@ -1,17 +1,17 @@
 error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
-  --> $DIR/implicit-capture-late.rs:10:55
+  --> $DIR/implicit-capture-late.rs:9:55
    |
 LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
    |                                                       ^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
    |
 note: lifetime declared here
-  --> $DIR/implicit-capture-late.rs:10:36
+  --> $DIR/implicit-capture-late.rs:9:36
    |
 LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
    |                                    ^^
 
 error: ['a: o]
-  --> $DIR/implicit-capture-late.rs:10:55
+  --> $DIR/implicit-capture-late.rs:9:55
    |
 LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
    |                                                       ^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/precise-capturing/higher-ranked.rs b/tests/ui/impl-trait/precise-capturing/higher-ranked.rs
index 3dc8523e963..925f03589e8 100644
--- a/tests/ui/impl-trait/precise-capturing/higher-ranked.rs
+++ b/tests/ui/impl-trait/precise-capturing/higher-ranked.rs
@@ -1,9 +1,8 @@
 //@ check-pass
+//@ edition: 2024
 
 // Show how precise captures allow us to skip capturing a higher-ranked lifetime
 
-#![feature(lifetime_capture_rules_2024)]
-
 trait Trait<'a> {
     type Item;
 }
diff --git a/tests/ui/impl-trait/precise-capturing/outlives.rs b/tests/ui/impl-trait/precise-capturing/outlives.rs
index f86a61be1e0..45e46848eea 100644
--- a/tests/ui/impl-trait/precise-capturing/outlives.rs
+++ b/tests/ui/impl-trait/precise-capturing/outlives.rs
@@ -1,9 +1,8 @@
 //@ check-pass
+//@ edition: 2024
 
 // Show that precise captures allow us to skip a lifetime param for outlives
 
-#![feature(lifetime_capture_rules_2024)]
-
 fn hello<'a: 'a, 'b: 'b>() -> impl Sized + use<'a> { }
 
 fn outlives<'a, T: 'a>(_: T) {}
diff --git a/tests/ui/impl-trait/variance.e2024.stderr b/tests/ui/impl-trait/variance.e2024.stderr
index 361a165da66..adbe8b91e86 100644
--- a/tests/ui/impl-trait/variance.e2024.stderr
+++ b/tests/ui/impl-trait/variance.e2024.stderr
@@ -1,23 +1,23 @@
 error: ['a: *, 'a: o]
-  --> $DIR/variance.rs:13:36
+  --> $DIR/variance.rs:11:36
    |
 LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
    |                                    ^^^^^^^^^^
 
 error: ['a: *, 'a: o]
-  --> $DIR/variance.rs:18:32
+  --> $DIR/variance.rs:15:32
    |
 LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: ['a: o]
-  --> $DIR/variance.rs:20:40
+  --> $DIR/variance.rs:17:40
    |
 LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
    |                                        ^^^^^^^^^^
 
 error: ['a: o]
-  --> $DIR/variance.rs:25:36
+  --> $DIR/variance.rs:21:36
    |
 LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/variance.new.stderr b/tests/ui/impl-trait/variance.new.stderr
deleted file mode 100644
index 361a165da66..00000000000
--- a/tests/ui/impl-trait/variance.new.stderr
+++ /dev/null
@@ -1,26 +0,0 @@
-error: ['a: *, 'a: o]
-  --> $DIR/variance.rs:13:36
-   |
-LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
-   |                                    ^^^^^^^^^^
-
-error: ['a: *, 'a: o]
-  --> $DIR/variance.rs:18:32
-   |
-LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: ['a: o]
-  --> $DIR/variance.rs:20:40
-   |
-LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
-   |                                        ^^^^^^^^^^
-
-error: ['a: o]
-  --> $DIR/variance.rs:25:36
-   |
-LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/impl-trait/variance.old.stderr b/tests/ui/impl-trait/variance.old.stderr
index 578d6fd14cd..57ffa7cde31 100644
--- a/tests/ui/impl-trait/variance.old.stderr
+++ b/tests/ui/impl-trait/variance.old.stderr
@@ -1,23 +1,23 @@
 error: ['a: *]
-  --> $DIR/variance.rs:13:36
+  --> $DIR/variance.rs:11:36
    |
 LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
    |                                    ^^^^^^^^^^
 
 error: ['a: *, 'a: o]
-  --> $DIR/variance.rs:18:32
+  --> $DIR/variance.rs:15:32
    |
 LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: []
-  --> $DIR/variance.rs:20:40
+  --> $DIR/variance.rs:17:40
    |
 LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
    |                                        ^^^^^^^^^^
 
 error: ['a: o]
-  --> $DIR/variance.rs:25:36
+  --> $DIR/variance.rs:21:36
    |
 LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/variance.rs b/tests/ui/impl-trait/variance.rs
index 1e359f033ff..bde3a886a4d 100644
--- a/tests/ui/impl-trait/variance.rs
+++ b/tests/ui/impl-trait/variance.rs
@@ -1,8 +1,6 @@
-//@ revisions: old new e2024
+//@ revisions: old e2024
 //@[e2024] edition: 2024
 
-#![cfg_attr(new, feature(lifetime_capture_rules_2024))]
-
 #![feature(rustc_attrs)]
 #![allow(internal_features)]
 #![rustc_variance_of_opaques]
@@ -12,15 +10,13 @@ impl<T> Captures<'_> for T {}
 
 fn not_captured_early<'a: 'a>() -> impl Sized {}
 //[old]~^ ['a: *]
-//[new]~^^ ['a: *, 'a: o]
-//[e2024]~^^^ ['a: *, 'a: o]
+//[e2024]~^^ ['a: *, 'a: o]
 
 fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ ['a: *, 'a: o]
 
 fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
 //[old]~^ []
-//[new]~^^ ['a: o]
-//[e2024]~^^^ ['a: o]
+//[e2024]~^^ ['a: o]
 
 fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ ['a: o]
 
diff --git a/tests/ui/layout/gce-rigid-const-in-array-len.rs b/tests/ui/layout/gce-rigid-const-in-array-len.rs
new file mode 100644
index 00000000000..8e57907a2c5
--- /dev/null
+++ b/tests/ui/layout/gce-rigid-const-in-array-len.rs
@@ -0,0 +1,27 @@
+//! With `feature(generic_const_exprs)`, anon consts (e.g. length in array types) will
+//! inherit their parent's predicates. When combined with `feature(trivial_bounds)`, it
+//! is possible to have an unevaluated constant that is rigid, but not generic.
+//!
+//! This is what happens below: `u8: A` does not hold in the global environment, but
+//! with trivial bounds + GCE it it possible that `<u8 as A>::B` can appear in an array
+//! length without causing a compile error. This constant is *rigid* (i.e. it cannot be
+//! normalized further), but it is *not generic* (i.e. it does not depend on any generic
+//! parameters).
+//!
+//! This test ensures that we do not ICE in layout computation when encountering such a
+//! constant.
+
+#![feature(rustc_attrs)]
+#![feature(generic_const_exprs)] //~ WARNING: the feature `generic_const_exprs` is incomplete
+#![feature(trivial_bounds)]
+
+#![crate_type = "lib"]
+
+trait A {
+    const B: usize;
+}
+
+#[rustc_layout(debug)]
+struct S([u8; <u8 as A>::B]) //~ ERROR: the type `[u8; <u8 as A>::B]` has an unknown layout
+where
+    u8: A;
diff --git a/tests/ui/layout/gce-rigid-const-in-array-len.stderr b/tests/ui/layout/gce-rigid-const-in-array-len.stderr
new file mode 100644
index 00000000000..6149debdfe8
--- /dev/null
+++ b/tests/ui/layout/gce-rigid-const-in-array-len.stderr
@@ -0,0 +1,17 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/gce-rigid-const-in-array-len.rs:15:12
+   |
+LL | #![feature(generic_const_exprs)]
+   |            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: the type `[u8; <u8 as A>::B]` has an unknown layout
+  --> $DIR/gce-rigid-const-in-array-len.rs:25:1
+   |
+LL | struct S([u8; <u8 as A>::B])
+   | ^^^^^^^^
+
+error: aborting due to 1 previous error; 1 warning emitted
+
diff --git a/tests/ui/layout/unconstrained-param-ice-137308.rs b/tests/ui/layout/unconstrained-param-ice-137308.rs
new file mode 100644
index 00000000000..c9b1e0a4b9e
--- /dev/null
+++ b/tests/ui/layout/unconstrained-param-ice-137308.rs
@@ -0,0 +1,18 @@
+//! Regression test for <https://github.com/rust-lang/rust/issues/137308>.
+//!
+//! This used to ICE in layout computation, because `<u8 as A>::B` fails to normalize
+//! due to the unconstrained param on the impl.
+
+#![feature(rustc_attrs)]
+#![crate_type = "lib"]
+
+trait A {
+    const B: usize;
+}
+
+impl<C: ?Sized> A for u8 { //~ ERROR: the type parameter `C` is not constrained
+    const B: usize = 42;
+}
+
+#[rustc_layout(debug)]
+struct S([u8; <u8 as A>::B]); //~ ERROR: the type has an unknown layout
diff --git a/tests/ui/layout/unconstrained-param-ice-137308.stderr b/tests/ui/layout/unconstrained-param-ice-137308.stderr
new file mode 100644
index 00000000000..615c131eb90
--- /dev/null
+++ b/tests/ui/layout/unconstrained-param-ice-137308.stderr
@@ -0,0 +1,15 @@
+error[E0207]: the type parameter `C` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/unconstrained-param-ice-137308.rs:13:6
+   |
+LL | impl<C: ?Sized> A for u8 {
+   |      ^ unconstrained type parameter
+
+error: the type has an unknown layout
+  --> $DIR/unconstrained-param-ice-137308.rs:18:1
+   |
+LL | struct S([u8; <u8 as A>::B]);
+   | ^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/tests/ui/lint/unaligned_references_fake_borrow.rs b/tests/ui/lint/unaligned_references_fake_borrow.rs
new file mode 100644
index 00000000000..b0ef8b471ca
--- /dev/null
+++ b/tests/ui/lint/unaligned_references_fake_borrow.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+
+// Regression test for <https://github.com/rust-lang/rust/issues/137250>.
+
+// Ensure that we don't emit unaligned packed field reference errors for the fake
+// borrows that we generate during match lowering. These fake borrows are there to
+// ensure in *borrow-checking* that we don't modify the value being matched, but
+// they are removed after the MIR is processed by `CleanupPostBorrowck`.
+
+#[repr(packed)]
+pub struct Packed(i32);
+
+fn f(x: Packed) {
+    match &x {
+        Packed(4) => {},
+        _ if true => {},
+        _ => {}
+    }
+
+    match x {
+        Packed(4) => {},
+        _ if true => {},
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr
index e22f33fd242..877995dfe12 100644
--- a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr
+++ b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr
@@ -6,7 +6,6 @@ LL | fn test1() {
 LL |     let mut _file = File::create("foo.txt")?;
    |                                            ^ cannot use the `?` operator in a function that returns `()`
    |
-   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
 help: consider adding return type
    |
 LL ~ fn test1() -> Result<(), Box<dyn std::error::Error>> {
@@ -23,7 +22,6 @@ LL | fn test2() {
 LL |     let mut _file = File::create("foo.txt")?;
    |                                            ^ cannot use the `?` operator in a function that returns `()`
    |
-   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
 help: consider adding return type
    |
 LL ~ fn test2() -> Result<(), Box<dyn std::error::Error>> {
@@ -41,7 +39,6 @@ LL |     fn test4(&self) {
 LL |         let mut _file = File::create("foo.txt")?;
    |                                                ^ cannot use the `?` operator in a method that returns `()`
    |
-   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
 help: consider adding return type
    |
 LL ~     fn test4(&self) -> Result<(), Box<dyn std::error::Error>> {
@@ -59,7 +56,6 @@ LL |     fn test5(&self) {
 LL |         let mut _file = File::create("foo.txt")?;
    |                                                ^ cannot use the `?` operator in a method that returns `()`
    |
-   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
 help: consider adding return type
    |
 LL ~     fn test5(&self) -> Result<(), Box<dyn std::error::Error>> {
@@ -78,7 +74,6 @@ LL | fn main() {
 LL |     let mut _file = File::create("foo.txt")?;
    |                                            ^ cannot use the `?` operator in a function that returns `()`
    |
-   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
 help: consider adding return type
    |
 LL ~ fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -99,7 +94,6 @@ LL |             let mut _file = File::create("foo.txt")?;
 LL |     mac!();
    |     ------ in this macro invocation
    |
-   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
    = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider adding return type
    |
diff --git a/tests/crashes/126944.rs b/tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs
index c0c5622e260..b1f7c4a6000 100644
--- a/tests/crashes/126944.rs
+++ b/tests/ui/traits/object/crash-due-to-projections-modulo-norm.rs
@@ -1,9 +1,12 @@
-//@ known-bug: rust-lang/rust#126944
+//@ check-pass
+
+// Regression test for #126944.
+
 // Step 1: Create two names for a single type: `Thing` and `AlsoThing`
 
 struct Thing;
 struct Dummy;
-pub trait DummyTrait {
+trait DummyTrait {
     type DummyType;
 }
 impl DummyTrait for Dummy {
@@ -13,7 +16,7 @@ type AlsoThing = <Dummy as DummyTrait>::DummyType;
 
 // Step 2: Create names for a single trait object type: `TraitObject` and `AlsoTraitObject`
 
-pub trait SomeTrait {
+trait SomeTrait {
     type Item;
 }
 type TraitObject = dyn SomeTrait<Item = AlsoThing>;
@@ -21,12 +24,12 @@ type AlsoTraitObject = dyn SomeTrait<Item = Thing>;
 
 // Step 3: Force the compiler to check whether the two names are the same type
 
-pub trait Supertrait {
+trait Supertrait {
     type Foo;
 }
-pub trait Subtrait: Supertrait<Foo = TraitObject> {}
+trait Subtrait: Supertrait<Foo = TraitObject> {}
 
-pub trait HasOutput<A: ?Sized> {
+trait HasOutput<A: ?Sized> {
     type Output;
 }
 
@@ -36,3 +39,5 @@ where
 {
     todo!()
 }
+
+fn main() {}
diff --git a/tests/ui/traits/object/incomplete-multiple-super-projection.rs b/tests/ui/traits/object/incomplete-multiple-super-projection.rs
new file mode 100644
index 00000000000..c7294eca4bd
--- /dev/null
+++ b/tests/ui/traits/object/incomplete-multiple-super-projection.rs
@@ -0,0 +1,32 @@
+// Regression test for #133361.
+
+trait Sup<T> {
+    type Assoc;
+}
+
+impl<T> Sup<T> for () {
+    type Assoc = T;
+}
+impl<T, U> Dyn<T, U> for () {}
+
+trait Dyn<A, B>: Sup<A, Assoc = A> + Sup<B, Assoc = B> {}
+
+trait Trait {
+    type Assoc;
+}
+impl Trait for dyn Dyn<(), ()> {
+    type Assoc = &'static str;
+}
+impl<A, B> Trait for dyn Dyn<A, B> {
+//~^ ERROR conflicting implementations of trait `Trait` for type `(dyn Dyn<(), ()> + 'static)`
+    type Assoc = usize;
+}
+
+fn call<A, B>(x: usize) -> <dyn Dyn<A, B> as Trait>::Assoc {
+    x
+}
+
+fn main() {
+    let x: &'static str = call::<(), ()>(0xDEADBEEF);
+    println!("{x}");
+}
diff --git a/tests/ui/traits/object/incomplete-multiple-super-projection.stderr b/tests/ui/traits/object/incomplete-multiple-super-projection.stderr
new file mode 100644
index 00000000000..b4271f70ed0
--- /dev/null
+++ b/tests/ui/traits/object/incomplete-multiple-super-projection.stderr
@@ -0,0 +1,12 @@
+error[E0119]: conflicting implementations of trait `Trait` for type `(dyn Dyn<(), ()> + 'static)`
+  --> $DIR/incomplete-multiple-super-projection.rs:20:1
+   |
+LL | impl Trait for dyn Dyn<(), ()> {
+   | ------------------------------ first implementation here
+...
+LL | impl<A, B> Trait for dyn Dyn<A, B> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Dyn<(), ()> + 'static)`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/crashes/79590.rs b/tests/ui/traits/object/infer-shadows-implied-projection.rs
index b73864cce23..628912c54fa 100644
--- a/tests/crashes/79590.rs
+++ b/tests/ui/traits/object/infer-shadows-implied-projection.rs
@@ -1,4 +1,4 @@
-//@ known-bug: #79590
+//@ check-pass
 
 trait Database: Restriction<Inner = u32> {}
 
diff --git a/tests/ui/traits/object/outlives-super-proj.rs b/tests/ui/traits/object/outlives-super-proj.rs
new file mode 100644
index 00000000000..15b67d9ab68
--- /dev/null
+++ b/tests/ui/traits/object/outlives-super-proj.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+
+// Make sure that we still deduce outlives bounds from supertrait projections
+// and require them for well-formedness.
+
+trait Trait {
+    type Assoc;
+}
+
+trait Bar {
+    type Assoc;
+}
+
+trait Foo<'a, T: 'a>: Bar<Assoc = &'a T> {
+
+}
+
+fn outlives<'a, T: 'a>() {}
+
+fn implied_outlives<'a, T: Trait>(x: &dyn Foo<'a, T::Assoc>) {
+    outlives::<'a, T::Assoc>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr
index 2f9fdf151f0..37fe142951d 100644
--- a/tests/ui/traits/object/pretty.stderr
+++ b/tests/ui/traits/object/pretty.stderr
@@ -154,12 +154,12 @@ error[E0308]: mismatched types
   --> $DIR/pretty.rs:41:56
    |
 LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x }
-   |                                                     -  ^ expected `()`, found `&dyn HasGat<u8, Assoc<bool> = ()>`
+   |                                                     -  ^ expected `()`, found `&dyn HasGat<u8>`
    |                                                     |
-   |                                                     help: try adding a return type: `-> &dyn HasGat<u8, Assoc<bool> = ()>`
+   |                                                     help: try adding a return type: `-> &dyn HasGat<u8>`
    |
    = note: expected unit type `()`
-              found reference `&dyn HasGat<u8, Assoc<bool> = ()>`
+              found reference `&dyn HasGat<u8>`
 
 error: aborting due to 14 previous errors; 1 warning emitted
 
diff --git a/tests/ui/traits/object/redundant.rs b/tests/ui/traits/object/redundant.rs
new file mode 100644
index 00000000000..be07b157138
--- /dev/null
+++ b/tests/ui/traits/object/redundant.rs
@@ -0,0 +1,12 @@
+//@ check-pass
+
+trait Foo: Bar<Out = ()> {}
+trait Bar {
+    type Out;
+}
+
+fn w(x: &dyn Foo<Out = ()>) {
+    let x: &dyn Foo = x;
+}
+
+fn main() {}
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index 45422be946e..6df05747f32 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -20,9 +20,6 @@ LL | fn option_to_result() -> Result<u64, String> {
    | -------------------------------------------- this function returns a `Result`
 LL |     Some(3)?;
    |            ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
-   = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
 
 error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:15:31
@@ -31,9 +28,6 @@ LL | fn control_flow_to_result() -> Result<u64, String> {
    | -------------------------------------------------- this function returns a `Result`
 LL |     Ok(ControlFlow::Break(123)?)
    |                               ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
-   |
-   = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
-   = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
 
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:20:22
@@ -42,9 +36,6 @@ LL | fn result_to_option() -> Option<u16> {
    | ------------------------------------ this function returns an `Option`
 LL |     Some(Err("hello")?)
    |                      ^ use `.ok()?` if you want to discard the `Result<Infallible, &str>` error information
-   |
-   = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
-   = help: the trait `FromResidual<Option<Infallible>>` is implemented for `Option<T>`
 
 error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
   --> $DIR/bad-interconversion.rs:25:33
@@ -53,9 +44,6 @@ LL | fn control_flow_to_option() -> Option<u64> {
    | ------------------------------------------ this function returns an `Option`
 LL |     Some(ControlFlow::Break(123)?)
    |                                 ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
-   |
-   = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
-   = help: the trait `FromResidual<Option<Infallible>>` is implemented for `Option<T>`
 
 error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
   --> $DIR/bad-interconversion.rs:30:39
diff --git a/tests/ui/try-trait/bad-question-mark-on-trait-object.rs b/tests/ui/try-trait/bad-question-mark-on-trait-object.rs
new file mode 100644
index 00000000000..2a0d14b1750
--- /dev/null
+++ b/tests/ui/try-trait/bad-question-mark-on-trait-object.rs
@@ -0,0 +1,29 @@
+struct E;
+//~^ NOTE `E` needs to implement `std::error::Error`
+//~| NOTE alternatively, `E` needs to implement `Into<X>`
+struct X; //~ NOTE `X` needs to implement `From<E>`
+
+fn foo() -> Result<(), Box<dyn std::error::Error>> { //~ NOTE required `E: std::error::Error` because of this
+    Ok(bar()?)
+    //~^ ERROR `?` couldn't convert the error: `E: std::error::Error` is not satisfied
+    //~| NOTE the trait `std::error::Error` is not implemented for `E`
+    //~| NOTE the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
+    //~| NOTE required for `Box<dyn std::error::Error>` to implement `From<E>`
+    //~| NOTE this has type `Result<_, E>`
+    //~| NOTE in this expansion
+    //~| NOTE in this expansion
+    //~| NOTE in this expansion
+}
+fn bat() -> Result<(), X> { //~ NOTE expected `X` because of this
+    Ok(bar()?)
+    //~^ ERROR `?` couldn't convert the error to `X`
+    //~| NOTE the trait `From<E>` is not implemented for `X`
+    //~| NOTE this can't be annotated with `?` because it has type `Result<_, E>`
+    //~| NOTE the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
+    //~| NOTE in this expansion
+    //~| NOTE in this expansion
+}
+fn bar() -> Result<(), E> {
+    Err(E)
+}
+fn main() {}
diff --git a/tests/ui/try-trait/bad-question-mark-on-trait-object.stderr b/tests/ui/try-trait/bad-question-mark-on-trait-object.stderr
new file mode 100644
index 00000000000..dd380850c9e
--- /dev/null
+++ b/tests/ui/try-trait/bad-question-mark-on-trait-object.stderr
@@ -0,0 +1,43 @@
+error[E0277]: `?` couldn't convert the error: `E: std::error::Error` is not satisfied
+  --> $DIR/bad-question-mark-on-trait-object.rs:7:13
+   |
+LL | fn foo() -> Result<(), Box<dyn std::error::Error>> {
+   |             -------------------------------------- required `E: std::error::Error` because of this
+LL |     Ok(bar()?)
+   |        -----^ the trait `std::error::Error` is not implemented for `E`
+   |        |
+   |        this has type `Result<_, E>`
+   |
+note: `E` needs to implement `std::error::Error`
+  --> $DIR/bad-question-mark-on-trait-object.rs:1:1
+   |
+LL | struct E;
+   | ^^^^^^^^
+   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
+   = note: required for `Box<dyn std::error::Error>` to implement `From<E>`
+
+error[E0277]: `?` couldn't convert the error to `X`
+  --> $DIR/bad-question-mark-on-trait-object.rs:18:13
+   |
+LL | fn bat() -> Result<(), X> {
+   |             ------------- expected `X` because of this
+LL |     Ok(bar()?)
+   |        -----^ the trait `From<E>` is not implemented for `X`
+   |        |
+   |        this can't be annotated with `?` because it has type `Result<_, E>`
+   |
+note: `X` needs to implement `From<E>`
+  --> $DIR/bad-question-mark-on-trait-object.rs:4:1
+   |
+LL | struct X;
+   | ^^^^^^^^
+note: alternatively, `E` needs to implement `Into<X>`
+  --> $DIR/bad-question-mark-on-trait-object.rs:1:1
+   |
+LL | struct E;
+   | ^^^^^^^^
+   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/try-trait/option-to-result.stderr b/tests/ui/try-trait/option-to-result.stderr
index 1a5a925f92f..8a4c4707942 100644
--- a/tests/ui/try-trait/option-to-result.stderr
+++ b/tests/ui/try-trait/option-to-result.stderr
@@ -6,9 +6,6 @@ LL | fn test_result() -> Result<(),()> {
 LL |     let a:Option<()> = Some(());
 LL |     a?;
    |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
-   = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
 
 error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
   --> $DIR/option-to-result.rs:11:6
@@ -18,9 +15,6 @@ LL | fn test_option() -> Option<i32>{
 LL |     let a:Result<i32, i32> = Ok(5);
 LL |     a?;
    |      ^ use `.ok()?` if you want to discard the `Result<Infallible, i32>` error information
-   |
-   = help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
-   = help: the trait `FromResidual<Option<Infallible>>` is implemented for `Option<T>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/try-trait/try-on-option-diagnostics.stderr b/tests/ui/try-trait/try-on-option-diagnostics.stderr
index 9ee540c79fd..08675e242a3 100644
--- a/tests/ui/try-trait/try-on-option-diagnostics.stderr
+++ b/tests/ui/try-trait/try-on-option-diagnostics.stderr
@@ -6,8 +6,6 @@ LL | fn a_function() -> u32 {
 LL |     let x: Option<u32> = None;
 LL |     x?;
    |      ^ cannot use the `?` operator in a function that returns `u32`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
 
 error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:14:10
@@ -17,8 +15,6 @@ LL |     let a_closure = || {
 LL |         let x: Option<u32> = None;
 LL |         x?;
    |          ^ cannot use the `?` operator in a closure that returns `{integer}`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
 
 error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:26:14
@@ -28,8 +24,6 @@ LL |         fn a_method() {
 LL |             let x: Option<u32> = None;
 LL |             x?;
    |              ^ cannot use the `?` operator in a method that returns `()`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
 
 error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option-diagnostics.rs:39:14
@@ -39,8 +33,6 @@ LL |         fn a_trait_method() {
 LL |             let x: Option<u32> = None;
 LL |             x?;
    |              ^ cannot use the `?` operator in a trait method that returns `()`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/try-trait/try-on-option.stderr b/tests/ui/try-trait/try-on-option.stderr
index 15d0b28ddc1..aeb519086d8 100644
--- a/tests/ui/try-trait/try-on-option.stderr
+++ b/tests/ui/try-trait/try-on-option.stderr
@@ -6,9 +6,6 @@ LL | fn foo() -> Result<u32, ()> {
 LL |     let x: Option<u32> = None;
 LL |     x?;
    |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
-   = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
   --> $DIR/try-on-option.rs:11:6
@@ -18,8 +15,6 @@ LL | fn bar() -> u32 {
 LL |     let x: Option<u32> = None;
 LL |     x?;
    |      ^ cannot use the `?` operator in a function that returns `u32`
-   |
-   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/try-trait/try-operator-on-main.stderr b/tests/ui/try-trait/try-operator-on-main.stderr
index 311e8076ed4..9c2526442ab 100644
--- a/tests/ui/try-trait/try-operator-on-main.stderr
+++ b/tests/ui/try-trait/try-operator-on-main.stderr
@@ -7,7 +7,6 @@ LL |     // error for a `Try` type on a non-`Try` fn
 LL |     std::fs::File::open("foo")?;
    |                               ^ cannot use the `?` operator in a function that returns `()`
    |
-   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
 help: consider adding return type
    |
 LL ~ fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -33,8 +32,6 @@ LL | fn main() {
 ...
 LL |     ()?;
    |       ^ cannot use the `?` operator in a function that returns `()`
-   |
-   = help: the trait `FromResidual<_>` is not implemented for `()`
 
 error[E0277]: the trait bound `(): Try` is not satisfied
   --> $DIR/try-operator-on-main.rs:14:25