about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs74
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/inspect/build.rs88
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/search_graph.rs22
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs12
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs28
-rw-r--r--compiler/rustc_type_ir/src/solve/inspect.rs12
-rw-r--r--library/core/src/cell.rs98
-rw-r--r--library/coretests/tests/cell.rs72
-rw-r--r--library/coretests/tests/lib.rs3
-rw-r--r--tests/ui/coroutine/auto-trait-regions.rs12
-rw-r--r--tests/ui/coroutine/auto-trait-regions.stderr24
-rw-r--r--tests/ui/coroutine/clone-impl-static.rs6
-rw-r--r--tests/ui/coroutine/clone-impl-static.stderr8
-rw-r--r--tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr (renamed from tests/ui/did_you_mean/bad-assoc-ty.stderr)60
-rw-r--r--tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr340
-rw-r--r--tests/ui/did_you_mean/bad-assoc-ty.rs11
-rw-r--r--tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2015.stderr (renamed from tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr)8
-rw-r--r--tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2021.stderr65
-rw-r--r--tests/ui/feature-gates/feature-gate-unsized_fn_params.rs7
-rw-r--r--tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2015.stderr (renamed from tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr)2
-rw-r--r--tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2024.stderr10
-rw-r--r--tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs6
-rw-r--r--tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2015.stderr (renamed from tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr)2
-rw-r--r--tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2024.stderr17
-rw-r--r--tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs6
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2015.stderr (renamed from tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr)42
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2021.stderr308
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs13
-rw-r--r--tests/ui/impl-trait/hidden-lifetimes.edition2015.stderr (renamed from tests/ui/impl-trait/hidden-lifetimes.stderr)4
-rw-r--r--tests/ui/impl-trait/hidden-lifetimes.edition2024.stderr26
-rw-r--r--tests/ui/impl-trait/hidden-lifetimes.rs12
-rw-r--r--tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2015.stderr (renamed from tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr)2
-rw-r--r--tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2024.stderr15
-rw-r--r--tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs7
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr (renamed from tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr)2
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr11
-rw-r--r--tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs3
-rw-r--r--tests/ui/impl-trait/issues/issue-54895.edition2015.stderr (renamed from tests/ui/impl-trait/issues/issue-54895.stderr)4
-rw-r--r--tests/ui/impl-trait/issues/issue-54895.edition2024.stderr27
-rw-r--r--tests/ui/impl-trait/issues/issue-54895.rs4
-rw-r--r--tests/ui/impl-trait/issues/issue-79099.edition2015.stderr (renamed from tests/ui/impl-trait/issues/issue-79099.stderr)4
-rw-r--r--tests/ui/impl-trait/issues/issue-79099.edition2024.stderr14
-rw-r--r--tests/ui/impl-trait/issues/issue-79099.rs5
-rw-r--r--tests/ui/impl-trait/precise-capturing/dyn-use.edition2015.stderr (renamed from tests/ui/impl-trait/precise-capturing/dyn-use.stderr)2
-rw-r--r--tests/ui/impl-trait/precise-capturing/dyn-use.edition2024.stderr26
-rw-r--r--tests/ui/impl-trait/precise-capturing/dyn-use.rs10
-rw-r--r--tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2015.stderr (renamed from tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr)16
-rw-r--r--tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2024.stderr51
-rw-r--r--tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs15
-rw-r--r--tests/ui/imports/import-from-missing-star-2.edition2015.stderr (renamed from tests/ui/imports/import-from-missing-star-2.stderr)2
-rw-r--r--tests/ui/imports/import-from-missing-star-2.edition2024.stderr11
-rw-r--r--tests/ui/imports/import-from-missing-star-2.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2015.stderr (renamed from tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr)2
-rw-r--r--tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2024.stderr91
-rw-r--r--tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs13
55 files changed, 1412 insertions, 328 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 780feb9b827..dd9ccadf6cf 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -3,7 +3,7 @@ use std::ops::ControlFlow;
 
 #[cfg(feature = "nightly")]
 use rustc_macros::HashStable_NoContext;
-use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack};
+use rustc_type_ir::data_structures::{HashMap, HashSet};
 use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::relate::Relate;
@@ -336,13 +336,12 @@ where
 
     /// Creates a nested evaluation context that shares the same search graph as the
     /// one passed in. This is suitable for evaluation, granted that the search graph
-    /// has had the nested goal recorded on its stack ([`SearchGraph::with_new_goal`]),
-    /// but it's preferable to use other methods that call this one rather than this
-    /// method directly.
+    /// has had the nested goal recorded on its stack. This method only be used by
+    /// `search_graph::Delegate::compute_goal`.
     ///
     /// This function takes care of setting up the inference context, setting the anchor,
     /// and registering opaques from the canonicalized input.
-    fn enter_canonical<R>(
+    pub(super) fn enter_canonical<R>(
         cx: I,
         search_graph: &'a mut SearchGraph<D>,
         canonical_input: CanonicalInput<I>,
@@ -398,56 +397,6 @@ where
         result
     }
 
-    /// The entry point of the solver.
-    ///
-    /// This function deals with (coinductive) cycles, overflow, and caching
-    /// and then calls [`EvalCtxt::compute_goal`] which contains the actual
-    /// logic of the solver.
-    ///
-    /// Instead of calling this function directly, use either [EvalCtxt::evaluate_goal]
-    /// if you're inside of the solver or [SolverDelegateEvalExt::evaluate_root_goal] if you're
-    /// outside of it.
-    #[instrument(level = "debug", skip(cx, search_graph, goal_evaluation), ret)]
-    fn evaluate_canonical_goal(
-        cx: I,
-        search_graph: &'a mut SearchGraph<D>,
-        canonical_input: CanonicalInput<I>,
-        step_kind_from_parent: PathKind,
-        goal_evaluation: &mut ProofTreeBuilder<D>,
-    ) -> QueryResult<I> {
-        let mut canonical_goal_evaluation =
-            goal_evaluation.new_canonical_goal_evaluation(canonical_input);
-
-        // Deal with overflow, caching, and coinduction.
-        //
-        // The actual solver logic happens in `ecx.compute_goal`.
-        let result = ensure_sufficient_stack(|| {
-            search_graph.with_new_goal(
-                cx,
-                canonical_input,
-                step_kind_from_parent,
-                &mut canonical_goal_evaluation,
-                |search_graph, cx, canonical_input, canonical_goal_evaluation| {
-                    EvalCtxt::enter_canonical(
-                        cx,
-                        search_graph,
-                        canonical_input,
-                        canonical_goal_evaluation,
-                        |ecx, goal| {
-                            let result = ecx.compute_goal(goal);
-                            ecx.inspect.query_result(result);
-                            result
-                        },
-                    )
-                },
-            )
-        });
-
-        canonical_goal_evaluation.query_result(result);
-        goal_evaluation.canonical_goal_evaluation(canonical_goal_evaluation);
-        result
-    }
-
     /// Recursively evaluates `goal`, returning whether any inference vars have
     /// been constrained and the certainty of the result.
     fn evaluate_goal(
@@ -501,18 +450,16 @@ where
         let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
         let mut goal_evaluation =
             self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
-        let canonical_response = EvalCtxt::evaluate_canonical_goal(
+        let canonical_result = self.search_graph.evaluate_goal(
             self.cx(),
-            self.search_graph,
             canonical_goal,
             self.step_kind_for_source(source),
             &mut goal_evaluation,
         );
-        let response = match canonical_response {
-            Err(e) => {
-                self.inspect.goal_evaluation(goal_evaluation);
-                return Err(e);
-            }
+        goal_evaluation.query_result(canonical_result);
+        self.inspect.goal_evaluation(goal_evaluation);
+        let response = match canonical_result {
+            Err(e) => return Err(e),
             Ok(response) => response,
         };
 
@@ -521,7 +468,6 @@ where
 
         let (normalization_nested_goals, certainty) =
             self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response);
-        self.inspect.goal_evaluation(goal_evaluation);
 
         // FIXME: We previously had an assert here that checked that recomputing
         // a goal after applying its constraints did not change its response.
@@ -582,7 +528,7 @@ where
         Ok((normalization_nested_goals, GoalEvaluation { certainty, has_changed, stalled_on }))
     }
 
-    fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
+    pub(super) fn compute_goal(&mut self, goal: Goal<I, I::Predicate>) -> QueryResult<I> {
         let Goal { param_env, predicate } = goal;
         let kind = predicate.kind();
         if let Some(kind) = kind.no_bound_vars() {
diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
index f22b275bc44..c8521624ebb 100644
--- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
@@ -13,8 +13,7 @@ use rustc_type_ir::{self as ty, Interner};
 use crate::delegate::SolverDelegate;
 use crate::solve::eval_ctxt::canonical;
 use crate::solve::{
-    CanonicalInput, Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource,
-    QueryResult, inspect,
+    Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource, QueryResult, inspect,
 };
 
 /// The core data structure when building proof trees.
@@ -54,7 +53,6 @@ where
 enum DebugSolver<I: Interner> {
     Root,
     GoalEvaluation(WipGoalEvaluation<I>),
-    CanonicalGoalEvaluation(WipCanonicalGoalEvaluation<I>),
     CanonicalGoalEvaluationStep(WipCanonicalGoalEvaluationStep<I>),
 }
 
@@ -64,12 +62,6 @@ impl<I: Interner> From<WipGoalEvaluation<I>> for DebugSolver<I> {
     }
 }
 
-impl<I: Interner> From<WipCanonicalGoalEvaluation<I>> for DebugSolver<I> {
-    fn from(g: WipCanonicalGoalEvaluation<I>) -> DebugSolver<I> {
-        DebugSolver::CanonicalGoalEvaluation(g)
-    }
-}
-
 impl<I: Interner> From<WipCanonicalGoalEvaluationStep<I>> for DebugSolver<I> {
     fn from(g: WipCanonicalGoalEvaluationStep<I>) -> DebugSolver<I> {
         DebugSolver::CanonicalGoalEvaluationStep(g)
@@ -80,7 +72,10 @@ impl<I: Interner> From<WipCanonicalGoalEvaluationStep<I>> for DebugSolver<I> {
 struct WipGoalEvaluation<I: Interner> {
     pub uncanonicalized_goal: Goal<I, I::Predicate>,
     pub orig_values: Vec<I::GenericArg>,
-    pub evaluation: Option<WipCanonicalGoalEvaluation<I>>,
+    pub encountered_overflow: bool,
+    /// After we finished evaluating this is moved into `kind`.
+    pub final_revision: Option<WipCanonicalGoalEvaluationStep<I>>,
+    pub result: Option<QueryResult<I>>,
 }
 
 impl<I: Interner> WipGoalEvaluation<I> {
@@ -88,31 +83,12 @@ impl<I: Interner> WipGoalEvaluation<I> {
         inspect::GoalEvaluation {
             uncanonicalized_goal: self.uncanonicalized_goal,
             orig_values: self.orig_values,
-            evaluation: self.evaluation.unwrap().finalize(),
-        }
-    }
-}
-
-#[derive_where(PartialEq, Eq, Debug; I: Interner)]
-struct WipCanonicalGoalEvaluation<I: Interner> {
-    goal: CanonicalInput<I>,
-    encountered_overflow: bool,
-    /// Only used for uncached goals. After we finished evaluating
-    /// the goal, this is interned and moved into `kind`.
-    final_revision: Option<WipCanonicalGoalEvaluationStep<I>>,
-    result: Option<QueryResult<I>>,
-}
-
-impl<I: Interner> WipCanonicalGoalEvaluation<I> {
-    fn finalize(self) -> inspect::CanonicalGoalEvaluation<I> {
-        inspect::CanonicalGoalEvaluation {
-            goal: self.goal,
             kind: if self.encountered_overflow {
                 assert!(self.final_revision.is_none());
-                inspect::CanonicalGoalEvaluationKind::Overflow
+                inspect::GoalEvaluationKind::Overflow
             } else {
                 let final_revision = self.final_revision.unwrap().finalize();
-                inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision }
+                inspect::GoalEvaluationKind::Evaluation { final_revision }
             },
             result: self.result.unwrap(),
         }
@@ -256,55 +232,27 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
 
     pub(in crate::solve) fn new_goal_evaluation(
         &mut self,
-        goal: Goal<I, I::Predicate>,
+        uncanonicalized_goal: Goal<I, I::Predicate>,
         orig_values: &[I::GenericArg],
         kind: GoalEvaluationKind,
     ) -> ProofTreeBuilder<D> {
         self.opt_nested(|| match kind {
             GoalEvaluationKind::Root => Some(WipGoalEvaluation {
-                uncanonicalized_goal: goal,
+                uncanonicalized_goal,
                 orig_values: orig_values.to_vec(),
-                evaluation: None,
+                encountered_overflow: false,
+                final_revision: None,
+                result: None,
             }),
             GoalEvaluationKind::Nested => None,
         })
     }
 
-    pub(crate) fn new_canonical_goal_evaluation(
-        &mut self,
-        goal: CanonicalInput<I>,
-    ) -> ProofTreeBuilder<D> {
-        self.nested(|| WipCanonicalGoalEvaluation {
-            goal,
-            encountered_overflow: false,
-            final_revision: None,
-            result: None,
-        })
-    }
-
-    pub(crate) fn canonical_goal_evaluation(
-        &mut self,
-        canonical_goal_evaluation: ProofTreeBuilder<D>,
-    ) {
-        if let Some(this) = self.as_mut() {
-            match (this, *canonical_goal_evaluation.state.unwrap()) {
-                (
-                    DebugSolver::GoalEvaluation(goal_evaluation),
-                    DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation),
-                ) => {
-                    let prev = goal_evaluation.evaluation.replace(canonical_goal_evaluation);
-                    assert_eq!(prev, None);
-                }
-                _ => unreachable!(),
-            }
-        }
-    }
-
     pub(crate) fn canonical_goal_evaluation_overflow(&mut self) {
         if let Some(this) = self.as_mut() {
             match this {
-                DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
-                    canonical_goal_evaluation.encountered_overflow = true;
+                DebugSolver::GoalEvaluation(goal_evaluation) => {
+                    goal_evaluation.encountered_overflow = true;
                 }
                 _ => unreachable!(),
             };
@@ -343,10 +291,10 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         if let Some(this) = self.as_mut() {
             match (this, *goal_evaluation_step.state.unwrap()) {
                 (
-                    DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations),
+                    DebugSolver::GoalEvaluation(goal_evaluation),
                     DebugSolver::CanonicalGoalEvaluationStep(goal_evaluation_step),
                 ) => {
-                    canonical_goal_evaluations.final_revision = Some(goal_evaluation_step);
+                    goal_evaluation.final_revision = Some(goal_evaluation_step);
                 }
                 _ => unreachable!(),
             }
@@ -489,8 +437,8 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
     pub(crate) fn query_result(&mut self, result: QueryResult<I>) {
         if let Some(this) = self.as_mut() {
             match this {
-                DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => {
-                    assert_eq!(canonical_goal_evaluation.result.replace(result), None);
+                DebugSolver::GoalEvaluation(goal_evaluation) => {
+                    assert_eq!(goal_evaluation.result.replace(result), None);
                 }
                 DebugSolver::CanonicalGoalEvaluationStep(evaluation_step) => {
                     assert_eq!(
diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
index ecffbbff7a2..12cbc7e8f91 100644
--- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
@@ -1,13 +1,14 @@
 use std::convert::Infallible;
 use std::marker::PhantomData;
 
+use rustc_type_ir::data_structures::ensure_sufficient_stack;
 use rustc_type_ir::search_graph::{self, PathKind};
 use rustc_type_ir::solve::{CanonicalInput, Certainty, NoSolution, QueryResult};
 use rustc_type_ir::{Interner, TypingMode};
 
-use super::inspect::ProofTreeBuilder;
-use super::{FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints};
 use crate::delegate::SolverDelegate;
+use crate::solve::inspect::ProofTreeBuilder;
+use crate::solve::{EvalCtxt, FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints};
 
 /// This type is never constructed. We only use it to implement `search_graph::Delegate`
 /// for all types which impl `SolverDelegate` and doing it directly fails in coherence.
@@ -80,8 +81,8 @@ where
 
     fn on_stack_overflow(
         cx: I,
-        inspect: &mut ProofTreeBuilder<D>,
         input: CanonicalInput<I>,
+        inspect: &mut ProofTreeBuilder<D>,
     ) -> QueryResult<I> {
         inspect.canonical_goal_evaluation_overflow();
         response_no_constraints(cx, input, Certainty::overflow(true))
@@ -106,6 +107,21 @@ where
         let certainty = from_result.unwrap().value.certainty;
         response_no_constraints(cx, for_input, certainty)
     }
+
+    fn compute_goal(
+        search_graph: &mut SearchGraph<D>,
+        cx: I,
+        input: CanonicalInput<I>,
+        inspect: &mut Self::ProofTreeBuilder,
+    ) -> QueryResult<I> {
+        ensure_sufficient_stack(|| {
+            EvalCtxt::enter_canonical(cx, search_graph, input, inspect, |ecx, goal| {
+                let result = ecx.compute_goal(goal);
+                ecx.inspect.query_result(result);
+                result
+            })
+        })
+    }
 }
 
 fn response_no_constraints<I: Interner>(
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 80df0fab2d8..308486811e6 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -37,7 +37,7 @@ pub struct InspectGoal<'a, 'tcx> {
     orig_values: Vec<ty::GenericArg<'tcx>>,
     goal: Goal<'tcx, ty::Predicate<'tcx>>,
     result: Result<Certainty, NoSolution>,
-    evaluation_kind: inspect::CanonicalGoalEvaluationKind<TyCtxt<'tcx>>,
+    evaluation_kind: inspect::GoalEvaluationKind<TyCtxt<'tcx>>,
     normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
     source: GoalSource,
 }
@@ -393,8 +393,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         let mut candidates = vec![];
         let last_eval_step = match &self.evaluation_kind {
             // An annoying edge case in case the recursion limit is 0.
-            inspect::CanonicalGoalEvaluationKind::Overflow => return vec![],
-            inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } => final_revision,
+            inspect::GoalEvaluationKind::Overflow => return vec![],
+            inspect::GoalEvaluationKind::Evaluation { final_revision } => final_revision,
         };
 
         let mut nested_goals = vec![];
@@ -426,10 +426,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
     ) -> Self {
         let infcx = <&SolverDelegate<'tcx>>::from(infcx);
 
-        let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, evaluation } = root;
+        let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, kind, result } = root;
         // If there's a normalizes-to goal, AND the evaluation result with the result of
         // constraining the normalizes-to RHS and computing the nested goals.
-        let result = evaluation.result.and_then(|ok| {
+        let result = result.and_then(|ok| {
             let nested_goals_certainty =
                 term_hack_and_nested_certainty.map_or(Ok(Certainty::Yes), |(_, c)| c)?;
             Ok(ok.value.certainty.and(nested_goals_certainty))
@@ -441,7 +441,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
             orig_values,
             goal: eager_resolve_vars(infcx, uncanonicalized_goal),
             result,
-            evaluation_kind: evaluation.kind,
+            evaluation_kind: kind,
             normalizes_to_term_hack: term_hack_and_nested_certainty.map(|(n, _)| n),
             source,
         }
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index a857da2fcd5..8941360d2d0 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -21,7 +21,7 @@ use std::marker::PhantomData;
 use derive_where::derive_where;
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
-use tracing::debug;
+use tracing::{debug, instrument};
 
 use crate::data_structures::HashMap;
 
@@ -56,7 +56,7 @@ pub trait Cx: Copy {
     fn evaluation_is_concurrent(&self) -> bool;
 }
 
-pub trait Delegate {
+pub trait Delegate: Sized {
     type Cx: Cx;
     /// Whether to use the provisional cache. Set to `false` by a fuzzer when
     /// validating the search graph.
@@ -94,8 +94,8 @@ pub trait Delegate {
     ) -> bool;
     fn on_stack_overflow(
         cx: Self::Cx,
-        inspect: &mut Self::ProofTreeBuilder,
         input: <Self::Cx as Cx>::Input,
+        inspect: &mut Self::ProofTreeBuilder,
     ) -> <Self::Cx as Cx>::Result;
     fn on_fixpoint_overflow(
         cx: Self::Cx,
@@ -108,6 +108,13 @@ pub trait Delegate {
         for_input: <Self::Cx as Cx>::Input,
         from_result: <Self::Cx as Cx>::Result,
     ) -> <Self::Cx as Cx>::Result;
+
+    fn compute_goal(
+        search_graph: &mut SearchGraph<Self>,
+        cx: Self::Cx,
+        input: <Self::Cx as Cx>::Input,
+        inspect: &mut Self::ProofTreeBuilder,
+    ) -> <Self::Cx as Cx>::Result;
 }
 
 /// In the initial iteration of a cycle, we do not yet have a provisional
@@ -589,15 +596,15 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
 
     /// Probably the most involved method of the whole solver.
     ///
-    /// Given some goal which is proven via the `prove_goal` closure, this
-    /// handles caching, overflow, and coinductive cycles.
-    pub fn with_new_goal(
+    /// While goals get computed via `D::compute_goal`, this function handles
+    /// caching, overflow, and cycles.
+    #[instrument(level = "debug", skip(self, cx, inspect), ret)]
+    pub fn evaluate_goal(
         &mut self,
         cx: X,
         input: X::Input,
         step_kind_from_parent: PathKind,
         inspect: &mut D::ProofTreeBuilder,
-        evaluate_goal: impl Fn(&mut Self, X, X::Input, &mut D::ProofTreeBuilder) -> X::Result + Copy,
     ) -> X::Result {
         let Some(available_depth) =
             AvailableDepth::allowed_depth_for_nested::<D>(self.root_depth, &self.stack)
@@ -666,7 +673,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         // must not be added to the global cache. Notably, this is the case for
         // trait solver cycles participants.
         let (evaluation_result, dep_node) =
-            cx.with_cached_task(|| self.evaluate_goal_in_task(cx, input, inspect, evaluate_goal));
+            cx.with_cached_task(|| self.evaluate_goal_in_task(cx, input, inspect));
 
         // We've finished computing the goal and have popped it from the stack,
         // lazily update its parent goal.
@@ -736,7 +743,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         }
 
         debug!("encountered stack overflow");
-        D::on_stack_overflow(cx, inspect, input)
+        D::on_stack_overflow(cx, input, inspect)
     }
 
     /// When reevaluating a goal with a changed provisional result, all provisional cache entry
@@ -1064,7 +1071,6 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         cx: X,
         input: X::Input,
         inspect: &mut D::ProofTreeBuilder,
-        evaluate_goal: impl Fn(&mut Self, X, X::Input, &mut D::ProofTreeBuilder) -> X::Result + Copy,
     ) -> EvaluationResult<X> {
         // We reset `encountered_overflow` each time we rerun this goal
         // but need to make sure we currently propagate it to the global
@@ -1073,7 +1079,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         let mut encountered_overflow = false;
         let mut i = 0;
         loop {
-            let result = evaluate_goal(self, cx, input, inspect);
+            let result = D::compute_goal(self, cx, input, inspect);
             let stack_entry = self.stack.pop();
             encountered_overflow |= stack_entry.encountered_overflow;
             debug_assert_eq!(stack_entry.input, input);
diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs
index b10641b287d..089695d0475 100644
--- a/compiler/rustc_type_ir/src/solve/inspect.rs
+++ b/compiler/rustc_type_ir/src/solve/inspect.rs
@@ -23,7 +23,7 @@ use std::hash::Hash;
 use derive_where::derive_where;
 use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 
-use crate::solve::{CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, QueryResult};
+use crate::solve::{CandidateSource, Certainty, Goal, GoalSource, QueryResult};
 use crate::{Canonical, CanonicalVarValues, Interner};
 
 /// Some `data` together with information about how they relate to the input
@@ -54,18 +54,12 @@ pub type CanonicalState<I, T> = Canonical<I, State<I, T>>;
 pub struct GoalEvaluation<I: Interner> {
     pub uncanonicalized_goal: Goal<I, I::Predicate>,
     pub orig_values: Vec<I::GenericArg>,
-    pub evaluation: CanonicalGoalEvaluation<I>,
-}
-
-#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
-pub struct CanonicalGoalEvaluation<I: Interner> {
-    pub goal: CanonicalInput<I>,
-    pub kind: CanonicalGoalEvaluationKind<I>,
+    pub kind: GoalEvaluationKind<I>,
     pub result: QueryResult<I>,
 }
 
 #[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)]
-pub enum CanonicalGoalEvaluationKind<I: Interner> {
+pub enum GoalEvaluationKind<I: Interner> {
     Overflow,
     Evaluation {
         /// This is always `ProbeKind::Root`.
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index a2c1ba835f3..7ce03e3d831 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -255,6 +255,7 @@ use crate::fmt::{self, Debug, Display};
 use crate::marker::{PhantomData, PointerLike, Unsize};
 use crate::mem;
 use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
+use crate::panic::const_panic;
 use crate::pin::PinCoerceUnsized;
 use crate::ptr::{self, NonNull};
 
@@ -781,16 +782,24 @@ impl Display for BorrowMutError {
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[track_caller]
 #[cold]
-fn panic_already_borrowed(err: BorrowMutError) -> ! {
-    panic!("{err}")
+const fn panic_already_borrowed(err: BorrowMutError) -> ! {
+    const_panic!(
+        "RefCell already borrowed",
+        "{err}",
+        err: BorrowMutError = err,
+    )
 }
 
 // This ensures the panicking code is outlined from `borrow` for `RefCell`.
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[track_caller]
 #[cold]
-fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
-    panic!("{err}")
+const fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
+    const_panic!(
+        "RefCell already mutably borrowed",
+        "{err}",
+        err: BorrowError = err,
+    )
 }
 
 // Positive values represent the number of `Ref` active. Negative values
@@ -810,12 +819,12 @@ type BorrowCounter = isize;
 const UNUSED: BorrowCounter = 0;
 
 #[inline(always)]
-fn is_writing(x: BorrowCounter) -> bool {
+const fn is_writing(x: BorrowCounter) -> bool {
     x < UNUSED
 }
 
 #[inline(always)]
-fn is_reading(x: BorrowCounter) -> bool {
+const fn is_reading(x: BorrowCounter) -> bool {
     x > UNUSED
 }
 
@@ -884,8 +893,9 @@ impl<T> RefCell<T> {
     #[stable(feature = "refcell_replace", since = "1.24.0")]
     #[track_caller]
     #[rustc_confusables("swap")]
-    pub fn replace(&self, t: T) -> T {
-        mem::replace(&mut *self.borrow_mut(), t)
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn replace(&self, t: T) -> T {
+        mem::replace(&mut self.borrow_mut(), t)
     }
 
     /// Replaces the wrapped value with a new one computed from `f`, returning
@@ -935,7 +945,8 @@ impl<T> RefCell<T> {
     /// ```
     #[inline]
     #[stable(feature = "refcell_swap", since = "1.24.0")]
-    pub fn swap(&self, other: &Self) {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn swap(&self, other: &Self) {
         mem::swap(&mut *self.borrow_mut(), &mut *other.borrow_mut())
     }
 }
@@ -975,7 +986,8 @@ impl<T: ?Sized> RefCell<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     #[track_caller]
-    pub fn borrow(&self) -> Ref<'_, T> {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn borrow(&self) -> Ref<'_, T> {
         match self.try_borrow() {
             Ok(b) => b,
             Err(err) => panic_already_mutably_borrowed(err),
@@ -1010,14 +1022,15 @@ impl<T: ?Sized> RefCell<T> {
     #[stable(feature = "try_borrow", since = "1.13.0")]
     #[inline]
     #[cfg_attr(feature = "debug_refcell", track_caller)]
-    pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
         match BorrowRef::new(&self.borrow) {
             Some(b) => {
                 #[cfg(feature = "debug_refcell")]
                 {
                     // `borrowed_at` is always the *first* active borrow
                     if b.borrow.get() == 1 {
-                        self.borrowed_at.set(Some(crate::panic::Location::caller()));
+                        self.borrowed_at.replace(Some(crate::panic::Location::caller()));
                     }
                 }
 
@@ -1071,7 +1084,8 @@ impl<T: ?Sized> RefCell<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     #[track_caller]
-    pub fn borrow_mut(&self) -> RefMut<'_, T> {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn borrow_mut(&self) -> RefMut<'_, T> {
         match self.try_borrow_mut() {
             Ok(b) => b,
             Err(err) => panic_already_borrowed(err),
@@ -1103,12 +1117,13 @@ impl<T: ?Sized> RefCell<T> {
     #[stable(feature = "try_borrow", since = "1.13.0")]
     #[inline]
     #[cfg_attr(feature = "debug_refcell", track_caller)]
-    pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
         match BorrowRefMut::new(&self.borrow) {
             Some(b) => {
                 #[cfg(feature = "debug_refcell")]
                 {
-                    self.borrowed_at.set(Some(crate::panic::Location::caller()));
+                    self.borrowed_at.replace(Some(crate::panic::Location::caller()));
                 }
 
                 // SAFETY: `BorrowRefMut` guarantees unique access.
@@ -1139,7 +1154,8 @@ impl<T: ?Sized> RefCell<T> {
     #[stable(feature = "cell_as_ptr", since = "1.12.0")]
     #[rustc_as_ptr]
     #[rustc_never_returns_null_ptr]
-    pub fn as_ptr(&self) -> *mut T {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn as_ptr(&self) -> *mut T {
         self.value.get()
     }
 
@@ -1176,7 +1192,8 @@ impl<T: ?Sized> RefCell<T> {
     /// ```
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
-    pub fn get_mut(&mut self) -> &mut T {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn get_mut(&mut self) -> &mut T {
         self.value.get_mut()
     }
 
@@ -1202,7 +1219,8 @@ impl<T: ?Sized> RefCell<T> {
     /// assert!(c.try_borrow().is_ok());
     /// ```
     #[unstable(feature = "cell_leak", issue = "69099")]
-    pub fn undo_leak(&mut self) -> &mut T {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn undo_leak(&mut self) -> &mut T {
         *self.borrow.get_mut() = UNUSED;
         self.get_mut()
     }
@@ -1236,7 +1254,8 @@ impl<T: ?Sized> RefCell<T> {
     /// ```
     #[stable(feature = "borrow_state", since = "1.37.0")]
     #[inline]
-    pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
         if !is_writing(self.borrow.get()) {
             // SAFETY: We check that nobody is actively writing now, but it is
             // the caller's responsibility to ensure that nobody writes until
@@ -1400,7 +1419,7 @@ struct BorrowRef<'b> {
 
 impl<'b> BorrowRef<'b> {
     #[inline]
-    fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRef<'b>> {
+    const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRef<'b>> {
         let b = borrow.get().wrapping_add(1);
         if !is_reading(b) {
             // Incrementing borrow can result in a non-reading value (<= 0) in these cases:
@@ -1417,22 +1436,24 @@ impl<'b> BorrowRef<'b> {
             // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow
             // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize
             //    is large enough to represent having one more read borrow
-            borrow.set(b);
+            borrow.replace(b);
             Some(BorrowRef { borrow })
         }
     }
 }
 
-impl Drop for BorrowRef<'_> {
+#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+impl const Drop for BorrowRef<'_> {
     #[inline]
     fn drop(&mut self) {
         let borrow = self.borrow.get();
         debug_assert!(is_reading(borrow));
-        self.borrow.set(borrow - 1);
+        self.borrow.replace(borrow - 1);
     }
 }
 
-impl Clone for BorrowRef<'_> {
+#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+impl const Clone for BorrowRef<'_> {
     #[inline]
     fn clone(&self) -> Self {
         // Since this Ref exists, we know the borrow flag
@@ -1442,7 +1463,7 @@ impl Clone for BorrowRef<'_> {
         // Prevent the borrow counter from overflowing into
         // a writing borrow.
         assert!(borrow != BorrowCounter::MAX);
-        self.borrow.set(borrow + 1);
+        self.borrow.replace(borrow + 1);
         BorrowRef { borrow: self.borrow }
     }
 }
@@ -1463,7 +1484,8 @@ pub struct Ref<'b, T: ?Sized + 'b> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Deref for Ref<'_, T> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const Deref for Ref<'_, T> {
     type Target = T;
 
     #[inline]
@@ -1488,7 +1510,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     #[stable(feature = "cell_extras", since = "1.15.0")]
     #[must_use]
     #[inline]
-    pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
         Ref { value: orig.value, borrow: orig.borrow.clone() }
     }
 
@@ -1610,7 +1633,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// assert!(cell.try_borrow_mut().is_err());
     /// ```
     #[unstable(feature = "cell_leak", issue = "69099")]
-    pub fn leak(orig: Ref<'b, T>) -> &'b T {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn leak(orig: Ref<'b, T>) -> &'b T {
         // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to
         // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a
         // unique reference to the borrowed RefCell. No further mutable references can be created
@@ -1776,7 +1800,8 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     /// assert!(cell.try_borrow_mut().is_err());
     /// ```
     #[unstable(feature = "cell_leak", issue = "69099")]
-    pub fn leak(mut orig: RefMut<'b, T>) -> &'b mut T {
+    #[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+    pub const fn leak(mut orig: RefMut<'b, T>) -> &'b mut T {
         // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't
         // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would
         // require a unique reference to the borrowed RefCell. No further references can be created
@@ -1792,25 +1817,26 @@ struct BorrowRefMut<'b> {
     borrow: &'b Cell<BorrowCounter>,
 }
 
-impl Drop for BorrowRefMut<'_> {
+#[rustc_const_unstable(feature = "const_ref_cell", issue = "137844")]
+impl const Drop for BorrowRefMut<'_> {
     #[inline]
     fn drop(&mut self) {
         let borrow = self.borrow.get();
         debug_assert!(is_writing(borrow));
-        self.borrow.set(borrow + 1);
+        self.borrow.replace(borrow + 1);
     }
 }
 
 impl<'b> BorrowRefMut<'b> {
     #[inline]
-    fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRefMut<'b>> {
+    const fn new(borrow: &'b Cell<BorrowCounter>) -> Option<BorrowRefMut<'b>> {
         // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
         // mutable reference, and so there must currently be no existing
         // references. Thus, while clone increments the mutable refcount, here
         // we explicitly only allow going from UNUSED to UNUSED - 1.
         match borrow.get() {
             UNUSED => {
-                borrow.set(UNUSED - 1);
+                borrow.replace(UNUSED - 1);
                 Some(BorrowRefMut { borrow })
             }
             _ => None,
@@ -1849,7 +1875,8 @@ pub struct RefMut<'b, T: ?Sized + 'b> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Deref for RefMut<'_, T> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const Deref for RefMut<'_, T> {
     type Target = T;
 
     #[inline]
@@ -1860,7 +1887,8 @@ impl<T: ?Sized> Deref for RefMut<'_, T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> DerefMut for RefMut<'_, T> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const DerefMut for RefMut<'_, T> {
     #[inline]
     fn deref_mut(&mut self) -> &mut T {
         // SAFETY: the value is accessible as long as we hold our borrow.
diff --git a/library/coretests/tests/cell.rs b/library/coretests/tests/cell.rs
index 781a46c3744..c0ac66e5d2b 100644
--- a/library/coretests/tests/cell.rs
+++ b/library/coretests/tests/cell.rs
@@ -1,4 +1,5 @@
 use core::cell::*;
+use core::mem::forget;
 
 #[test]
 fn smoketest_unsafe_cell() {
@@ -477,3 +478,74 @@ fn const_cells() {
         const _: i32 = CELL.into_inner();
     */
 }
+
+#[test]
+fn refcell_borrow() {
+    // Check that `borrow` is usable at compile-time
+    const {
+        let a = RefCell::new(0);
+        assert!(a.try_borrow().is_ok());
+        assert!(a.try_borrow_mut().is_ok());
+        let a_ref = a.borrow();
+        assert!(*a_ref == 0);
+        assert!(a.try_borrow().is_ok());
+        assert!(a.try_borrow_mut().is_err());
+    }
+}
+
+#[test]
+fn refcell_borrow_mut() {
+    // Check that `borrow_mut` is usable at compile-time
+    const {
+        let mut a = RefCell::new(0);
+        {
+            assert!(a.try_borrow().is_ok());
+            assert!(a.try_borrow_mut().is_ok());
+            let mut a_ref = a.borrow_mut();
+            assert!(*a_ref == 0);
+            *a_ref = 10;
+            assert!(*a_ref == 10);
+            assert!(a.try_borrow().is_err());
+            assert!(a.try_borrow_mut().is_err());
+        }
+        assert!(*a.get_mut() == 10);
+    };
+}
+struct NeverDrop;
+impl Drop for NeverDrop {
+    fn drop(&mut self) {
+        panic!("should never be called");
+    }
+}
+
+#[test]
+fn refcell_replace() {
+    // Check that `replace` is usable at compile-time
+    const {
+        let a = RefCell::new(0);
+        assert!(a.replace(10) == 0);
+        let a = a.into_inner();
+        assert!(a == 10);
+
+        let b = RefCell::new(NeverDrop);
+        forget(b.replace(NeverDrop));
+        forget(b)
+    };
+}
+
+#[test]
+fn refcell_swap() {
+    // Check that `swap` is usable at compile-time
+    const {
+        let (a, b) = (RefCell::new(31), RefCell::new(41));
+        a.swap(&b);
+        let (a, b) = (a.into_inner(), b.into_inner());
+        assert!(a == 41);
+        assert!(b == 31);
+
+        let c = RefCell::new(NeverDrop);
+        let d = RefCell::new(NeverDrop);
+        c.swap(&d);
+        forget((c, d));
+    };
+}
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 5449132413b..b6298883784 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -15,8 +15,11 @@
 #![feature(cfg_target_has_reliable_f16_f128)]
 #![feature(char_max_len)]
 #![feature(clone_to_uninit)]
+#![feature(const_deref)]
+#![feature(const_destruct)]
 #![feature(const_eval_select)]
 #![feature(const_float_round_methods)]
+#![feature(const_ref_cell)]
 #![feature(const_trait_impl)]
 #![feature(core_float_math)]
 #![feature(core_intrinsics)]
diff --git a/tests/ui/coroutine/auto-trait-regions.rs b/tests/ui/coroutine/auto-trait-regions.rs
index f115896a473..736555b31bb 100644
--- a/tests/ui/coroutine/auto-trait-regions.rs
+++ b/tests/ui/coroutine/auto-trait-regions.rs
@@ -23,31 +23,31 @@ fn assert_foo<T: Foo>(f: T) {}
 fn main() {
     // Make sure 'static is erased for coroutine interiors so we can't match it in trait selection
     let x: &'static _ = &OnlyFooIfStaticRef(No);
-    let gen = #[coroutine] move || {
+    let generator = #[coroutine] move || {
         let x = x;
         yield;
         assert_foo(x);
     };
-    assert_foo(gen);
+    assert_foo(generator);
     //~^ ERROR implementation of `Foo` is not general enough
 
     // Allow impls which matches any lifetime
     let x = &OnlyFooIfRef(No);
-    let gen = #[coroutine] move || {
+    let generator = #[coroutine] move || {
         let x = x;
         yield;
         assert_foo(x);
     };
-    assert_foo(gen); // ok
+    assert_foo(generator); // ok
 
     // Disallow impls which relates lifetimes in the coroutine interior
-    let gen = #[coroutine] move || {
+    let generator = #[coroutine] move || {
         let a = A(&mut true, &mut true, No);
         //~^ ERROR borrow may still be in use when coroutine yields
         //~| ERROR borrow may still be in use when coroutine yields
         yield;
         assert_foo(a);
     };
-    assert_foo(gen);
+    assert_foo(generator);
     //~^ ERROR not general enough
 }
diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr
index 77b5f3ce57c..beb689d868d 100644
--- a/tests/ui/coroutine/auto-trait-regions.stderr
+++ b/tests/ui/coroutine/auto-trait-regions.stderr
@@ -1,8 +1,8 @@
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/auto-trait-regions.rs:45:19
    |
-LL |     let gen = #[coroutine] move || {
-   |                            ------- within this coroutine
+LL |     let generator = #[coroutine] move || {
+   |                                  ------- within this coroutine
 LL |         let a = A(&mut true, &mut true, No);
    |                   ^^^^^^^^^
 ...
@@ -11,14 +11,14 @@ LL |         yield;
    |
 help: add `static` to mark this coroutine as unmovable
    |
-LL |     let gen = #[coroutine] static move || {
-   |                            ++++++
+LL |     let generator = #[coroutine] static move || {
+   |                                  ++++++
 
 error[E0626]: borrow may still be in use when coroutine yields
   --> $DIR/auto-trait-regions.rs:45:30
    |
-LL |     let gen = #[coroutine] move || {
-   |                            ------- within this coroutine
+LL |     let generator = #[coroutine] move || {
+   |                                  ------- within this coroutine
 LL |         let a = A(&mut true, &mut true, No);
    |                              ^^^^^^^^^
 ...
@@ -27,14 +27,14 @@ LL |         yield;
    |
 help: add `static` to mark this coroutine as unmovable
    |
-LL |     let gen = #[coroutine] static move || {
-   |                            ++++++
+LL |     let generator = #[coroutine] static move || {
+   |                                  ++++++
 
 error: implementation of `Foo` is not general enough
   --> $DIR/auto-trait-regions.rs:31:5
    |
-LL |     assert_foo(gen);
-   |     ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+LL |     assert_foo(generator);
+   |     ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
    = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`...
    = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef`
@@ -42,8 +42,8 @@ LL |     assert_foo(gen);
 error: implementation of `Foo` is not general enough
   --> $DIR/auto-trait-regions.rs:51:5
    |
-LL |     assert_foo(gen);
-   |     ^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+LL |     assert_foo(generator);
+   |     ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
    = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`...
    = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2`
diff --git a/tests/ui/coroutine/clone-impl-static.rs b/tests/ui/coroutine/clone-impl-static.rs
index f6fadff7faf..2f941d65591 100644
--- a/tests/ui/coroutine/clone-impl-static.rs
+++ b/tests/ui/coroutine/clone-impl-static.rs
@@ -7,13 +7,13 @@
 #![feature(coroutines, coroutine_clone, stmt_expr_attributes)]
 
 fn main() {
-    let gen = #[coroutine]
+    let generator = #[coroutine]
     static move || {
         yield;
     };
-    check_copy(&gen);
+    check_copy(&generator);
     //~^ ERROR Copy` is not satisfied
-    check_clone(&gen);
+    check_clone(&generator);
     //~^ ERROR Clone` is not satisfied
 }
 
diff --git a/tests/ui/coroutine/clone-impl-static.stderr b/tests/ui/coroutine/clone-impl-static.stderr
index db1d2770346..9fb71fd5fd0 100644
--- a/tests/ui/coroutine/clone-impl-static.stderr
+++ b/tests/ui/coroutine/clone-impl-static.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Copy` is not satisfied
   --> $DIR/clone-impl-static.rs:14:16
    |
-LL |     check_copy(&gen);
-   |     ---------- ^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
+LL |     check_copy(&generator);
+   |     ---------- ^^^^^^^^^^ the trait `Copy` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -15,8 +15,8 @@ LL | fn check_copy<T: Copy>(_x: &T) {}
 error[E0277]: the trait bound `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}: Clone` is not satisfied
   --> $DIR/clone-impl-static.rs:16:17
    |
-LL |     check_clone(&gen);
-   |     ----------- ^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
+LL |     check_clone(&generator);
+   |     ----------- ^^^^^^^^^^ the trait `Clone` is not implemented for `{static coroutine@$DIR/clone-impl-static.rs:11:5: 11:19}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr
index 7e34f4d35b4..0835f766a82 100644
--- a/tests/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr
@@ -1,5 +1,5 @@
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:1:10
+  --> $DIR/bad-assoc-ty.rs:5:10
    |
 LL | type A = [u8; 4]::AssocTy;
    |          ^^^^^^^
@@ -10,7 +10,7 @@ LL | type A = <[u8; 4]>::AssocTy;
    |          +       +
 
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:5:10
+  --> $DIR/bad-assoc-ty.rs:9:10
    |
 LL | type B = [u8]::AssocTy;
    |          ^^^^
@@ -21,7 +21,7 @@ LL | type B = <[u8]>::AssocTy;
    |          +    +
 
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:9:10
+  --> $DIR/bad-assoc-ty.rs:13:10
    |
 LL | type C = (u8)::AssocTy;
    |          ^^^^
@@ -32,7 +32,7 @@ LL | type C = <(u8)>::AssocTy;
    |          +    +
 
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:13:10
+  --> $DIR/bad-assoc-ty.rs:17:10
    |
 LL | type D = (u8, u8)::AssocTy;
    |          ^^^^^^^^
@@ -43,7 +43,7 @@ LL | type D = <(u8, u8)>::AssocTy;
    |          +        +
 
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:17:10
+  --> $DIR/bad-assoc-ty.rs:21:10
    |
 LL | type E = _::AssocTy;
    |          ^
@@ -54,7 +54,7 @@ LL | type E = <_>::AssocTy;
    |          + +
 
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:21:19
+  --> $DIR/bad-assoc-ty.rs:25:19
    |
 LL | type F = &'static (u8)::AssocTy;
    |                   ^^^^
@@ -65,7 +65,7 @@ LL | type F = &'static <(u8)>::AssocTy;
    |                   +    +
 
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:27:10
+  --> $DIR/bad-assoc-ty.rs:31:10
    |
 LL | type G = dyn 'static + (Send)::AssocTy;
    |          ^^^^^^^^^^^^^^^^^^^^
@@ -76,7 +76,7 @@ LL | type G = <dyn 'static + (Send)>::AssocTy;
    |          +                    +
 
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:46:10
+  --> $DIR/bad-assoc-ty.rs:51:10
    |
 LL | type I = ty!()::AssocTy;
    |          ^^^^^
@@ -87,7 +87,7 @@ LL | type I = <ty!()>::AssocTy;
    |          +     +
 
 error: missing angle brackets in associated item path
-  --> $DIR/bad-assoc-ty.rs:39:19
+  --> $DIR/bad-assoc-ty.rs:44:19
    |
 LL |     ($ty: ty) => ($ty::AssocTy);
    |                   ^^^
@@ -102,7 +102,7 @@ LL |     ($ty: ty) => (<$ty>::AssocTy);
    |                   +   +
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:1:10
+  --> $DIR/bad-assoc-ty.rs:5:10
    |
 LL | type A = [u8; 4]::AssocTy;
    |          ^^^^^^^^^^^^^^^^
@@ -114,7 +114,7 @@ LL + type A = <[u8; 4] as Example>::AssocTy;
    |
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:5:10
+  --> $DIR/bad-assoc-ty.rs:9:10
    |
 LL | type B = [u8]::AssocTy;
    |          ^^^^^^^^^^^^^
@@ -126,7 +126,7 @@ LL + type B = <[u8] as Example>::AssocTy;
    |
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:9:10
+  --> $DIR/bad-assoc-ty.rs:13:10
    |
 LL | type C = (u8)::AssocTy;
    |          ^^^^^^^^^^^^^
@@ -138,7 +138,7 @@ LL + type C = <u8 as Example>::AssocTy;
    |
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:13:10
+  --> $DIR/bad-assoc-ty.rs:17:10
    |
 LL | type D = (u8, u8)::AssocTy;
    |          ^^^^^^^^^^^^^^^^^
@@ -150,13 +150,13 @@ LL + type D = <(u8, u8) as Example>::AssocTy;
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
-  --> $DIR/bad-assoc-ty.rs:17:10
+  --> $DIR/bad-assoc-ty.rs:21:10
    |
 LL | type E = _::AssocTy;
    |          ^ not allowed in type signatures
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:21:19
+  --> $DIR/bad-assoc-ty.rs:25:19
    |
 LL | type F = &'static (u8)::AssocTy;
    |                   ^^^^^^^^^^^^^
@@ -168,7 +168,7 @@ LL + type F = &'static <u8 as Example>::AssocTy;
    |
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:27:10
+  --> $DIR/bad-assoc-ty.rs:31:10
    |
 LL | type G = dyn 'static + (Send)::AssocTy;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -180,7 +180,7 @@ LL + type G = <(dyn Send + 'static) as Example>::AssocTy;
    |
 
 warning: trait objects without an explicit `dyn` are deprecated
-  --> $DIR/bad-assoc-ty.rs:33:10
+  --> $DIR/bad-assoc-ty.rs:37:10
    |
 LL | type H = Fn(u8) -> (u8)::Output;
    |          ^^^^^^^^^^^^^^
@@ -194,7 +194,7 @@ LL | type H = <dyn Fn(u8) -> (u8)>::Output;
    |          ++++               +
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:33:10
+  --> $DIR/bad-assoc-ty.rs:37:10
    |
 LL | type H = Fn(u8) -> (u8)::Output;
    |          ^^^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL + type H = <(dyn Fn(u8) -> u8 + 'static) as IntoFuture>::Output;
    |
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:39:19
+  --> $DIR/bad-assoc-ty.rs:44:19
    |
 LL |     ($ty: ty) => ($ty::AssocTy);
    |                   ^^^^^^^^^^^^
@@ -225,7 +225,7 @@ LL +     ($ty: ty) => (<u8 as Example>::AssocTy);
    |
 
 error[E0223]: ambiguous associated type
-  --> $DIR/bad-assoc-ty.rs:46:10
+  --> $DIR/bad-assoc-ty.rs:51:10
    |
 LL | type I = ty!()::AssocTy;
    |          ^^^^^^^^^^^^^^
@@ -237,7 +237,7 @@ LL + type I = <u8 as Example>::AssocTy;
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/bad-assoc-ty.rs:51:13
+  --> $DIR/bad-assoc-ty.rs:56:13
    |
 LL | fn foo<X: K<_, _>>(x: X) {}
    |             ^  ^ not allowed in type signatures
@@ -245,7 +245,7 @@ LL | fn foo<X: K<_, _>>(x: X) {}
    |             not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/bad-assoc-ty.rs:54:34
+  --> $DIR/bad-assoc-ty.rs:59:34
    |
 LL | fn bar<F>(_: F) where F: Fn() -> _ {}
    |                                  ^ not allowed in type signatures
@@ -257,7 +257,7 @@ LL + fn bar<F, T>(_: F) where F: Fn() -> T {}
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/bad-assoc-ty.rs:57:19
+  --> $DIR/bad-assoc-ty.rs:62:19
    |
 LL | fn baz<F: Fn() -> _>(_: F) {}
    |                   ^ not allowed in type signatures
@@ -269,7 +269,7 @@ LL + fn baz<F: Fn() -> T, T>(_: F) {}
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/bad-assoc-ty.rs:60:33
+  --> $DIR/bad-assoc-ty.rs:65:33
    |
 LL | struct L<F>(F) where F: Fn() -> _;
    |                                 ^ not allowed in type signatures
@@ -281,7 +281,7 @@ LL + struct L<F, T>(F) where F: Fn() -> T;
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/bad-assoc-ty.rs:82:38
+  --> $DIR/bad-assoc-ty.rs:87:38
    |
 LL |     fn foo<F>(_: F) where F: Fn() -> _ {}
    |                                      ^ not allowed in type signatures
@@ -293,7 +293,7 @@ LL +     fn foo<F, T>(_: F) where F: Fn() -> T {}
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/bad-assoc-ty.rs:62:30
+  --> $DIR/bad-assoc-ty.rs:67:30
    |
 LL | struct M<F> where F: Fn() -> _ {
    |                              ^ not allowed in type signatures
@@ -305,7 +305,7 @@ LL + struct M<F, T> where F: Fn() -> T {
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for enums
-  --> $DIR/bad-assoc-ty.rs:66:28
+  --> $DIR/bad-assoc-ty.rs:71:28
    |
 LL | enum N<F> where F: Fn() -> _ {
    |                            ^ not allowed in type signatures
@@ -317,7 +317,7 @@ LL + enum N<F, T> where F: Fn() -> T {
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for unions
-  --> $DIR/bad-assoc-ty.rs:71:29
+  --> $DIR/bad-assoc-ty.rs:76:29
    |
 LL | union O<F> where F: Fn() -> _ {
    |                             ^ not allowed in type signatures
@@ -329,7 +329,7 @@ LL + union O<F, T> where F: Fn() -> T {
    |
 
 error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
-  --> $DIR/bad-assoc-ty.rs:73:5
+  --> $DIR/bad-assoc-ty.rs:78:5
    |
 LL |     foo: F,
    |     ^^^^^^
@@ -341,7 +341,7 @@ LL |     foo: std::mem::ManuallyDrop<F>,
    |          +++++++++++++++++++++++ +
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits
-  --> $DIR/bad-assoc-ty.rs:77:29
+  --> $DIR/bad-assoc-ty.rs:82:29
    |
 LL | trait P<F> where F: Fn() -> _ {
    |                             ^ not allowed in type signatures
diff --git a/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr b/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr
new file mode 100644
index 00000000000..3cc403f9ac4
--- /dev/null
+++ b/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr
@@ -0,0 +1,340 @@
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:5:10
+   |
+LL | type A = [u8; 4]::AssocTy;
+   |          ^^^^^^^
+   |
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL | type A = <[u8; 4]>::AssocTy;
+   |          +       +
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:9:10
+   |
+LL | type B = [u8]::AssocTy;
+   |          ^^^^
+   |
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL | type B = <[u8]>::AssocTy;
+   |          +    +
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:13:10
+   |
+LL | type C = (u8)::AssocTy;
+   |          ^^^^
+   |
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL | type C = <(u8)>::AssocTy;
+   |          +    +
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:17:10
+   |
+LL | type D = (u8, u8)::AssocTy;
+   |          ^^^^^^^^
+   |
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL | type D = <(u8, u8)>::AssocTy;
+   |          +        +
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:21:10
+   |
+LL | type E = _::AssocTy;
+   |          ^
+   |
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL | type E = <_>::AssocTy;
+   |          + +
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:25:19
+   |
+LL | type F = &'static (u8)::AssocTy;
+   |                   ^^^^
+   |
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL | type F = &'static <(u8)>::AssocTy;
+   |                   +    +
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:31:10
+   |
+LL | type G = dyn 'static + (Send)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^^^^
+   |
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL | type G = <dyn 'static + (Send)>::AssocTy;
+   |          +                    +
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:51:10
+   |
+LL | type I = ty!()::AssocTy;
+   |          ^^^^^
+   |
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL | type I = <ty!()>::AssocTy;
+   |          +     +
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:44:19
+   |
+LL |     ($ty: ty) => ($ty::AssocTy);
+   |                   ^^^
+...
+LL | type J = ty!(u8);
+   |          ------- in this macro invocation
+   |
+   = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
+   |
+LL |     ($ty: ty) => (<$ty>::AssocTy);
+   |                   +   +
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:5:10
+   |
+LL | type A = [u8; 4]::AssocTy;
+   |          ^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8; 4]`, you could use the fully-qualified path
+   |
+LL - type A = [u8; 4]::AssocTy;
+LL + type A = <[u8; 4] as Example>::AssocTy;
+   |
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:9:10
+   |
+LL | type B = [u8]::AssocTy;
+   |          ^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `[u8]`, you could use the fully-qualified path
+   |
+LL - type B = [u8]::AssocTy;
+LL + type B = <[u8] as Example>::AssocTy;
+   |
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:13:10
+   |
+LL | type C = (u8)::AssocTy;
+   |          ^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
+   |
+LL - type C = (u8)::AssocTy;
+LL + type C = <u8 as Example>::AssocTy;
+   |
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:17:10
+   |
+LL | type D = (u8, u8)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(u8, u8)`, you could use the fully-qualified path
+   |
+LL - type D = (u8, u8)::AssocTy;
+LL + type D = <(u8, u8) as Example>::AssocTy;
+   |
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
+  --> $DIR/bad-assoc-ty.rs:21:10
+   |
+LL | type E = _::AssocTy;
+   |          ^ not allowed in type signatures
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:25:19
+   |
+LL | type F = &'static (u8)::AssocTy;
+   |                   ^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
+   |
+LL - type F = &'static (u8)::AssocTy;
+LL + type F = &'static <u8 as Example>::AssocTy;
+   |
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:31:10
+   |
+LL | type G = dyn 'static + (Send)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `(dyn Send + 'static)`, you could use the fully-qualified path
+   |
+LL - type G = dyn 'static + (Send)::AssocTy;
+LL + type G = <(dyn Send + 'static) as Example>::AssocTy;
+   |
+
+error[E0782]: expected a type, found a trait
+  --> $DIR/bad-assoc-ty.rs:37:10
+   |
+LL | type H = Fn(u8) -> (u8)::Output;
+   |          ^^^^^^^^^^^^^^
+   |
+help: you can add the `dyn` keyword if you want a trait object
+   |
+LL | type H = <dyn Fn(u8) -> (u8)>::Output;
+   |          ++++               +
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:44:19
+   |
+LL |     ($ty: ty) => ($ty::AssocTy);
+   |                   ^^^^^^^^^^^^
+...
+LL | type J = ty!(u8);
+   |          ------- in this macro invocation
+   |
+   = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
+   |
+LL -     ($ty: ty) => ($ty::AssocTy);
+LL +     ($ty: ty) => (<u8 as Example>::AssocTy);
+   |
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:51:10
+   |
+LL | type I = ty!()::AssocTy;
+   |          ^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path
+   |
+LL - type I = ty!()::AssocTy;
+LL + type I = <u8 as Example>::AssocTy;
+   |
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/bad-assoc-ty.rs:56:13
+   |
+LL | fn foo<X: K<_, _>>(x: X) {}
+   |             ^  ^ not allowed in type signatures
+   |             |
+   |             not allowed in type signatures
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/bad-assoc-ty.rs:59:34
+   |
+LL | fn bar<F>(_: F) where F: Fn() -> _ {}
+   |                                  ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL - fn bar<F>(_: F) where F: Fn() -> _ {}
+LL + fn bar<F, T>(_: F) where F: Fn() -> T {}
+   |
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/bad-assoc-ty.rs:62:19
+   |
+LL | fn baz<F: Fn() -> _>(_: F) {}
+   |                   ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL - fn baz<F: Fn() -> _>(_: F) {}
+LL + fn baz<F: Fn() -> T, T>(_: F) {}
+   |
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/bad-assoc-ty.rs:65:33
+   |
+LL | struct L<F>(F) where F: Fn() -> _;
+   |                                 ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL - struct L<F>(F) where F: Fn() -> _;
+LL + struct L<F, T>(F) where F: Fn() -> T;
+   |
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/bad-assoc-ty.rs:87:38
+   |
+LL |     fn foo<F>(_: F) where F: Fn() -> _ {}
+   |                                      ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL -     fn foo<F>(_: F) where F: Fn() -> _ {}
+LL +     fn foo<F, T>(_: F) where F: Fn() -> T {}
+   |
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs
+  --> $DIR/bad-assoc-ty.rs:67:30
+   |
+LL | struct M<F> where F: Fn() -> _ {
+   |                              ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL - struct M<F> where F: Fn() -> _ {
+LL + struct M<F, T> where F: Fn() -> T {
+   |
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for enums
+  --> $DIR/bad-assoc-ty.rs:71:28
+   |
+LL | enum N<F> where F: Fn() -> _ {
+   |                            ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL - enum N<F> where F: Fn() -> _ {
+LL + enum N<F, T> where F: Fn() -> T {
+   |
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for unions
+  --> $DIR/bad-assoc-ty.rs:76:29
+   |
+LL | union O<F> where F: Fn() -> _ {
+   |                             ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL - union O<F> where F: Fn() -> _ {
+LL + union O<F, T> where F: Fn() -> T {
+   |
+
+error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
+  --> $DIR/bad-assoc-ty.rs:78:5
+   |
+LL |     foo: F,
+   |     ^^^^^^
+   |
+   = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
+help: wrap the field type in `ManuallyDrop<...>`
+   |
+LL |     foo: std::mem::ManuallyDrop<F>,
+   |          +++++++++++++++++++++++ +
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for traits
+  --> $DIR/bad-assoc-ty.rs:82:29
+   |
+LL | trait P<F> where F: Fn() -> _ {
+   |                             ^ not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL - trait P<F> where F: Fn() -> _ {
+LL + trait P<F, T> where F: Fn() -> T {
+   |
+
+error: aborting due to 29 previous errors
+
+Some errors have detailed explanations: E0121, E0223, E0740, E0782.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/did_you_mean/bad-assoc-ty.rs b/tests/ui/did_you_mean/bad-assoc-ty.rs
index 5a559b01ea2..6e56cba24e1 100644
--- a/tests/ui/did_you_mean/bad-assoc-ty.rs
+++ b/tests/ui/did_you_mean/bad-assoc-ty.rs
@@ -1,3 +1,7 @@
+//@revisions: edition2015 edition2021
+//@[edition2015] edition:2015
+//@[edition2021] edition:2021
+
 type A = [u8; 4]::AssocTy;
 //~^ ERROR missing angle brackets in associated item path
 //~| ERROR ambiguous associated type
@@ -31,9 +35,10 @@ type G = dyn 'static + (Send)::AssocTy;
 // This is actually a legal path with fn-like generic arguments in the middle!
 // Recovery should not apply in this context.
 type H = Fn(u8) -> (u8)::Output;
-//~^ ERROR ambiguous associated type
-//~| WARN trait objects without an explicit `dyn` are deprecated
-//~| WARN this is accepted in the current edition
+//[edition2015]~^ ERROR ambiguous associated type
+//[edition2015]~| WARN trait objects without an explicit `dyn` are deprecated
+//[edition2015]~| WARN this is accepted in the current edition
+//[edition2021]~^^^^ ERROR expected a type, found a trait
 
 macro_rules! ty {
     ($ty: ty) => ($ty::AssocTy);
diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2015.stderr
index 30f95851768..ac2d1ffa868 100644
--- a/tests/ui/feature-gates/feature-gate-unsized_fn_params.stderr
+++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:17:11
+  --> $DIR/feature-gate-unsized_fn_params.rs:20:11
    |
 LL | fn foo(x: dyn Foo) {
    |           ^^^^^^^ doesn't have a size known at compile-time
@@ -17,7 +17,7 @@ LL | fn foo(x: &dyn Foo) {
    |           +
 
 error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:21:11
+  --> $DIR/feature-gate-unsized_fn_params.rs:24:11
    |
 LL | fn bar(x: Foo) {
    |           ^^^ doesn't have a size known at compile-time
@@ -34,7 +34,7 @@ LL | fn bar(x: &dyn Foo) {
    |           ++++
 
 error[E0277]: the size for values of type `[()]` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:25:11
+  --> $DIR/feature-gate-unsized_fn_params.rs:30:11
    |
 LL | fn qux(_: [()]) {}
    |           ^^^^ doesn't have a size known at compile-time
@@ -47,7 +47,7 @@ LL | fn qux(_: &[()]) {}
    |           +
 
 error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:29:9
+  --> $DIR/feature-gate-unsized_fn_params.rs:34:9
    |
 LL |     foo(*x);
    |         ^^ doesn't have a size known at compile-time
diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2021.stderr b/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2021.stderr
new file mode 100644
index 00000000000..12411f695f4
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.edition2021.stderr
@@ -0,0 +1,65 @@
+error[E0782]: expected a type, found a trait
+  --> $DIR/feature-gate-unsized_fn_params.rs:24:11
+   |
+LL | fn bar(x: Foo) {
+   |           ^^^
+   |
+help: use a new generic type parameter, constrained by `Foo`
+   |
+LL - fn bar(x: Foo) {
+LL + fn bar<T: Foo>(x: T) {
+   |
+help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference
+   |
+LL | fn bar(x: impl Foo) {
+   |           ++++
+help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch
+   |
+LL | fn bar(x: &dyn Foo) {
+   |           ++++
+
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:20:11
+   |
+LL | fn foo(x: dyn Foo) {
+   |           ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+   = help: unsized fn params are gated as an unstable feature
+help: you can use `impl Trait` as the argument type
+   |
+LL - fn foo(x: dyn Foo) {
+LL + fn foo(x: impl Foo) {
+   |
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn foo(x: &dyn Foo) {
+   |           +
+
+error[E0277]: the size for values of type `[()]` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:30:11
+   |
+LL | fn qux(_: [()]) {}
+   |           ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[()]`
+   = help: unsized fn params are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed slices always have a known size
+   |
+LL | fn qux(_: &[()]) {}
+   |           +
+
+error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
+  --> $DIR/feature-gate-unsized_fn_params.rs:34:9
+   |
+LL |     foo(*x);
+   |         ^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
+   = note: all function arguments must have a statically known size
+   = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0782.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs b/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs
index c04e57843d4..3c5f932e891 100644
--- a/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs
+++ b/tests/ui/feature-gates/feature-gate-unsized_fn_params.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2021
+//@[edition2015] edition:2015
+//@[edition2021] edition:2021
 #![allow(unused, bare_trait_objects)]
 #[repr(align(256))]
 struct A {
@@ -18,7 +21,9 @@ fn foo(x: dyn Foo) { //~ ERROR [E0277]
     x.foo()
 }
 
-fn bar(x: Foo) { //~ ERROR [E0277]
+fn bar(x: Foo) {
+//[edition2015]~^ ERROR [E0277]
+//[edition2021]~^^ ERROR expected a type, found a trait
     x.foo()
 }
 
diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2015.stderr
index a2d00edbb6d..68b4e2ed39f 100644
--- a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr
+++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0700]: hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds
-  --> $DIR/rpit-hidden-erased-unsoundness.rs:16:5
+  --> $DIR/rpit-hidden-erased-unsoundness.rs:19:5
    |
 LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a {
    |              --           --------------- opaque type defined here
diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2024.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2024.stderr
new file mode 100644
index 00000000000..6c0c1789582
--- /dev/null
+++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.edition2024.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/rpit-hidden-erased-unsoundness.rs:24:5
+   |
+LL | fn step3<'a, 'b: 'a>() -> impl Send + 'a {
+   |              -- lifetime `'b` defined here
+LL |     step2::<'a, 'b>()
+   |     ^^^^^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'static`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs
index 6863a3c73ba..3338063d8c6 100644
--- a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs
+++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 // This test should never pass!
 
 #![feature(type_alias_impl_trait)]
@@ -14,11 +17,12 @@ fn step1<'a, 'b: 'a>() -> impl Sized + Captures<'b> + 'a {
 
 fn step2<'a, 'b: 'a>() -> impl Sized + 'a {
     step1::<'a, 'b>()
-    //~^ ERROR hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds
+    //[edition2015]~^ ERROR hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds
 }
 
 fn step3<'a, 'b: 'a>() -> impl Send + 'a {
     step2::<'a, 'b>()
+    //[edition2024]~^ ERROR lifetime may not live long enough
     // This should not be Send unless `'b: 'static`
 }
 
diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2015.stderr
index a1e92e53384..769a878a45c 100644
--- a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr
+++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
-  --> $DIR/rpit-hide-lifetime-for-swap.rs:17:5
+  --> $DIR/rpit-hide-lifetime-for-swap.rs:20:5
    |
 LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
    |             --                                            -------------- opaque type defined here
diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2024.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2024.stderr
new file mode 100644
index 00000000000..6109184250b
--- /dev/null
+++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.edition2024.stderr
@@ -0,0 +1,17 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/rpit-hide-lifetime-for-swap.rs:27:38
+   |
+LL |     let x = [1, 2, 3];
+   |         - binding `x` declared here
+LL |     let short = Rc::new(RefCell::new(&x));
+   |                                      ^^ borrowed value does not live long enough
+...
+LL |     let res: &'static [i32; 3] = *long.borrow();
+   |              ----------------- type annotation requires that `x` is borrowed for `'static`
+LL |     res
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs
index 4de2ffbb808..c4eaec478b8 100644
--- a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs
+++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 // This test should never pass!
 
 use std::cell::RefCell;
@@ -15,13 +18,14 @@ impl<T> Swap for Rc<RefCell<T>> {
 
 fn hide<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
     x
-    //~^ ERROR hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
+    //[edition2015]~^ ERROR hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
 }
 
 fn dangle() -> &'static [i32; 3] {
     let long = Rc::new(RefCell::new(&[4, 5, 6]));
     let x = [1, 2, 3];
     let short = Rc::new(RefCell::new(&x));
+    //[edition2024]~^ ERROR `x` does not live long enough
     hide(long.clone()).swap(hide(short));
     let res: &'static [i32; 3] = *long.borrow();
     res
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2015.stderr
index 304d7d43b78..64f0b201ca2 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
    |
 LL | fn fuz() -> (usize, Trait) { (42, Struct) }
    |             ^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,7 +9,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
    = note: the return type of a function must have a statically known size
 
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
    |
 LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
    |             ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -19,7 +19,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
    = note: the return type of a function must have a statically known size
 
 error[E0746]: return type cannot be a trait object without pointer indirection
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
    |
 LL | fn bap() -> Trait { Struct }
    |             ^^^^^ doesn't have a size known at compile-time
@@ -34,7 +34,7 @@ LL | fn bap() -> Box<dyn Trait> { Box::new(Struct) }
    |             +++++++      +   +++++++++      +
 
 error[E0746]: return type cannot be a trait object without pointer indirection
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:22:13
    |
 LL | fn ban() -> dyn Trait { Struct }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
@@ -50,7 +50,7 @@ LL | fn ban() -> Box<dyn Trait> { Box::new(Struct) }
    |             ++++         +   +++++++++      +
 
 error[E0746]: return type cannot be a trait object without pointer indirection
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:24:13
    |
 LL | fn bak() -> dyn Trait { unimplemented!() }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
@@ -66,7 +66,7 @@ LL | fn bak() -> Box<dyn Trait> { Box::new(unimplemented!()) }
    |             ++++         +   +++++++++                +
 
 error[E0746]: return type cannot be a trait object without pointer indirection
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:21:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:26:13
    |
 LL | fn bal() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
@@ -86,7 +86,7 @@ LL ~     Box::new(42)
    |
 
 error[E0746]: return type cannot be a trait object without pointer indirection
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:32:13
    |
 LL | fn bax() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
@@ -106,7 +106,7 @@ LL ~         Box::new(42)
    |
 
 error[E0746]: return type cannot be a trait object without pointer indirection
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:62:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:67:13
    |
 LL | fn bat() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
@@ -126,7 +126,7 @@ LL ~     Box::new(42)
    |
 
 error[E0746]: return type cannot be a trait object without pointer indirection
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:68:13
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:73:13
    |
 LL | fn bay() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
@@ -146,7 +146,7 @@ LL ~         Box::new(42)
    |
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:35
    |
 LL | fn fuz() -> (usize, Trait) { (42, Struct) }
    |                                   ^^^^^^ expected `dyn Trait`, found `Struct`
@@ -156,7 +156,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
    = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
 
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:30
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:30
    |
 LL | fn fuz() -> (usize, Trait) { (42, Struct) }
    |                              ^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -166,7 +166,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
    = note: tuples must have a statically known size to be initialized
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:39
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:39
    |
 LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
    |                                       ^^^^^^ expected `dyn Trait`, found `Struct`
@@ -176,7 +176,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
    = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
 
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:34
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:34
    |
 LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
    |                                  ^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -186,7 +186,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
    = note: tuples must have a statically known size to be initialized
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:36:16
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:41:16
    |
 LL | fn bam() -> Box<dyn Trait> {
    |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
@@ -203,7 +203,7 @@ LL |         return Box::new(Struct);
    |                +++++++++      +
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:38:5
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:43:5
    |
 LL | fn bam() -> Box<dyn Trait> {
    |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
@@ -220,7 +220,7 @@ LL |     Box::new(42)
    |     +++++++++  +
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:42:16
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:47:16
    |
 LL | fn baq() -> Box<dyn Trait> {
    |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
@@ -237,7 +237,7 @@ LL |         return Box::new(0);
    |                +++++++++ +
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:44:5
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:49:5
    |
 LL | fn baq() -> Box<dyn Trait> {
    |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
@@ -254,7 +254,7 @@ LL |     Box::new(42)
    |     +++++++++  +
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9
    |
 LL | fn baz() -> Box<dyn Trait> {
    |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
@@ -271,7 +271,7 @@ LL |         Box::new(Struct)
    |         +++++++++      +
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:50:9
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9
    |
 LL | fn baz() -> Box<dyn Trait> {
    |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
@@ -288,7 +288,7 @@ LL |         Box::new(42)
    |         +++++++++  +
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:9
    |
 LL | fn baw() -> Box<dyn Trait> {
    |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
@@ -305,7 +305,7 @@ LL |         Box::new(0)
    |         +++++++++ +
 
 error[E0308]: mismatched types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:57:9
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:62:9
    |
 LL | fn baw() -> Box<dyn Trait> {
    |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2021.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2021.stderr
new file mode 100644
index 00000000000..5811431b494
--- /dev/null
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.edition2021.stderr
@@ -0,0 +1,308 @@
+error[E0782]: expected a type, found a trait
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:21
+   |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+   |                     ^^^^^
+   |
+help: you can add the `dyn` keyword if you want a trait object
+   |
+LL | fn fuz() -> (usize, dyn Trait) { (42, Struct) }
+   |                     +++
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |             ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+   = note: the return type of a function must have a statically known size
+
+error[E0782]: expected a type, found a trait
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
+   |
+LL | fn bap() -> Trait { Struct }
+   |             ^^^^^
+   |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+   |
+LL | fn bap() -> impl Trait { Struct }
+   |             ++++
+help: alternatively, you can return an owned trait object
+   |
+LL | fn bap() -> Box<dyn Trait> { Struct }
+   |             +++++++      +
+
+error[E0746]: return type cannot be a trait object without pointer indirection
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:22:13
+   |
+LL | fn ban() -> dyn Trait { Struct }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+help: consider returning an `impl Trait` instead of a `dyn Trait`
+   |
+LL - fn ban() -> dyn Trait { Struct }
+LL + fn ban() -> impl Trait { Struct }
+   |
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn ban() -> Box<dyn Trait> { Box::new(Struct) }
+   |             ++++         +   +++++++++      +
+
+error[E0746]: return type cannot be a trait object without pointer indirection
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:24:13
+   |
+LL | fn bak() -> dyn Trait { unimplemented!() }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+help: consider returning an `impl Trait` instead of a `dyn Trait`
+   |
+LL - fn bak() -> dyn Trait { unimplemented!() }
+LL + fn bak() -> impl Trait { unimplemented!() }
+   |
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn bak() -> Box<dyn Trait> { Box::new(unimplemented!()) }
+   |             ++++         +   +++++++++                +
+
+error[E0746]: return type cannot be a trait object without pointer indirection
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:26:13
+   |
+LL | fn bal() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+help: consider returning an `impl Trait` instead of a `dyn Trait`
+   |
+LL - fn bal() -> dyn Trait {
+LL + fn bal() -> impl Trait {
+   |
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bal() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         return Box::new(Struct);
+LL |     }
+LL ~     Box::new(42)
+   |
+
+error[E0746]: return type cannot be a trait object without pointer indirection
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:32:13
+   |
+LL | fn bax() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+help: consider returning an `impl Trait` instead of a `dyn Trait`
+   |
+LL - fn bax() -> dyn Trait {
+LL + fn bax() -> impl Trait {
+   |
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bax() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         Box::new(Struct)
+LL |     } else {
+LL ~         Box::new(42)
+   |
+
+error[E0746]: return type cannot be a trait object without pointer indirection
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:67:13
+   |
+LL | fn bat() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+help: consider returning an `impl Trait` instead of a `dyn Trait`
+   |
+LL - fn bat() -> dyn Trait {
+LL + fn bat() -> impl Trait {
+   |
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bat() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         return Box::new(0);
+LL |     }
+LL ~     Box::new(42)
+   |
+
+error[E0746]: return type cannot be a trait object without pointer indirection
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:73:13
+   |
+LL | fn bay() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+help: consider returning an `impl Trait` instead of a `dyn Trait`
+   |
+LL - fn bay() -> dyn Trait {
+LL + fn bay() -> impl Trait {
+   |
+help: alternatively, box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bay() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         Box::new(0)
+LL |     } else {
+LL ~         Box::new(42)
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:39
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |                                       ^^^^^^ expected `dyn Trait`, found `Struct`
+   |
+   = note: expected trait object `(dyn Trait + 'static)`
+                    found struct `Struct`
+   = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:34
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |                                  ^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+   = note: tuples must have a statically known size to be initialized
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:41:16
+   |
+LL | fn bam() -> Box<dyn Trait> {
+   |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+LL |     if true {
+LL |         return Struct;
+   |                ^^^^^^ expected `Box<dyn Trait>`, found `Struct`
+   |
+   = note: expected struct `Box<(dyn Trait + 'static)>`
+              found struct `Struct`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |         return Box::new(Struct);
+   |                +++++++++      +
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:43:5
+   |
+LL | fn bam() -> Box<dyn Trait> {
+   |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+...
+LL |     42
+   |     ^^ expected `Box<dyn Trait>`, found integer
+   |
+   = note: expected struct `Box<(dyn Trait + 'static)>`
+                found type `{integer}`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |     Box::new(42)
+   |     +++++++++  +
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:47:16
+   |
+LL | fn baq() -> Box<dyn Trait> {
+   |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+LL |     if true {
+LL |         return 0;
+   |                ^ expected `Box<dyn Trait>`, found integer
+   |
+   = note: expected struct `Box<(dyn Trait + 'static)>`
+                found type `{integer}`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |         return Box::new(0);
+   |                +++++++++ +
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:49:5
+   |
+LL | fn baq() -> Box<dyn Trait> {
+   |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+...
+LL |     42
+   |     ^^ expected `Box<dyn Trait>`, found integer
+   |
+   = note: expected struct `Box<(dyn Trait + 'static)>`
+                found type `{integer}`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |     Box::new(42)
+   |     +++++++++  +
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9
+   |
+LL | fn baz() -> Box<dyn Trait> {
+   |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+LL |     if true {
+LL |         Struct
+   |         ^^^^^^ expected `Box<dyn Trait>`, found `Struct`
+   |
+   = note: expected struct `Box<(dyn Trait + 'static)>`
+              found struct `Struct`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |         Box::new(Struct)
+   |         +++++++++      +
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9
+   |
+LL | fn baz() -> Box<dyn Trait> {
+   |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+...
+LL |         42
+   |         ^^ expected `Box<dyn Trait>`, found integer
+   |
+   = note: expected struct `Box<(dyn Trait + 'static)>`
+                found type `{integer}`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |         Box::new(42)
+   |         +++++++++  +
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:9
+   |
+LL | fn baw() -> Box<dyn Trait> {
+   |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+LL |     if true {
+LL |         0
+   |         ^ expected `Box<dyn Trait>`, found integer
+   |
+   = note: expected struct `Box<(dyn Trait + 'static)>`
+                found type `{integer}`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |         Box::new(0)
+   |         +++++++++ +
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:62:9
+   |
+LL | fn baw() -> Box<dyn Trait> {
+   |             -------------- expected `Box<(dyn Trait + 'static)>` because of return type
+...
+LL |         42
+   |         ^^ expected `Box<dyn Trait>`, found integer
+   |
+   = note: expected struct `Box<(dyn Trait + 'static)>`
+                found type `{integer}`
+   = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
+help: store this in the heap by calling `Box::new`
+   |
+LL |         Box::new(42)
+   |         +++++++++  +
+
+error: aborting due to 19 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0746, E0782.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
index ccf0a1ad3d4..aa1f871d8ea 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2021
+//@[edition2015] edition:2015
+//@[edition2021] edition:2021
 #![allow(bare_trait_objects)]
 struct Struct;
 trait Trait {}
@@ -5,15 +8,17 @@ impl Trait for Struct {}
 impl Trait for u32 {}
 
 fn fuz() -> (usize, Trait) { (42, Struct) }
-//~^ ERROR E0277
-//~| ERROR E0277
-//~| ERROR E0308
+//[edition2015]~^ ERROR E0277
+//[edition2015]~| ERROR E0277
+//[edition2015]~| ERROR E0308
+//[edition2021]~^^^^ ERROR expected a type, found a trait
 fn bar() -> (usize, dyn Trait) { (42, Struct) }
 //~^ ERROR E0277
 //~| ERROR E0277
 //~| ERROR E0308
 fn bap() -> Trait { Struct }
-//~^ ERROR E0746
+//[edition2015]~^ ERROR E0746
+//[edition2021]~^^ ERROR expected a type, found a trait
 fn ban() -> dyn Trait { Struct }
 //~^ ERROR E0746
 fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0746
diff --git a/tests/ui/impl-trait/hidden-lifetimes.stderr b/tests/ui/impl-trait/hidden-lifetimes.edition2015.stderr
index 70d8c816ecb..b63115f7658 100644
--- a/tests/ui/impl-trait/hidden-lifetimes.stderr
+++ b/tests/ui/impl-trait/hidden-lifetimes.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-lifetimes.rs:29:5
+  --> $DIR/hidden-lifetimes.rs:33:5
    |
 LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
    |                 --                                   -------------- opaque type defined here
@@ -14,7 +14,7 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + use<'
    |                                                                     ++++++++++++++++
 
 error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-lifetimes.rs:46:5
+  --> $DIR/hidden-lifetimes.rs:50:5
    |
 LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
    |                        --                                            -------------- opaque type defined here
diff --git a/tests/ui/impl-trait/hidden-lifetimes.edition2024.stderr b/tests/ui/impl-trait/hidden-lifetimes.edition2024.stderr
new file mode 100644
index 00000000000..d585bb50b13
--- /dev/null
+++ b/tests/ui/impl-trait/hidden-lifetimes.edition2024.stderr
@@ -0,0 +1,26 @@
+error[E0515]: cannot return value referencing local variable `x`
+  --> $DIR/hidden-lifetimes.rs:41:5
+   |
+LL |     hide_ref(&mut res).swap(hide_ref(&mut &x));
+   |                                           -- `x` is borrowed here
+LL |     res
+   |     ^^^ returns a value referencing data owned by the current function
+
+error[E0597]: `x` does not live long enough
+  --> $DIR/hidden-lifetimes.rs:57:38
+   |
+LL |     let x = [1, 2, 3];
+   |         - binding `x` declared here
+LL |     let short = Rc::new(RefCell::new(&x));
+   |                                      ^^ borrowed value does not live long enough
+LL |     hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short));
+LL |     let res: &'static [i32; 3] = *long.borrow();
+   |              ----------------- type annotation requires that `x` is borrowed for `'static`
+LL |     res
+LL | }
+   | - `x` dropped here while still borrowed
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0515, E0597.
+For more information about an error, try `rustc --explain E0515`.
diff --git a/tests/ui/impl-trait/hidden-lifetimes.rs b/tests/ui/impl-trait/hidden-lifetimes.rs
index ae07c892768..b50c43bd3fa 100644
--- a/tests/ui/impl-trait/hidden-lifetimes.rs
+++ b/tests/ui/impl-trait/hidden-lifetimes.rs
@@ -1,3 +1,7 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
+
 // Test to show what happens if we were not careful and allowed invariant
 // lifetimes to escape though an impl trait.
 //
@@ -27,14 +31,14 @@ impl<T> Swap for Rc<RefCell<T>> {
 // `&'a mut &'l T` are the same type.
 fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
     x
-    //~^ ERROR hidden type
+    //[edition2015]~^ ERROR hidden type
 }
 
 fn dangle_ref() -> &'static [i32; 3] {
     let mut res = &[4, 5, 6];
     let x = [1, 2, 3];
     hide_ref(&mut res).swap(hide_ref(&mut &x));
-    res
+    res //[edition2024]~ ERROR cannot return value referencing local variable `x`
 }
 
 // Here we are hiding `'b` making the caller believe that `Rc<RefCell<&'s T>>`
@@ -44,13 +48,13 @@ fn dangle_ref() -> &'static [i32; 3] {
 // only has a single lifetime.
 fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
     x
-    //~^ ERROR hidden type
+    //[edition2015]~^ ERROR hidden type
 }
 
 fn dangle_rc_refcell() -> &'static [i32; 3] {
     let long = Rc::new(RefCell::new(&[4, 5, 6]));
     let x = [1, 2, 3];
-    let short = Rc::new(RefCell::new(&x));
+    let short = Rc::new(RefCell::new(&x)); //[edition2024]~ ERROR `x` does not live long enough
     hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short));
     let res: &'static [i32; 3] = *long.borrow();
     res
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2015.stderr
index 4e453c108d4..4ba59826231 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds
-  --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9
+  --> $DIR/impl-fn-hrtb-bounds-2.rs:8:9
    |
 LL | fn a() -> impl Fn(&u8) -> impl Debug {
    |                           ---------- opaque type defined here
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2024.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2024.stderr
new file mode 100644
index 00000000000..c7aedfe96bb
--- /dev/null
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.edition2024.stderr
@@ -0,0 +1,15 @@
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+  --> $DIR/impl-fn-hrtb-bounds-2.rs:7:27
+   |
+LL | fn a() -> impl Fn(&u8) -> impl Debug {
+   |                           ^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
+  --> $DIR/impl-fn-hrtb-bounds-2.rs:7:19
+   |
+LL | fn a() -> impl Fn(&u8) -> impl Debug {
+   |                   ^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs
index b0aeded0ef7..f4bfbdeb9f3 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.rs
@@ -1,8 +1,11 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 #![feature(impl_trait_in_fn_trait_return)]
 use std::fmt::Debug;
 
-fn a() -> impl Fn(&u8) -> impl Debug {
-    |x| x //~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds
+fn a() -> impl Fn(&u8) -> impl Debug { //[edition2024]~ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+    |x| x //[edition2015]~ ERROR hidden type for `impl Debug` captures lifetime that does not appear in bounds
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr
index 6064b09ef09..94476bcfbe8 100644
--- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/impl-fn-predefined-lifetimes.rs:5:9
+  --> $DIR/impl-fn-predefined-lifetimes.rs:8:9
    |
 LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
    |                                                -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr
new file mode 100644
index 00000000000..2f1eacb0c34
--- /dev/null
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr
@@ -0,0 +1,11 @@
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/impl-fn-predefined-lifetimes.rs:8:9
+   |
+LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
+   |      -- this generic parameter must be used with a generic lifetime parameter
+LL |     |x| x
+   |         ^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
index 199cbbf4fcc..b2963cc10fa 100644
--- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
+++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 #![feature(impl_trait_in_fn_trait_return)]
 use std::fmt::Debug;
 
diff --git a/tests/ui/impl-trait/issues/issue-54895.stderr b/tests/ui/impl-trait/issues/issue-54895.edition2015.stderr
index 64b425328e3..27a3c6c8b7c 100644
--- a/tests/ui/impl-trait/issues/issue-54895.stderr
+++ b/tests/ui/impl-trait/issues/issue-54895.edition2015.stderr
@@ -1,11 +1,11 @@
 error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
-  --> $DIR/issue-54895.rs:15:53
+  --> $DIR/issue-54895.rs:18:53
    |
 LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
    |                                                     ^^
    |
 note: lifetime declared here
-  --> $DIR/issue-54895.rs:15:20
+  --> $DIR/issue-54895.rs:18:20
    |
 LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
    |                    ^^
diff --git a/tests/ui/impl-trait/issues/issue-54895.edition2024.stderr b/tests/ui/impl-trait/issues/issue-54895.edition2024.stderr
new file mode 100644
index 00000000000..54aa29e62d8
--- /dev/null
+++ b/tests/ui/impl-trait/issues/issue-54895.edition2024.stderr
@@ -0,0 +1,27 @@
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+  --> $DIR/issue-54895.rs:18:40
+   |
+LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+   |                                        ^^^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
+  --> $DIR/issue-54895.rs:18:20
+   |
+LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+   |                    ^^
+
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+  --> $DIR/issue-54895.rs:18:53
+   |
+LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+   |                                                     ^^
+   |
+note: lifetime declared here
+  --> $DIR/issue-54895.rs:18:20
+   |
+LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
+   |                    ^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/issues/issue-54895.rs b/tests/ui/impl-trait/issues/issue-54895.rs
index 13c0038ce43..bc1841209e1 100644
--- a/tests/ui/impl-trait/issues/issue-54895.rs
+++ b/tests/ui/impl-trait/issues/issue-54895.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 trait Trait<'a> {
     type Out;
     fn call(&'a self) -> Self::Out;
@@ -14,6 +17,7 @@ impl<'a> Trait<'a> for X {
 
 fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
     //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+    //[edition2024]~^^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     X(())
 }
 
diff --git a/tests/ui/impl-trait/issues/issue-79099.stderr b/tests/ui/impl-trait/issues/issue-79099.edition2015.stderr
index d7c0c494454..ee1a479310d 100644
--- a/tests/ui/impl-trait/issues/issue-79099.stderr
+++ b/tests/ui/impl-trait/issues/issue-79099.edition2015.stderr
@@ -1,5 +1,5 @@
 error: expected identifier, found `1`
-  --> $DIR/issue-79099.rs:3:65
+  --> $DIR/issue-79099.rs:6:65
    |
 LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
    |                                                         -----   ^ expected identifier
@@ -10,7 +10,7 @@ LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0562]: `impl Trait` is not allowed in the type of variable bindings
-  --> $DIR/issue-79099.rs:3:16
+  --> $DIR/issue-79099.rs:6:16
    |
 LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/issues/issue-79099.edition2024.stderr b/tests/ui/impl-trait/issues/issue-79099.edition2024.stderr
new file mode 100644
index 00000000000..3e422e25136
--- /dev/null
+++ b/tests/ui/impl-trait/issues/issue-79099.edition2024.stderr
@@ -0,0 +1,14 @@
+error[E0562]: `impl Trait` is not allowed in the type of variable bindings
+  --> $DIR/issue-79099.rs:6:16
+   |
+LL |         let f: impl core::future::Future<Output = u8> = async { 1 };
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `impl Trait` is only allowed in arguments and return types of functions and methods
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+   = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/impl-trait/issues/issue-79099.rs b/tests/ui/impl-trait/issues/issue-79099.rs
index c2bad59045b..8426298620f 100644
--- a/tests/ui/impl-trait/issues/issue-79099.rs
+++ b/tests/ui/impl-trait/issues/issue-79099.rs
@@ -1,8 +1,11 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 struct Bug {
     V1: [(); {
         let f: impl core::future::Future<Output = u8> = async { 1 };
         //~^ ERROR `impl Trait` is not allowed in the type of variable bindings
-        //~| ERROR expected identifier
+        //[edition2015]~| ERROR expected identifier
         1
     }],
 }
diff --git a/tests/ui/impl-trait/precise-capturing/dyn-use.stderr b/tests/ui/impl-trait/precise-capturing/dyn-use.edition2015.stderr
index d8903fc4129..9951e9e0965 100644
--- a/tests/ui/impl-trait/precise-capturing/dyn-use.stderr
+++ b/tests/ui/impl-trait/precise-capturing/dyn-use.edition2015.stderr
@@ -1,5 +1,5 @@
 error: expected one of `!`, `(`, `::`, `<`, `where`, or `{`, found keyword `use`
-  --> $DIR/dyn-use.rs:1:26
+  --> $DIR/dyn-use.rs:4:26
    |
 LL | fn dyn() -> &'static dyn use<> { &() }
    |                          ^^^ expected one of `!`, `(`, `::`, `<`, `where`, or `{`
diff --git a/tests/ui/impl-trait/precise-capturing/dyn-use.edition2024.stderr b/tests/ui/impl-trait/precise-capturing/dyn-use.edition2024.stderr
new file mode 100644
index 00000000000..cb3fe4cb583
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/dyn-use.edition2024.stderr
@@ -0,0 +1,26 @@
+error: expected identifier, found keyword `dyn`
+  --> $DIR/dyn-use.rs:4:4
+   |
+LL | fn dyn() -> &'static dyn use<> { &() }
+   |    ^^^ expected identifier, found keyword
+   |
+help: escape `dyn` to use it as an identifier
+   |
+LL | fn r#dyn() -> &'static dyn use<> { &() }
+   |    ++
+
+error: `use<...>` precise capturing syntax not allowed in `dyn` trait object bounds
+  --> $DIR/dyn-use.rs:4:26
+   |
+LL | fn dyn() -> &'static dyn use<> { &() }
+   |                          ^^^^^
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/dyn-use.rs:4:22
+   |
+LL | fn dyn() -> &'static dyn use<> { &() }
+   |                      ^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/impl-trait/precise-capturing/dyn-use.rs b/tests/ui/impl-trait/precise-capturing/dyn-use.rs
index fb2f83e2d21..0b6a9467ff7 100644
--- a/tests/ui/impl-trait/precise-capturing/dyn-use.rs
+++ b/tests/ui/impl-trait/precise-capturing/dyn-use.rs
@@ -1,2 +1,10 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 fn dyn() -> &'static dyn use<> { &() }
-//~^ ERROR expected one of `!`, `(`, `::`, `<`, `where`, or `{`, found keyword `use`
+//[edition2015]~^ ERROR expected one of `!`, `(`, `::`, `<`, `where`, or `{`, found keyword `use`
+//[edition2024]~^^ ERROR expected identifier, found keyword `dyn`
+//[edition2024]~| ERROR `use<...>` precise capturing syntax not allowed in `dyn` trait object bounds
+//[edition2024]~| ERROR at least one trait is required for an object type
+
+fn main() {}
diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2015.stderr
index 0d8fa650df4..c16722bb80f 100644
--- a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.stderr
+++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-type-suggestion.rs:3:5
+  --> $DIR/hidden-type-suggestion.rs:6:5
    |
 LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b> {
    |             --                    -------------------- opaque type defined here
@@ -15,7 +15,7 @@ LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b, 'a> {
    |                                                      ++++
 
 error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-type-suggestion.rs:9:5
+  --> $DIR/hidden-type-suggestion.rs:12:5
    |
 LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<T> {
    |          --                   ------------------- opaque type defined here
@@ -31,7 +31,7 @@ LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<'a, T> {
    |                                                +++
 
 error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-type-suggestion.rs:15:5
+  --> $DIR/hidden-type-suggestion.rs:18:5
    |
 LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<> {
    |          --                ------------------ opaque type defined here
@@ -47,7 +47,7 @@ LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<'a> {
    |                                             ++
 
 error[E0700]: hidden type for `impl Captures<'captured>` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-type-suggestion.rs:24:5
+  --> $DIR/hidden-type-suggestion.rs:27:5
    |
 LL | fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captures<'captured> {
    |            --                                                    ------------------------ opaque type defined here
@@ -63,7 +63,7 @@ LL | fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captu
    |                                                                                           ++++++++++++++++++++++++++++++
 
 error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-type-suggestion.rs:30:5
+  --> $DIR/hidden-type-suggestion.rs:33:5
    |
 LL | fn no_params_yet(_: impl Sized, y: &()) -> impl Sized {
    |                                    ---     ---------- opaque type defined here
@@ -74,7 +74,7 @@ LL |     y
    |     ^
    |
 note: you could use a `use<...>` bound to explicitly capture `'_`, but argument-position `impl Trait`s are not nameable
-  --> $DIR/hidden-type-suggestion.rs:28:21
+  --> $DIR/hidden-type-suggestion.rs:31:21
    |
 LL | fn no_params_yet(_: impl Sized, y: &()) -> impl Sized {
    |                     ^^^^^^^^^^
@@ -85,7 +85,7 @@ LL + fn no_params_yet<T: Sized>(_: T, y: &()) -> impl Sized + use<'_, T> {
    |
 
 error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
-  --> $DIR/hidden-type-suggestion.rs:36:5
+  --> $DIR/hidden-type-suggestion.rs:39:5
    |
 LL | fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized {
    |                   --                                  ---------- opaque type defined here
@@ -96,7 +96,7 @@ LL |     y
    |     ^
    |
 note: you could use a `use<...>` bound to explicitly capture `'a`, but argument-position `impl Trait`s are not nameable
-  --> $DIR/hidden-type-suggestion.rs:34:29
+  --> $DIR/hidden-type-suggestion.rs:37:29
    |
 LL | fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized {
    |                             ^^^^^^^^^^
diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2024.stderr b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2024.stderr
new file mode 100644
index 00000000000..308dc9b00fc
--- /dev/null
+++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.edition2024.stderr
@@ -0,0 +1,51 @@
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/hidden-type-suggestion.rs:6:5
+   |
+LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b> {
+   |             --                    -------------------- opaque type defined here
+   |             |
+   |             hidden type `&'a ()` captures the lifetime `'a` as defined here
+LL |
+LL |     x
+   |     ^
+   |
+help: add `'a` to the `use<...>` bound to explicitly capture it
+   |
+LL | fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b, 'a> {
+   |                                                      ++++
+
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/hidden-type-suggestion.rs:12:5
+   |
+LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<T> {
+   |          --                   ------------------- opaque type defined here
+   |          |
+   |          hidden type `&'a ()` captures the lifetime `'a` as defined here
+LL |
+LL |     x
+   |     ^
+   |
+help: add `'a` to the `use<...>` bound to explicitly capture it
+   |
+LL | fn param<'a, T>(x: &'a ()) -> impl Sized + use<'a, T> {
+   |                                                +++
+
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/hidden-type-suggestion.rs:18:5
+   |
+LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<> {
+   |          --                ------------------ opaque type defined here
+   |          |
+   |          hidden type `&'a ()` captures the lifetime `'a` as defined here
+LL |
+LL |     x
+   |     ^
+   |
+help: add `'a` to the `use<...>` bound to explicitly capture it
+   |
+LL | fn empty<'a>(x: &'a ()) -> impl Sized + use<'a> {
+   |                                             ++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs
index d34c6135596..9712eac859a 100644
--- a/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs
+++ b/tests/ui/impl-trait/precise-capturing/hidden-type-suggestion.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 fn lifetime<'a, 'b>(x: &'a ()) -> impl Sized + use<'b> {
 //~^ HELP add `'a` to the `use<...>` bound
     x
@@ -20,21 +23,21 @@ trait Captures<'a> {}
 impl<T> Captures<'_> for T {}
 
 fn missing<'a, 'captured, 'not_captured, Captured>(x: &'a ()) -> impl Captures<'captured> {
-//~^ HELP add a `use<...>` bound
+//[edition2015]~^ HELP add a `use<...>` bound
     x
-//~^ ERROR hidden type for
+//[edition2015]~^ ERROR hidden type for
 }
 
 fn no_params_yet(_: impl Sized, y: &()) -> impl Sized {
-//~^ HELP add a `use<...>` bound
+//[edition2015]~^ HELP add a `use<...>` bound
     y
-//~^ ERROR hidden type for
+//[edition2015]~^ ERROR hidden type for
 }
 
 fn yes_params_yet<'a, T>(_: impl Sized, y: &'a ()) -> impl Sized {
-//~^ HELP add a `use<...>` bound
+//[edition2015]~^ HELP add a `use<...>` bound
     y
-//~^ ERROR hidden type for
+//[edition2015]~^ ERROR hidden type for
 }
 
 fn main() {}
diff --git a/tests/ui/imports/import-from-missing-star-2.stderr b/tests/ui/imports/import-from-missing-star-2.edition2015.stderr
index 9fe2bdbcfa2..cd1a9581d30 100644
--- a/tests/ui/imports/import-from-missing-star-2.stderr
+++ b/tests/ui/imports/import-from-missing-star-2.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0432]: unresolved import `spam`
-  --> $DIR/import-from-missing-star-2.rs:2:9
+  --> $DIR/import-from-missing-star-2.rs:6:9
    |
 LL |     use spam::*;
    |         ^^^^ use of unresolved module or unlinked crate `spam`
diff --git a/tests/ui/imports/import-from-missing-star-2.edition2024.stderr b/tests/ui/imports/import-from-missing-star-2.edition2024.stderr
new file mode 100644
index 00000000000..086b7a576b2
--- /dev/null
+++ b/tests/ui/imports/import-from-missing-star-2.edition2024.stderr
@@ -0,0 +1,11 @@
+error[E0432]: unresolved import `spam`
+  --> $DIR/import-from-missing-star-2.rs:6:9
+   |
+LL |     use spam::*;
+   |         ^^^^ use of unresolved module or unlinked crate `spam`
+   |
+   = help: you might be missing a crate named `spam`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/imports/import-from-missing-star-2.rs b/tests/ui/imports/import-from-missing-star-2.rs
index cb341b0b0ca..9dad2d4886b 100644
--- a/tests/ui/imports/import-from-missing-star-2.rs
+++ b/tests/ui/imports/import-from-missing-star-2.rs
@@ -1,5 +1,10 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 mod foo {
+//[edition2015]~^ HELP you might be missing a crate named `spam`, add it to your project and import it in your code
     use spam::*; //~ ERROR unresolved import `spam` [E0432]
+    //[edition2024]~^ HELP you might be missing a crate named `spam`
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2015.stderr
index 0bf9dccfad8..4f1e769bc6c 100644
--- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr
+++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2015.stderr
@@ -1,5 +1,5 @@
 error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
-  --> $DIR/imply_bounds_from_bounds_param.rs:26:5
+  --> $DIR/imply_bounds_from_bounds_param.rs:29:5
    |
 LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
    |         --                     ------------ opaque type defined here
diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2024.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2024.stderr
new file mode 100644
index 00000000000..a7135e8f05f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.edition2024.stderr
@@ -0,0 +1,91 @@
+error[E0499]: cannot borrow `z` as mutable more than once at a time
+  --> $DIR/imply_bounds_from_bounds_param.rs:36:27
+   |
+LL |     let mut thing = test(&mut z);
+   |                          ------ first mutable borrow occurs here
+LL |     let mut thing2 = test(&mut z);
+   |                           ^^^^^^ second mutable borrow occurs here
+LL |     thing.plus_one();
+   |     ----- first borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/imply_bounds_from_bounds_param.rs:35:21
+   |
+LL |     let mut thing = test(&mut z);
+   |                     ^^^^^^^^^^^^
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<> {
+   |                                             +++++++
+
+error[E0502]: cannot borrow `z` as immutable because it is also borrowed as mutable
+  --> $DIR/imply_bounds_from_bounds_param.rs:38:5
+   |
+LL |     let mut thing = test(&mut z);
+   |                          ------ mutable borrow occurs here
+...
+LL |     assert_eq!(z, 43);
+   |     ^^^^^^^^^^^^^^^^^ immutable borrow occurs here
+...
+LL |     thing.plus_one();
+   |     ----- mutable borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/imply_bounds_from_bounds_param.rs:35:21
+   |
+LL |     let mut thing = test(&mut z);
+   |                     ^^^^^^^^^^^^
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<> {
+   |                                             +++++++
+
+error[E0502]: cannot borrow `z` as immutable because it is also borrowed as mutable
+  --> $DIR/imply_bounds_from_bounds_param.rs:40:5
+   |
+LL |     let mut thing = test(&mut z);
+   |                          ------ mutable borrow occurs here
+...
+LL |     assert_eq!(z, 44);
+   |     ^^^^^^^^^^^^^^^^^ immutable borrow occurs here
+LL |     thing.plus_one();
+   |     ----- mutable borrow later used here
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/imply_bounds_from_bounds_param.rs:35:21
+   |
+LL |     let mut thing = test(&mut z);
+   |                     ^^^^^^^^^^^^
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<> {
+   |                                             +++++++
+
+error[E0502]: cannot borrow `z` as immutable because it is also borrowed as mutable
+  --> $DIR/imply_bounds_from_bounds_param.rs:42:5
+   |
+LL |     let mut thing = test(&mut z);
+   |                          ------ mutable borrow occurs here
+...
+LL |     assert_eq!(z, 45);
+   |     ^^^^^^^^^^^^^^^^^ immutable borrow occurs here
+LL | }
+   | - mutable borrow might be used here, when `thing` is dropped and runs the destructor for type `impl PlusOne`
+   |
+note: this call may capture more lifetimes than intended, because Rust 2024 has adjusted the `impl Trait` lifetime capture rules
+  --> $DIR/imply_bounds_from_bounds_param.rs:35:21
+   |
+LL |     let mut thing = test(&mut z);
+   |                     ^^^^^^^^^^^^
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the precise capturing `use<...>` syntax to make the captures explicit
+   |
+LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne + use<> {
+   |                                             +++++++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0499, E0502.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs
index 5d5645077c2..672019ba73a 100644
--- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs
+++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.rs
@@ -1,3 +1,6 @@
+//@revisions: edition2015 edition2024
+//@[edition2015] edition:2015
+//@[edition2024] edition:2024
 #![feature(impl_trait_in_assoc_type)]
 
 trait Callable {
@@ -24,17 +27,17 @@ impl<T: PlusOne> Callable for T {
 
 fn test<'a>(y: &'a mut i32) -> impl PlusOne {
     <&'a mut i32 as Callable>::call(y)
-    //~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
+    //[edition2015]~^ ERROR hidden type for `impl PlusOne` captures lifetime that does not appear in bounds
 }
 
 fn main() {
     let mut z = 42;
     let mut thing = test(&mut z);
-    let mut thing2 = test(&mut z);
+    let mut thing2 = test(&mut z); //[edition2024]~ ERROR cannot borrow `z` as mutable more than once
     thing.plus_one();
-    assert_eq!(z, 43);
+    assert_eq!(z, 43); //[edition2024]~ ERROR cannot borrow `z` as immutable
     thing2.plus_one();
-    assert_eq!(z, 44);
+    assert_eq!(z, 44); //[edition2024]~ ERROR cannot borrow `z` as immutable
     thing.plus_one();
-    assert_eq!(z, 45);
+    assert_eq!(z, 45); //[edition2024]~ ERROR cannot borrow `z` as immutable
 }