Rollup merge of #163170 - mejrs:hir_imports, r=oli-obk

Update deprecated rustc_hir imports

Followup to https://github.com/rust-lang/rust/pull/160336

That's ~half of them, I'm not doing it all in one go to reduce conflicts.
diff --git a/Cargo.lock b/Cargo.lock
index 471734d..a1a43f4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -287,12 +287,6 @@
 
 [[package]]
 name = "base64"
-version = "0.21.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
-
-[[package]]
-name = "base64"
 version = "0.22.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
@@ -2135,7 +2129,7 @@
 checksum = "8bdc5a74b0feeb5e6a1dc2dd08c34280a61e37668d10a6a3b27ad69d0fb9ce2e"
 dependencies = [
  "aho-corasick",
- "base64 0.22.1",
+ "base64",
  "bstr",
  "jaq-core",
  "jiff",
@@ -5055,7 +5049,6 @@
 dependencies = [
  "arrayvec",
  "askama",
- "base64 0.21.7",
  "expect-test",
  "indexmap",
  "itertools",
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index fed7fdd..00f28ec 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -156,7 +156,7 @@ pub(crate) fn compute_regions<'tcx>(
             &universal_region_relations.universal_regions,
             body,
             move_data,
-            &location_map,
+            Rc::clone(&location_map),
             borrow_set,
         );
     }
diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs
index 44a2170..5855f60 100644
--- a/compiler/rustc_borrowck/src/polonius/constraints.rs
+++ b/compiler/rustc_borrowck/src/polonius/constraints.rs
@@ -1,3 +1,5 @@
+use std::rc::Rc;
+
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_index::IndexVec;
 use rustc_middle::mir::{Body, Location};
@@ -8,7 +10,7 @@
 use crate::constraints::OutlivesConstraint;
 use crate::dataflow::BorrowIndex;
 use crate::polonius::ConstraintDirection;
-use crate::polonius::liveness::RegionLiveness;
+use crate::polonius::liveness::LivenessSource;
 use crate::type_check::Locations;
 
 /// A localized outlives constraint reifies the CFG location where the outlives constraint holds,
@@ -38,6 +40,8 @@ pub(super) struct LocalizedNode {
 /// The localized constraint graph indexes the physical and logical edges to lazily compute a given
 /// node's successors during traversal.
 pub(super) struct LocalizedConstraintGraph {
+    location_map: Rc<DenseLocationMap>,
+
     /// The actual, physical, edges we have recorded for a given node. We localize them on-demand
     /// when traversing from the node to the successor region.
     edges: FxHashMap<LocalizedNode, FxIndexSet<RegionVid>>,
@@ -48,16 +52,10 @@ pub(super) struct LocalizedConstraintGraph {
     logical_edges: IndexVec<RegionVid, FxIndexSet<RegionVid>>,
 }
 
-/// The source of liveness information for a given region.
-pub(super) trait LivenessSource<'loc> {
-    fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_>;
-    fn location_map(&self) -> &'loc DenseLocationMap;
-}
-
 /// The visitor interface when traversing a `LocalizedConstraintGraph`.
 pub(super) trait LocalizedConstraintGraphVisitor {
     /// Callback called when traversing a given `loan` encounters a localized `node` it hasn't
-    /// visited before.
+    /// visited before, and whether its region is live at that point.
     fn on_node_traversed(&mut self, _loan: BorrowIndex, _node: LocalizedNode, _is_live: bool) {}
 
     /// Callback called when discovering a new `successor` node for the `current_node`.
@@ -68,7 +66,7 @@ fn on_successor_discovered(&mut self, _current_node: LocalizedNode, _successor:
 impl LocalizedConstraintGraph {
     /// Traverses the constraints and returns the indexed graph of edges per node.
     pub(super) fn new<'tcx>(
-        location_map: &DenseLocationMap,
+        location_map: Rc<DenseLocationMap>,
         outlives_constraints: impl Iterator<Item = OutlivesConstraint<'tcx>>,
     ) -> Self {
         let mut edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default();
@@ -92,23 +90,21 @@ pub(super) fn new<'tcx>(
             }
         }
 
-        LocalizedConstraintGraph { edges, logical_edges }
+        LocalizedConstraintGraph { location_map, edges, logical_edges }
     }
 
     /// Traverses the localized constraint graph per-loan, and notifies the `visitor` of discovered
     /// nodes and successors.
-    pub(super) fn traverse<'tcx, 'loc>(
+    pub(super) fn traverse<'tcx>(
         &self,
         body: &Body<'tcx>,
         borrow_set: &BorrowSet<'tcx>,
-        liveness_source: &mut impl LivenessSource<'loc>,
+        liveness_source: &mut impl LivenessSource,
         visitor: &mut impl LocalizedConstraintGraphVisitor,
     ) {
         let mut visited = FxHashSet::default();
         let mut stack = Vec::new();
 
-        let location_map = liveness_source.location_map();
-
         // Compute reachability per loan by traversing each loan's subgraph starting from where it
         // is introduced.
         for (loan_idx, loan) in borrow_set.iter_enumerated() {
@@ -117,7 +113,7 @@ pub(super) fn traverse<'tcx, 'loc>(
 
             let start_node = LocalizedNode {
                 region: loan.region,
-                point: location_map.point_from_location(loan.reserve_location),
+                point: self.location_map.point_from_location(loan.reserve_location),
             };
             visited.insert(start_node);
             stack.push(start_node);
@@ -125,7 +121,7 @@ pub(super) fn traverse<'tcx, 'loc>(
             while let Some(node) = stack.pop() {
                 let liveness = liveness_source.liveness_for_region(node.region);
                 // We've reached a node we haven't visited before.
-                let location = location_map.to_location(node.point);
+                let location = self.location_map.to_location(node.point);
                 visitor.on_node_traversed(loan_idx, node, liveness.is_live_at(node.point));
 
                 // When we find a _new_ successor, we'd like to
@@ -181,7 +177,7 @@ pub(super) fn traverse<'tcx, 'loc>(
                         for successor_block in body[location.block].terminator().successors() {
                             let next_location =
                                 Location { block: successor_block, statement_index: 0 };
-                            let next_point = location_map.point_from_location(next_location);
+                            let next_point = self.location_map.point_from_location(next_location);
                             if liveness.is_live_at(next_point) {
                                 successor_found(LocalizedNode {
                                     region: node.region,
@@ -224,7 +220,7 @@ pub(super) fn traverse<'tcx, 'loc>(
                                 statement_index: body[pred_block].statements.len(),
                             };
                             let previous_point =
-                                location_map.point_from_location(previous_location);
+                                self.location_map.point_from_location(previous_location);
                             successor_found(LocalizedNode {
                                 region: node.region,
                                 point: previous_point,
diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs
index fff3169..fb4c6fb 100644
--- a/compiler/rustc_borrowck/src/polonius/dump.rs
+++ b/compiler/rustc_borrowck/src/polonius/dump.rs
@@ -5,7 +5,7 @@
 use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions};
 use rustc_middle::mir::{Body, Location};
 use rustc_middle::ty::{RegionVid, TyCtxt};
-use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
+use rustc_mir_dataflow::points::PointIndex;
 use rustc_session::config::MirIncludeSpans;
 
 use crate::borrow_set::BorrowSet;
@@ -32,7 +32,7 @@ struct CachedLivenessSource<'a, 'tcx> {
     liveness: &'a LivenessValues,
 }
 
-impl<'a, 'tcx> LivenessSource<'a> for CachedLivenessSource<'a, 'tcx> {
+impl<'a, 'tcx> LivenessSource for CachedLivenessSource<'a, 'tcx> {
     fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> {
         RegionLiveness::new(
             region,
@@ -41,9 +41,6 @@ fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> {
             self.liveness.points(),
         )
     }
-    fn location_map(&self) -> &'a DenseLocationMap {
-        self.liveness.location_map()
-    }
 }
 
 /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information.
diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs
index 0bef063..9cbaa2d 100644
--- a/compiler/rustc_borrowck/src/polonius/liveness.rs
+++ b/compiler/rustc_borrowck/src/polonius/liveness.rs
@@ -1,84 +1,17 @@
 use rustc_index::IndexVec;
 use rustc_index::interval::{IntervalSet, SparseIntervalMatrix};
 use rustc_middle::mir::Local;
-use rustc_middle::ty::{GenericArg, RegionVid, Ty};
+use rustc_middle::ty::{GenericArg, RegionVid, Ty, TyCtxt};
 use rustc_mir_dataflow::points::PointIndex;
 
-use crate::BorrowckInferCtxt;
 use crate::polonius::{ConstraintDirection, LiveRegionVariances};
 use crate::region_infer::values::LivenessValues;
 use crate::type_check::liveness::LivenessComputation;
 use crate::universal_regions::UniversalRegions;
 
-#[derive(Default)]
-pub(crate) struct DeferredLocals<'tcx> {
-    /// For each region, the local whose liveness is deferred.
-    ///
-    /// Importantly, because of MIR renumbering, this will always be a 1:1 relationship.
-    by_region: IndexVec<RegionVid, Option<Local>>,
-
-    /// For each deferred local, gets the regions contained within that local at use and drop.
-    drop_args_by_local: IndexVec<Local, Option<Vec<GenericArg<'tcx>>>>,
-}
-
-impl<'tcx> DeferredLocals<'tcx> {
-    pub(crate) fn defer_local(
-        &mut self,
-        infcx: &BorrowckInferCtxt<'tcx>,
-        universal_regions: &UniversalRegions<'tcx>,
-        local: Local,
-        local_ty: Ty<'tcx>,
-        dropck_kinds: &[GenericArg<'tcx>],
-    ) {
-        let tcx = infcx.tcx;
-
-        // We already have drop data for this local, because we need to register
-        // region constraints eagerly. So, we'll store this so we don't need to
-        // recompute.
-        self.drop_args_by_local.insert(local, dropck_kinds.to_vec());
-
-        // Then, we want to map all the regions contained within this local to
-        // the local itself. Later, when asked for liveness of a given region,
-        // we can trace liveness for the local containing it.
-        let by_region = &mut self.by_region;
-        tcx.for_each_free_region(&local_ty, |region| {
-            // See note in [`VarianceExtractor::record_variance`].
-            if region.is_bound() || region.is_erased() {
-                return;
-            }
-            let vid = universal_regions.to_region_vid(region);
-            // Because of MIR renumbering, we should always have a 1:1 mapping
-            // between a region and a local.
-            let previous = by_region.insert(vid, local);
-            debug_assert!(
-                previous.is_none(),
-                "{vid:?} is in the type of both {previous:?} and {local:?}, but \
-                MIR renumbering should ensure that this is impossible.",
-            );
-        });
-    }
-
-    /// For a given region, compute the liveness for the local containing it, if if is deferred.
-    #[inline]
-    pub(crate) fn compute_deferred_local(
-        &mut self,
-        region: RegionVid,
-        universal_regions: &UniversalRegions<'tcx>,
-        liveness: &mut LivenessValues,
-        live_region_variances: &mut LiveRegionVariances,
-        comp: &mut LivenessComputation<'_, 'tcx>,
-    ) {
-        let Some(local) = self.by_region.remove(region) else {
-            return;
-        };
-        let Some(drop_args) = self.drop_args_by_local.remove(local) else {
-            return;
-        };
-
-        comp.compute(local, universal_regions, Some(live_region_variances), liveness, || {
-            &drop_args
-        });
-    }
+/// The source of liveness information for a given region.
+pub(super) trait LivenessSource {
+    fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_>;
 }
 
 /// For a given region, the relevant liveness and variance information.
@@ -122,3 +55,74 @@ pub(super) fn is_live_at(&self, point: PointIndex) -> bool {
         self.live_points.map_or(false, |points| points.contains(point))
     }
 }
+
+/// The data needed to compute region liveness on-demand while traversing the localized outlives
+/// constraint graph to compute loan liveness.
+#[derive(Default)]
+pub(crate) struct DeferredLocals<'tcx> {
+    /// For each region, the local whose liveness is deferred.
+    ///
+    /// Importantly, because of MIR renumbering, this will always be a 1:1 relationship.
+    by_region: IndexVec<RegionVid, Option<Local>>,
+
+    /// For each deferred local, gets the regions contained within that local at use and drop.
+    drop_args_by_local: IndexVec<Local, Option<Vec<GenericArg<'tcx>>>>,
+}
+
+impl<'tcx> DeferredLocals<'tcx> {
+    pub(crate) fn defer_local(
+        &mut self,
+        tcx: TyCtxt<'tcx>,
+        universal_regions: &UniversalRegions<'tcx>,
+        local: Local,
+        local_ty: Ty<'tcx>,
+        dropck_kinds: &[GenericArg<'tcx>],
+    ) {
+        // We already have drop data for this local, because we need to register
+        // region constraints eagerly. So, we'll store this so we don't need to
+        // recompute.
+        self.drop_args_by_local.insert(local, dropck_kinds.to_vec());
+
+        // Then, we want to map all the regions contained within this local to
+        // the local itself. Later, when asked for liveness of a given region,
+        // we can trace liveness for the local containing it.
+        let by_region = &mut self.by_region;
+        tcx.for_each_free_region(&local_ty, |region| {
+            // See note in `VarianceExtractor::record_variance`.
+            if region.is_bound() || region.is_erased() {
+                return;
+            }
+            let vid = universal_regions.to_region_vid(region);
+            // Because of MIR renumbering, we should always have a 1:1 mapping
+            // between a region and a local.
+            let previous = by_region.insert(vid, local);
+            debug_assert!(
+                previous.is_none(),
+                "{vid:?} is in the type of both {previous:?} and {local:?}, but \
+                MIR renumbering should ensure that this is impossible.",
+            );
+        });
+    }
+
+    /// For a given region, compute the liveness for the local containing it, if it is deferred.
+    #[inline]
+    pub(crate) fn compute_deferred_local(
+        &mut self,
+        region: RegionVid,
+        universal_regions: &UniversalRegions<'tcx>,
+        liveness: &mut LivenessValues,
+        live_region_variances: &mut LiveRegionVariances,
+        comp: &mut LivenessComputation<'_, 'tcx>,
+    ) {
+        let Some(local) = self.by_region.remove(region) else {
+            return;
+        };
+        let Some(drop_args) = self.drop_args_by_local.remove(local) else {
+            return;
+        };
+
+        comp.compute(local, universal_regions, Some(live_region_variances), liveness, || {
+            &drop_args
+        });
+    }
+}
diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs
index 654c750..73133b6 100644
--- a/compiler/rustc_borrowck/src/polonius/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/mod.rs
@@ -39,6 +39,8 @@
 mod liveness;
 mod liveness_constraints;
 
+use std::rc::Rc;
+
 use rustc_data_structures::fx::FxHashSet;
 use rustc_index::IndexVec;
 use rustc_index::bit_set::DenseBitSet;
@@ -53,7 +55,7 @@
 use crate::constraints::OutlivesConstraint;
 use crate::dataflow::BorrowIndex;
 pub(crate) use crate::polonius::liveness::DeferredLocals;
-use crate::polonius::liveness::RegionLiveness;
+use crate::polonius::liveness::{LivenessSource, RegionLiveness};
 use crate::region_infer::values::LivenessValues;
 use crate::type_check::liveness::{LivenessComputation, LocalUseMap};
 use crate::universal_regions::UniversalRegions;
@@ -141,7 +143,7 @@ pub(crate) fn compute_loan_liveness(
         universal_regions: &UniversalRegions<'tcx>,
         body: &Body<'tcx>,
         move_data: &MoveData<'tcx>,
-        location_map: &DenseLocationMap,
+        location_map: Rc<DenseLocationMap>,
         borrow_set: &BorrowSet<'tcx>,
     ) {
         // We don't need to prepare the graph (index NLL constraints, etc.) if we have no loans to
@@ -151,7 +153,7 @@ pub(crate) fn compute_loan_liveness(
             // on the lazy localized constraint graph to trace the liveness of loans, for the next
             // step in the chain (the NLL loan scope and active loans computations).
             let graph =
-                LocalizedConstraintGraph::new(liveness.location_map(), outlives_constraints);
+                LocalizedConstraintGraph::new(Rc::clone(&location_map), outlives_constraints);
 
             let local_use_map = self
                 .local_use_map
@@ -161,7 +163,7 @@ pub(crate) fn compute_loan_liveness(
                 std::mem::take(&mut self.deferred_locals_for_liveness);
             let mut live_loans = LiveLoans::new(location_map.num_points(), borrow_set.len());
             let comp =
-                LivenessComputation::new(infcx, body, location_map, move_data, &local_use_map);
+                LivenessComputation::new(infcx, body, &location_map, move_data, &local_use_map);
             let mut liveness_source = DeferredLivenessSource {
                 liveness,
                 live_region_variances: &mut self.live_region_variances,
@@ -190,7 +192,7 @@ struct DeferredLivenessSource<'a, 'tcx> {
     comp: LivenessComputation<'a, 'tcx>,
 }
 
-impl<'a> LivenessSource<'a> for DeferredLivenessSource<'a, '_> {
+impl<'a> LivenessSource for DeferredLivenessSource<'a, '_> {
     #[inline]
     fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> {
         self.deferred_locals_for_liveness.compute_deferred_local(
@@ -208,10 +210,6 @@ fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> {
             self.liveness.points(),
         )
     }
-
-    fn location_map(&self) -> &'a DenseLocationMap {
-        self.comp.location_map
-    }
 }
 
 /// Visitor to record loan liveness when traversing the localized constraint graph.
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 6e4e940..800f722 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -201,10 +201,6 @@ pub(crate) fn location_from_point(&self, point: PointIndex) -> Location {
         self.location_map.to_location(point)
     }
 
-    pub(crate) fn location_map(&self) -> &Rc<DenseLocationMap> {
-        &self.location_map
-    }
-
     /// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active
     /// loans dataflow computations.
     pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) {
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
index 9c39645..0bb6ecb 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
@@ -82,7 +82,7 @@ fn next(&mut self) -> Option<AppearanceIndex> {
 
 impl LocalUseMap {
     pub(crate) fn build(
-        live_locals: &[Local],
+        mut live_locals: impl Iterator<Item = Local>,
         location_map: &DenseLocationMap,
         body: &Body<'_>,
     ) -> Self {
@@ -94,13 +94,11 @@ pub(crate) fn build(
             appearances: IndexVec::new(),
         };
 
-        if live_locals.is_empty() {
-            return local_use_map;
-        }
+        let Some(head) = live_locals.next() else { return local_use_map };
 
-        let mut locals_with_use_data: DenseBitSet<Local> =
-            DenseBitSet::new_empty(body.local_decls.len());
-        live_locals.iter().for_each(|&local| {
+        let mut locals_with_use_data = DenseBitSet::new_empty(body.local_decls.len());
+        locals_with_use_data.insert(head);
+        live_locals.for_each(|local| {
             locals_with_use_data.insert(local);
         });
 
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index 6b9eae7..905547c 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -78,13 +78,12 @@ pub(super) fn generate<'tcx>(
             break 'deferred FxIndexSet::default();
         }
 
-        let free_regions: FxHashSet<RegionVid> =
-            typeck.universal_regions.universal_regions_iter().collect();
+        let free_regions = typeck.universal_regions.universal_regions_iter().collect();
         let (polonius_relevant, _) =
             compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body);
 
-        let boring: FxHashSet<Local> = boring_locals.iter().copied().collect();
-        let deferred: FxIndexSet<Local> =
+        let boring: FxHashSet<_> = boring_locals.iter().copied().collect();
+        let deferred =
             polonius_relevant.into_iter().filter(|local| boring.contains(local)).collect();
         typeck.polonius_context.as_mut().unwrap().boring_nll_locals = boring;
         deferred
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 0811b66..21b2e0f 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -52,8 +52,8 @@ pub(super) fn trace<'tcx>(
 
     // The use map must also cover the deferred locals: their liveness is computed later, from
     // this same map, when the loan liveness traversal first reaches one of their regions.
-    let use_map_locals: Vec<Local> = relevant_live_locals.iter().chain(deferred).copied().collect();
-    let local_use_map = LocalUseMap::build(&use_map_locals, location_map, typeck.body);
+    let use_map_locals = relevant_live_locals.iter().chain(deferred).copied();
+    let local_use_map = LocalUseMap::build(use_map_locals, location_map, typeck.body);
     let comp = LivenessComputation::new(
         typeck.infcx,
         typeck.body,
@@ -221,7 +221,7 @@ fn dropck_boring_local(
         // are *no* drops (which is relatively cheap).
         if deferred.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() {
             deferred_locals.defer_local(
-                typeck.infcx,
+                typeck.infcx.tcx,
                 typeck.universal_regions,
                 local,
                 local_ty,
@@ -265,7 +265,7 @@ fn dropck_boring_local(
 
         // Finally, we mark that this local is deferred, including the drop kinds.
         deferred_locals.defer_local(
-            typeck.infcx,
+            typeck.infcx.tcx,
             typeck.universal_regions,
             local,
             local_ty,
@@ -279,8 +279,8 @@ fn dropck_boring_local(
     /// the function body only at certain nodes in the CFG.
     fn record_legacy_polonius_drop_facts(
         &mut self,
-        relevant_live_locals: &[Local],
-        deferred: &FxIndexSet<Local>,
+        nll_relevant_locals: &[Local],
+        deferred_polonius_relevant_locals: &FxIndexSet<Local>,
     ) {
         // This is *all wonky* because this used to call a shared
         // `add_drop_live_facts_for` function that was also used for regular
@@ -292,16 +292,15 @@ fn record_legacy_polonius_drop_facts(
         // `add_drop_live_facts_for()` that make sense.
         let Some(facts) = self.typeck.polonius_facts.as_ref() else { return };
         let facts_to_add: Vec<_> = {
-            let relevant_live_locals: FxIndexSet<_> =
-                relevant_live_locals.iter().copied().collect();
+            let nll_relevant_locals: FxIndexSet<_> = nll_relevant_locals.iter().copied().collect();
 
             facts
                 .var_dropped_at
                 .iter()
                 .filter_map(|&(local, location_index)| {
                     let local_ty = self.comp.body.local_decls[local].ty;
-                    if relevant_live_locals.contains(&local)
-                        || deferred.contains(&local)
+                    if nll_relevant_locals.contains(&local)
+                        || deferred_polonius_relevant_locals.contains(&local)
                         || !local_ty.has_free_regions()
                     {
                         return None;
@@ -394,7 +393,7 @@ pub(crate) fn compute<'drop_data>(
         universal_regions: &UniversalRegions<'tcx>,
         live_region_variances: Option<&mut LiveRegionVariances>,
         liveness_constraints: &mut LivenessValues,
-        get_drop_args: impl FnOnce() -> &'drop_data Vec<GenericArg<'tcx>>,
+        get_drop_args: impl FnOnce() -> &'drop_data [GenericArg<'tcx>],
     ) where
         'tcx: 'drop_data,
     {
@@ -431,17 +430,16 @@ pub(crate) fn compute<'drop_data>(
         if !self.drop_live_at.is_empty() {
             let drop_data = get_drop_args();
 
-            // `drop_live_at` is using a DenseBitSet, but `make_all_regions_live`
-            // expects an IntervalSet. We thus convert between those two here.
-            // Using a `DenseBitSet` has better performance, but storing liveness
-            // as a dense matrix has worse performance. There's probably room here
-            // for some cleanup, but this works for now.
-            let mut drop_live_at: IntervalSet<PointIndex> =
-                IntervalSet::new(self.drop_live_at.domain_size());
-            for item in self.drop_live_at.iter() {
+            // `compute_drop_live_points_for` computes `drop_live_at` as a `DenseBitSet`, but
+            // `make_all_regions_live` expects an `IntervalSet`. We thus convert between those two
+            // here. Using a `DenseBitSet` has better performance, but storing liveness as a dense
+            // matrix has worse performance. There's probably room here for some cleanup, but this
+            // works for now.
+            let mut drop_live_at = IntervalSet::new(self.drop_live_at.domain_size());
+            for point in self.drop_live_at.iter() {
                 // We iterate the `drop_live_at` set from smallest to largest values, so
                 // we can use append to add things to the interval set at the end.
-                drop_live_at.append(item);
+                drop_live_at.append(point);
             }
 
             for &kind in drop_data {
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 96b39f0..9774165 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -15,8 +15,11 @@
 /// A meta-variable expression, for expansions based on properties of meta-variables.
 #[derive(Debug, PartialEq, Encodable, Decodable)]
 pub(crate) enum MetaVarExpr {
-    /// Unification of two or more identifiers.
-    Concat(Box<[MetaVarExprConcatElem]>),
+    /// Unification of two or more identifiers/literals/metavariables into an identifier.
+    ConcatIdent(Box<[MetaVarExprConcatElem]>),
+
+    /// Unification of two or more identifiers/literals/metavariables into a string literal.
+    ConcatStr(Box<[MetaVarExprConcatElem]>),
 
     /// The number of repetitions of an identifier.
     Count(Ident, usize),
@@ -73,7 +76,12 @@ pub(crate) fn parse<'psess>(
 
         let mut iter = args.iter();
         let rslt = match ident.name {
-            sym::concat => parse_concat(&mut iter, psess, outer_span, ident.span)?,
+            sym::concat => {
+                MetaVarExpr::ConcatIdent(parse_concat(&mut iter, psess, outer_span, ident.span)?)
+            }
+            sym::concat_str => {
+                MetaVarExpr::ConcatStr(parse_concat(&mut iter, psess, outer_span, ident.span)?)
+            }
             sym::count => parse_count(&mut iter, psess, ident.span)?,
             sym::ignore => {
                 eat_dollar(&mut iter, psess, ident.span)?;
@@ -95,7 +103,7 @@ pub(crate) fn parse<'psess>(
 
     pub(crate) fn for_each_metavar<A>(&self, mut aux: A, mut cb: impl FnMut(A, &Ident) -> A) -> A {
         match self {
-            MetaVarExpr::Concat(elems) => {
+            MetaVarExpr::ConcatIdent(elems) | MetaVarExpr::ConcatStr(elems) => {
                 for elem in elems {
                     if let MetaVarExprConcatElem::Var(ident) = elem {
                         aux = cb(aux, ident)
@@ -175,7 +183,7 @@ fn parse_concat<'psess>(
     psess: &'psess ParseSess,
     outer_span: Span,
     expr_ident_span: Span,
-) -> PResult<'psess, MetaVarExpr> {
+) -> PResult<'psess, Box<[MetaVarExprConcatElem]>> {
     let mut result = Vec::new();
     loop {
         let is_var = try_eat_dollar(iter);
@@ -210,7 +218,7 @@ fn parse_concat<'psess>(
             .dcx()
             .struct_span_err(expr_ident_span, "`concat` must have at least two elements"));
     }
-    Ok(MetaVarExpr::Concat(result.into()))
+    Ok(result.into())
 }
 
 /// Parse a meta-variable `count` expression: `count(ident[, depth])`
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index aed69c9..ff1607c 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -7,7 +7,7 @@
 use rustc_session::Session;
 use rustc_session::diagnostics::feature_err;
 use rustc_span::edition::Edition;
-use rustc_span::{Ident, Span, kw, sym};
+use rustc_span::{Ident, Span, Symbol, kw, sym};
 
 use crate::diagnostics;
 use crate::mbe::macro_parser::count_metavar_decls;
@@ -204,9 +204,14 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, sp
     }
 }
 
-fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Session, span: Span) {
+fn maybe_emit_macro_metavar_expr_concat_feature(
+    features: &Features,
+    sess: &Session,
+    span: Span,
+    what: Symbol,
+) {
     if !features.macro_metavar_expr_concat() {
-        let msg = "the `concat` meta-variable expression is unstable";
+        let msg = format!("the `{what}` meta-variable expression is unstable");
         feature_err(sess, sym::macro_metavar_expr_concat, span, msg).emit();
     }
 }
@@ -278,11 +283,19 @@ fn parse_tree<'a>(
                                         return TokenTree::token(token::Dollar, dollar_span);
                                     }
                                     Ok(elem) => {
-                                        if let MetaVarExpr::Concat(_) = elem {
+                                        if matches!(elem, MetaVarExpr::ConcatIdent(_)) {
                                             maybe_emit_macro_metavar_expr_concat_feature(
                                                 features,
                                                 sess,
                                                 delim_span.entire(),
+                                                sym::concat,
+                                            );
+                                        } else if matches!(elem, MetaVarExpr::ConcatStr(_)) {
+                                            maybe_emit_macro_metavar_expr_concat_feature(
+                                                features,
+                                                sess,
+                                                delim_span.entire(),
+                                                sym::concat_str,
                                             );
                                         } else {
                                             maybe_emit_macro_metavar_expr_feature(
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index c258d9e..8d03697 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -597,7 +597,8 @@ fn transcribe_metavar_expr<'tx>(
 ) -> PResult<'tx, ()> {
     let dcx = tscx.psess.dcx();
     let tt = match *expr {
-        MetaVarExpr::Concat(ref elements) => metavar_expr_concat(tscx, dspan, elements)?,
+        MetaVarExpr::ConcatIdent(ref elements) => metavar_expr_concat_ident(tscx, dspan, elements)?,
+        MetaVarExpr::ConcatStr(ref elements) => metavar_expr_concat_str(tscx, dspan, elements)?,
         MetaVarExpr::Count(original_ident, depth) => {
             let matched = matched_from_ident(dcx, original_ident, tscx.interp)?;
             let count = count_repetitions(dcx, depth, matched, &tscx.repeats, &dspan)?;
@@ -635,11 +636,52 @@ fn transcribe_metavar_expr<'tx>(
 }
 
 /// Handle the `${concat(...)}` metavariable expression.
-fn metavar_expr_concat<'tx>(
+fn metavar_expr_concat_ident<'tx>(
     tscx: &mut TranscrCtx<'tx, '_>,
     dspan: DelimSpan,
     elements: &[MetaVarExprConcatElem],
 ) -> PResult<'tx, TokenTree> {
+    let (symbol, concatenated_span) = metavar_expr_concat(tscx, dspan, elements)?;
+    if !rustc_lexer::is_ident(symbol.as_str()) {
+        return Err(tscx.psess.dcx().create_err(ConcatInvalidIdent {
+            span: concatenated_span,
+            reason: InvalidIdentReason::new(symbol),
+        }));
+    }
+    tscx.psess.symbol_gallery.insert(symbol, concatenated_span);
+
+    // The current implementation marks the span as coming from the macro regardless of
+    // contexts of the concatenated identifiers but this behavior may change in the
+    // future.
+    Ok(TokenTree::Token(
+        Token::from_ast_ident(Ident::new(symbol, concatenated_span)),
+        Spacing::Alone,
+    ))
+}
+
+/// Handle the `${concat_str(...)}` metavariable expression.
+fn metavar_expr_concat_str<'tx>(
+    tscx: &mut TranscrCtx<'tx, '_>,
+    dspan: DelimSpan,
+    elements: &[MetaVarExprConcatElem],
+) -> PResult<'tx, TokenTree> {
+    let (symbol, concatenated_span) = metavar_expr_concat(tscx, dspan, elements)?;
+
+    // The current implementation marks the span as coming from the macro regardless of
+    // contexts of the concatenated identifiers but this behavior may change in the
+    // future.
+    Ok(TokenTree::Token(
+        Token::new(TokenKind::lit(LitKind::Str, symbol, None), concatenated_span),
+        Spacing::Alone,
+    ))
+}
+
+/// Shared logic for concat/concat_str metavariable expressions
+fn metavar_expr_concat<'tx>(
+    tscx: &mut TranscrCtx<'tx, '_>,
+    dspan: DelimSpan,
+    elements: &[MetaVarExprConcatElem],
+) -> PResult<'tx, (Symbol, Span)> {
     let dcx = tscx.psess.dcx();
     let mut concatenated = String::new();
     for element in elements {
@@ -668,21 +710,7 @@ fn metavar_expr_concat<'tx>(
     }
     let symbol = nfc_normalize(&concatenated);
     let concatenated_span = tscx.visited_dspan(dspan);
-    if !rustc_lexer::is_ident(symbol.as_str()) {
-        return Err(dcx.create_err(ConcatInvalidIdent {
-            span: concatenated_span,
-            reason: InvalidIdentReason::new(symbol),
-        }));
-    }
-    tscx.psess.symbol_gallery.insert(symbol, concatenated_span);
-
-    // The current implementation marks the span as coming from the macro regardless of
-    // contexts of the concatenated identifiers but this behavior may change in the
-    // future.
-    Ok(TokenTree::Token(
-        Token::from_ast_ident(Ident::new(symbol, concatenated_span)),
-        Spacing::Alone,
-    ))
+    Ok((symbol, concatenated_span))
 }
 
 /// Store the metavariable span for this original span into a side table.
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 78f3929..450b98f 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -484,9 +484,8 @@ fn main() {
     let llvm_static_stdcpp = tracked_env_var_os("LLVM_STATIC_STDCPP");
     let llvm_use_libcxx = tracked_env_var_os("LLVM_USE_LIBCXX");
 
-    let stdcppname = if target.contains("openbsd") {
-        if target.contains("sparc64") { "estdc++" } else { "c++" }
-    } else if target.contains("darwin")
+    let stdcppname = if target.contains("openbsd")
+        || target.contains("darwin")
         || target.contains("freebsd")
         || target.contains("windows-gnullvm")
         || target.contains("aix")
diff --git a/compiler/rustc_mir_transform/src/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs
index 0ae39b1..84359e7 100644
--- a/compiler/rustc_mir_transform/src/coroutine/layout.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs
@@ -253,6 +253,7 @@ fn compute_storage_conflicts<'mir, 'tcx>(
         saved_locals,
         local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()),
         eligible_storage_live: DenseBitSet::new_empty(body.local_decls.len()),
+        last_recorded_storage_live: DenseBitSet::new_empty(body.local_decls.len()),
     };
 
     // Filter out:
@@ -297,6 +298,10 @@ struct StorageConflictVisitor<'a> {
     local_conflicts: BitMatrix<Local, Local>,
     // We keep this bitset as a buffer to avoid reallocating memory.
     eligible_storage_live: DenseBitSet<Local>,
+    // The last live set whose conflicts were recorded. This is just a fast path:
+    // if the current live set is a subset, we can skip updating the conflict matrix
+    // since its conflicts have already been recorded.
+    last_recorded_storage_live: DenseBitSet<Local>,
 }
 
 impl<'a, 'tcx> ResultsVisitor<'tcx, MaybeRequiresStorage> for StorageConflictVisitor<'a> {
@@ -324,9 +329,14 @@ fn apply_state(&mut self, state: &DenseBitSet<Local>) {
         self.eligible_storage_live.clone_from(state);
         self.eligible_storage_live.intersect(&**self.saved_locals);
 
+        if self.last_recorded_storage_live.superset(&self.eligible_storage_live) {
+            return;
+        }
+
         for local in self.eligible_storage_live.iter() {
             self.local_conflicts.union_row_with(&self.eligible_storage_live, local);
         }
+        std::mem::swap(&mut self.last_recorded_storage_live, &mut self.eligible_storage_live);
     }
 }
 
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 52eaa44..7397d43 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
@@ -460,7 +460,10 @@ pub(super) fn step_kind_for_source(&self, source: GoalSource) -> PathKind {
             // Relating types is always unproductive. If we were to map proof trees to
             // corecursive functions as explained in #136824, relating types never
             // introduces a constructor which could cause the recursion to be guarded.
-            GoalSource::TypeRelating => PathKind::Inductive,
+            //
+            // FIXME(-Znext-solver=coinductive): For now we treat all inductive cycles as
+            // `Unknown`. See the comment in `fn initial_provisional_result`.
+            GoalSource::TypeRelating => PathKind::Unknown,
             // These goal sources are likely unproductive and can be changed to
             // `PathKind::Inductive`. Keeping them as unknown until we're confident
             // about this and have an example where it is necessary.
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 e147a13..ecd175d 100644
--- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
@@ -1,9 +1,9 @@
 use std::convert::Infallible;
 use std::marker::PhantomData;
 
+use rustc_type_ir::Interner;
 use rustc_type_ir::search_graph::{self, PathKind};
 use rustc_type_ir::solve::{AccessedOpaques, Certainty, NoSolution, QueryResult, RerunResultExt};
-use rustc_type_ir::{Interner, MayBeErased, TypingMode};
 
 use crate::canonical::response_no_constraints_raw;
 use crate::delegate::SolverDelegate;
@@ -52,29 +52,21 @@ fn initial_provisional_result(
             PathKind::Unknown | PathKind::ForcedAmbiguity => {
                 response_no_constraints(cx, input, Certainty::overflow(false))
             }
-            // Even though we know these cycles to be unproductive, we still return
-            // overflow during coherence. This is both as we are not 100% confident in
-            // the implementation yet and any incorrect errors would be unsound there.
+            // Even though we know some cycles to be unproductive, we still treat them
+            // as unknown for now. This is both as we are not 100% confident in the
+            // implementation yet and any incorrect errors would be unsound there.
+            //
             // The affected cases are also fairly artificial and not necessarily desirable
             // so keeping this as ambiguity is fine for now.
             //
-            // See `tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs` for an
-            // example where this would matter. We likely should change these cycles to `NoSolution`
-            // even in coherence once this is a bit more settled.
-            PathKind::Inductive => match input.typing_mode.0 {
-                TypingMode::Coherence => {
-                    response_no_constraints(cx, input, Certainty::overflow(false))
-                }
-                TypingMode::Typeck { .. }
-                | TypingMode::PostTypeckUntilBorrowck { .. }
-                | TypingMode::Reflection
-                | TypingMode::PostBorrowck { .. }
-                | TypingMode::PostAnalysis
-                | TypingMode::Codegen
-                | TypingMode::ErasedNotCoherence(MayBeErased) => {
-                    (Err(NoSolution), AccessedOpaques::default())
-                }
-            },
+            // See `tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs` and
+            // `tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs`
+            // for examples where this would matter.
+            //
+            // FIXME(-Znext-solver=coinductive): Long term, we probably do want to
+            // return `NoSolution` here. This should happen separately from the
+            // stabilization of the new solver.
+            PathKind::Inductive => unreachable!(),
         }
     }
 
diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs
index 566b257..b6482aa 100644
--- a/compiler/rustc_parse/src/diagnostics.rs
+++ b/compiler/rustc_parse/src/diagnostics.rs
@@ -4651,3 +4651,15 @@ pub(crate) struct SuggestIntroduceTypeParameter {
     pub span: Span,
     pub parameters: String,
 }
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    "you might have meant to write a diverging block on a refutable `let` statement by using `let-else`
+    for more information, visit <https://doc.rust-lang.org/beta/rust-by-example/flow_control/let_else.html>",
+    code = " else ",
+    applicability = "maybe-incorrect"
+)]
+pub(crate) struct MissingElseInLet {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index a2db5c0..5bc30ae 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -57,7 +57,11 @@ pub fn parse_expr(&mut self) -> PResult<'a, Box<Expr>> {
         self.current_closure.take();
         self.parse_expr_res(Restrictions::empty())
     }
-
+    #[inline]
+    pub fn parse_expr_in_let(&mut self) -> PResult<'a, Box<Expr>> {
+        self.current_closure.take();
+        self.parse_expr_res(Restrictions::IN_LET)
+    }
     /// Parses an expression, forcing tokens to be collected.
     pub fn parse_expr_force_collect(&mut self) -> PResult<'a, Box<Expr>> {
         self.current_closure.take();
@@ -3680,11 +3684,12 @@ pub(super) fn parse_struct_fields(
             Option<ErrorGuaranteed>, /* async blocks are forbidden in Rust 2015 */
         ),
     > {
+        let open_span = self.prev_token.span; //{
         let mut fields = ThinVec::new();
         let mut base = ast::StructRest::None;
         let mut recovered_async = None;
         let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD);
-
+        let in_let = self.restrictions.contains(Restrictions::IN_LET);
         let async_block_err = |e: &mut Diag<'_>, span: Span| {
             crate::diagnostics::AsyncBlockIn2015 { span }.add_to_diag(e);
             crate::diagnostics::HelpUseLatestEdition::new().add_to_diag(e);
@@ -3769,6 +3774,28 @@ pub(super) fn parse_struct_fields(
                         return Err(e);
                     }
 
+                    if in_let {
+                        // Better diagnostic for `foo { return 42; };`
+                        // We've consumed `foo {` already
+                        let mut snapshot = self.create_snapshot_for_diagnostic();
+                        let might_be_stmt = snapshot.token.is_keyword(kw::Return);
+                        snapshot.consume_block(
+                            exp!(OpenBrace),
+                            exp!(CloseBrace),
+                            super::diagnostics::ConsumeClosingDelim::Yes,
+                        ); //consume to the end of the block, including `}`
+
+                        // make sure the block is at the end by eating a `;`,
+                        // we shouldn't report such diagnostic for `let a = foo{return 43;}+bar;`
+                        // also skip the suggestion if the span cross macro boundaries
+                        if might_be_stmt && snapshot.eat(exp!(Semi)) && pth.span.eq_ctxt(open_span)
+                        {
+                            let span = pth.span.between(open_span);
+                            e.subdiagnostic(crate::diagnostics::MissingElseInLet { span });
+                            self.restore_snapshot(snapshot);
+                            return Err(e);
+                        }
+                    }
                     let guar = e.emit_err();
                     if pth == kw::Async {
                         recovered_async = Some(guar);
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 281ca98..50ded81 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -125,6 +125,9 @@ struct Restrictions: u8 {
         /// expression, but halts parsing the expression when reaching certain
         /// tokens like `=`.
         const IS_PAT            = 1 << 5;
+        /// Used to detect a missing `else` in a let statement.
+        /// e.g. let Some(foo) = bar{return;};
+        const IN_LET            = 1 << 6;
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index a082ea6..d59ef93 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -3,14 +3,13 @@
 use std::ops::Bound;
 
 use ast::Label;
-use rustc_ast as ast;
 use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
 use rustc_ast::tokenstream::TokenTree;
 use rustc_ast::util::classify::{self, TrailingBrace};
 use rustc_ast::visit::{Visitor, walk_expr};
 use rustc_ast::{
-    AttrStyle, AttrVec, Block, BlockCheckMode, DUMMY_NODE_ID, Expr, ExprKind, HasAttrs, Local,
-    LocalKind, MacCall, MacCallStmt, MacStmtStyle, Recovered, Stmt, StmtKind,
+    self as ast, AttrStyle, AttrVec, Block, BlockCheckMode, DUMMY_NODE_ID, Expr, ExprKind,
+    HasAttrs, Local, LocalKind, MacCall, MacCallStmt, MacStmtStyle, Recovered, Stmt, StmtKind,
 };
 use rustc_errors::{Applicability, Diag, PResult};
 use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
@@ -517,7 +516,7 @@ fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<Box<Exp
             _ => self.eat(exp!(Eq)),
         };
 
-        Ok(if eq_consumed || eq_optional { Some(self.parse_expr()?) } else { None })
+        Ok(if eq_consumed || eq_optional { Some(self.parse_expr_in_let()?) } else { None })
     }
 
     /// Parses a block. No inner attributes are allowed.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 098b659..bd70e5a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -680,6 +680,7 @@
         complex,
         concat,
         concat_bytes,
+        concat_str,
         conservative_impl_trait,
         console,
         const_allocate,
diff --git a/compiler/rustc_target/src/asm/nvptx.rs b/compiler/rustc_target/src/asm/nvptx.rs
index da8b79d..4aaafe1 100644
--- a/compiler/rustc_target/src/asm/nvptx.rs
+++ b/compiler/rustc_target/src/asm/nvptx.rs
@@ -36,9 +36,9 @@ pub fn supported_types(
         _arch: InlineAsmArch,
     ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
-            Self::reg16 => types! { _: I8, I16; },
-            Self::reg32 => types! { _: I8, I16, I32, F32; },
-            Self::reg64 => types! { _: I8, I16, I32, F32, I64, F64; },
+            Self::reg16 => types! { _: I8, I16, F16; },
+            Self::reg32 => types! { _: I8, I16, F16, I32, F32; },
+            Self::reg64 => types! { _: I8, I16, F16, I32, F32, I64, F64; },
         }
     }
 }
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index ce36a93..201f007 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -668,8 +668,6 @@ pub fn into_inner(boxed: Self) -> T {
     /// # Examples
     ///
     /// ```
-    /// #![feature(box_take)]
-    ///
     /// let c = Box::new(5);
     ///
     /// // take the value out of the box
@@ -680,7 +678,7 @@ pub fn into_inner(boxed: Self) -> T {
     /// let c = Box::write(uninit, 6);
     /// assert_eq!(*c, 6);
     /// ```
-    #[unstable(feature = "box_take", issue = "147212")]
+    #[stable(feature = "box_take", since = "CURRENT_RUSTC_VERSION")]
     pub fn take(boxed: Self) -> (T, Box<mem::MaybeUninit<T>, A>) {
         // SAFETY: Reading out an initialised value & leaving behind a
         // box with uninit contents.
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 7c879e2..d79af3a 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -659,8 +659,8 @@ pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
     #[must_use = "this does not display the `CStr`; \
                   it returns an object that can be displayed"]
     #[inline]
-    pub fn display(&self) -> impl fmt::Display {
-        crate::bstr::ByteStr::from_bytes(self.to_bytes())
+    pub fn display(&self) -> Display<'_> {
+        Display { c_str: self }
     }
 
     /// Returns the same string as a string slice `&CStr`.
@@ -858,3 +858,41 @@ fn count(self) -> usize {
 
 #[unstable(feature = "cstr_bytes", issue = "112115")]
 impl FusedIterator for Bytes<'_> {}
+
+/// Helper struct for safely printing a [`CStr`] with [`format!`] and `{}`.
+///
+/// A [`CStr`] might contain non-Unicode data. This `struct` implements the
+/// [`Display`] trait in a way that mitigates that. It is created by the
+/// [`display`](CStr::display) method on [`CStr`]. This may perform lossy
+/// conversion, depending on the platform. If you would like an implementation
+/// which escapes the [`CStr`] please use [`Debug`] instead.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(cstr_display)]
+///
+/// let s = c"Hello, world!";
+/// println!("{}", s.display());
+/// ```
+///
+/// [`Display`]: fmt::Display
+/// [`format!`]: ../../../std/macro.format.html
+#[unstable(feature = "cstr_display", issue = "139984")]
+pub struct Display<'a> {
+    c_str: &'a CStr,
+}
+
+#[unstable(feature = "cstr_display", issue = "139984")]
+impl fmt::Debug for Display<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&self.c_str, f)
+    }
+}
+
+#[unstable(feature = "cstr_display", issue = "139984")]
+impl fmt::Display for Display<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(crate::bstr::ByteStr::from_bytes(self.c_str.to_bytes()), f)
+    }
+}
diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs
index 7b03d58..2cc1ebb 100644
--- a/library/core/src/io/borrowed_buf.rs
+++ b/library/core/src/io/borrowed_buf.rs
@@ -222,6 +222,14 @@ pub struct BorrowedCursor<'a, T> {
     borrowed_buf: NonNull<BorrowedBuf<'a, T>>,
 }
 
+// SAFETY: A `BorrowedCursor<'a, T>` is a unique borrow of a `BorrowedBuf<'a, T>`, which is a
+// `&'a mut [MaybeUninit<T>]` and two `Copy` fields. The `buf` raw pointer is used like
+// `&mut [MaybeUninit<T>]` so `T: Send` -> `Send` and  is: `T: Sync` -> `Sync`, and the
+// `borrowed_buf` only touches two `Copy` fields, without depending of `T`.
+unsafe impl<T: Send> Send for BorrowedCursor<'_, T> {}
+// SAFETY: See the `Send` impl above.
+unsafe impl<T: Sync> Sync for BorrowedCursor<'_, T> {}
+
 impl<T> Debug for BorrowedCursor<'_, T> {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
         let buf = BorrowedBufDebug {
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index f5c7c85..25326f4 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -1576,6 +1576,16 @@ pub enum FpCategory {
 #[inline(always)]
 #[unstable(issue = "none", feature = "std_internals")]
 pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool {
+    // Assume that `digits` represents a whole number N in base `radix`.
+    // Then in infinite precision arithmetic (on whole numbers), we have:
+    //
+    // |N| <= pow(radix, digits.len()) - 1
+    //     <= pow(16, 2 * size_of::<T>() - is_signed) - 1
+    //     == pow(2, 8 * size_of::<T>() - 4 * is_signed) - 1
+    //     <= pow(2, 8 * size_of::<T>() - is_signed) - 1
+    //     == T::MAX
+    //
+    // Therefore this condition is sufficient for having no overflow.
     radix <= 16 && digits.len() <= size_of::<T>() * 2 - is_signed_ty as usize
 }
 
@@ -1819,20 +1829,23 @@ macro_rules! unwrap_or_PIE {
                     // Consider radix 16 as it has the highest information density per digit and will thus overflow the earliest:
                     // `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow.
                     // `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow.
-                    macro_rules! run_unchecked_loop {
-                        ($unchecked_additive_op:tt) => {{
+                    //
+                    // NOTE: We could use unchecked arithmetic here, but we don't, based on the observation
+                    // that it produces the same assembly as wrapping ones. See #163099.
+                    macro_rules! run_no_check_loop {
+                        ($additive_op:ident) => {{
                             while let [c, rest @ ..] = digits {
-                                result = result * (radix as $int_ty);
+                                result = <$int_ty>::wrapping_mul(result, radix as _);
                                 let x = unwrap_or_PIE!((*c as char).to_digit(radix), InvalidDigit);
-                                result = result $unchecked_additive_op (x as $int_ty);
+                                result = result.$additive_op(x as $int_ty);
                                 digits = rest;
                             }
                         }};
                     }
                     if is_positive {
-                        run_unchecked_loop!(+)
+                        run_no_check_loop!(wrapping_add)
                     } else {
-                        run_unchecked_loop!(-)
+                        run_no_check_loop!(wrapping_sub)
                     };
                 } else {
                     macro_rules! run_checked_loop {
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index cb0ca5d..9c3a675 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -8,6 +8,8 @@
 pub use alloc::ffi::c_str::{CString, NulError};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::ffi::c_str::CStr;
+#[unstable(feature = "cstr_display", issue = "139984")]
+pub use core::ffi::c_str::Display;
 #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
 pub use core::ffi::c_str::FromBytesUntilNulError;
 #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 043f854..fb0acda 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -204,11 +204,7 @@
 #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
 unsafe extern "C" {}
 
-#[cfg(all(target_os = "openbsd", target_arch = "sparc64"))]
-#[link(name = "gcc")]
-unsafe extern "C" {}
-
-#[cfg(all(target_os = "openbsd", not(target_arch = "sparc64")))]
+#[cfg(target_os = "openbsd")]
 #[link(name = "c++abi")]
 unsafe extern "C" {}
 
diff --git a/src/doc/rustc/src/platform-support/openbsd.md b/src/doc/rustc/src/platform-support/openbsd.md
index e6fb23c..75bae0e 100644
--- a/src/doc/rustc/src/platform-support/openbsd.md
+++ b/src/doc/rustc/src/platform-support/openbsd.md
@@ -14,7 +14,7 @@
 | `i686-unknown-openbsd`         | libc++      | [Standard PC and clones based on the Intel i386 architecture and compatible processors](https://www.openbsd.org/i386.html) |
 | `powerpc64-unknown-openbsd`    | libc++      | [IBM POWER-based PowerNV systems](https://www.openbsd.org/powerpc64.html) |
 | `riscv64gc-unknown-openbsd`    | libc++      | [64-bit RISC-V systems](https://www.openbsd.org/riscv64.html) |
-| `sparc64-unknown-openbsd`      | estdc++     | [Sun UltraSPARC and Fujitsu SPARC64 systems](https://www.openbsd.org/sparc64.html) |
+| `sparc64-unknown-openbsd`      | libc++      | [Sun UltraSPARC and Fujitsu SPARC64 systems](https://www.openbsd.org/sparc64.html) |
 | `x86_64-unknown-openbsd`       | libc++      | [AMD64-based systems](https://www.openbsd.org/amd64.html) |
 
 Note that all OS versions are *major* even if using X.Y notation (`6.8` and `6.9` are different major versions) and could be binary incompatibles (with breaking changes).
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 4d78952..64fff96 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -11,7 +11,6 @@
 # tidy-alphabetical-start
 arrayvec = { version = "0.7", default-features = false }
 askama = { version = "0.16.1", default-features = false, features = ["alloc", "config", "derive"] }
-base64 = "0.21.7"
 indexmap = { version = "2", features = ["serde"] }
 itertools = "0.15"
 libc = "0.2"
diff --git a/tests/assembly-llvm/asm/nvptx-types.rs b/tests/assembly-llvm/asm/nvptx-types.rs
index 1cb176c..15c4dab 100644
--- a/tests/assembly-llvm/asm/nvptx-types.rs
+++ b/tests/assembly-llvm/asm/nvptx-types.rs
@@ -3,7 +3,7 @@
 //@ compile-flags: --target nvptx64-nvidia-cuda
 //@ needs-llvm-components: nvptx
 
-#![feature(no_core, asm_experimental_arch)]
+#![feature(no_core, asm_experimental_arch, f16)]
 #![crate_type = "rlib"]
 #![no_core]
 
@@ -38,78 +38,96 @@ pub unsafe fn $func(x: $ty) -> $ty {
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i8
 // CHECK: // begin inline asm
-// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg16_i8 i8 reg16 "mov.i16");
+check!(reg16_i8 i8 reg16 "mov.b16");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i16
 // CHECK: // begin inline asm
-// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg16_i16 i16 reg16 "mov.i16");
+check!(reg16_i16 i16 reg16 "mov.b16");
+
+// CHECK-LABEL: .visible .func (.param .align 2 .b8 func_retval0[2]) reg16_f16
+// CHECK: // begin inline asm
+// CHECK: mov.b16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg16_f16 f16 reg16 "mov.b16");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i8
 // CHECK: // begin inline asm
-// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg32_i8 i8 reg32 "mov.i32");
+check!(reg32_i8 i8 reg32 "mov.b32");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i16
 // CHECK: // begin inline asm
-// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg32_i16 i16 reg32 "mov.i32");
+check!(reg32_i16 i16 reg32 "mov.b32");
+
+// CHECK-LABEL: .visible .func (.param .align 2 .b8 func_retval0[2]) reg32_f16
+// CHECK: // begin inline asm
+// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_f16 f16 reg32 "mov.b32");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i32
 // CHECK: // begin inline asm
-// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg32_i32 i32 reg32 "mov.i32");
+check!(reg32_i32 i32 reg32 "mov.b32");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_f32
 // CHECK: // begin inline asm
-// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg32_f32 f32 reg32 "mov.i32");
+check!(reg32_f32 f32 reg32 "mov.b32");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i8
 // CHECK: // begin inline asm
-// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg64_i8 i8 reg64 "mov.i64");
+check!(reg64_i8 i8 reg64 "mov.b64");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i16
 // CHECK: // begin inline asm
-// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg64_i16 i16 reg64 "mov.i64");
+check!(reg64_i16 i16 reg64 "mov.b64");
+
+// CHECK-LABEL: .visible .func (.param .align 2 .b8 func_retval0[2]) reg64_f16
+// CHECK: // begin inline asm
+// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_f16 f16 reg64 "mov.b64");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i32
 // CHECK: // begin inline asm
-// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg64_i32 i32 reg64 "mov.i64");
+check!(reg64_i32 i32 reg64 "mov.b64");
 
 // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_f32
 // CHECK: // begin inline asm
-// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg64_f32 f32 reg64 "mov.i64");
+check!(reg64_f32 f32 reg64 "mov.b64");
 
 // CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_i64
 // CHECK: // begin inline asm
-// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg64_i64 i64 reg64 "mov.i64");
+check!(reg64_i64 i64 reg64 "mov.b64");
 
 // CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_f64
 // CHECK: // begin inline asm
-// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg64_f64 f64 reg64 "mov.i64");
+check!(reg64_f64 f64 reg64 "mov.b64");
 
 // CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_ptr
 // CHECK: // begin inline asm
-// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
 // CHECK: // end inline asm
-check!(reg64_ptr ptr reg64 "mov.i64");
+check!(reg64_ptr ptr reg64 "mov.b64");
diff --git a/tests/codegen-llvm/float/f16b.rs b/tests/codegen-llvm/float/f16b.rs
index 7de6a77..3bd2455 100644
--- a/tests/codegen-llvm/float/f16b.rs
+++ b/tests/codegen-llvm/float/f16b.rs
@@ -1,4 +1,13 @@
 //@ compile-flags: -Copt-level=3
+//@ revisions: GENERIC LOONGARCH32 LOONGARCH64 RISCV32 RISCV64
+//@ [GENERIC] ignore-loongarch32
+//@ [GENERIC] ignore-loongarch64
+//@ [GENERIC] ignore-riscv32
+//@ [GENERIC] ignore-riscv64
+//@ [LOONGARCH32] only-loongarch32
+//@ [LOONGARCH64] only-loongarch64
+//@ [RISCV32] only-riscv32
+//@ [RISCV64] only-riscv64
 
 #![crate_type = "lib"]
 #![feature(f16b)]
@@ -8,31 +17,63 @@
 
 use core::num::f16b;
 
-// CHECK-LABEL: define{{.*}} bfloat @identity_f16b(bfloat
+// GENERIC-LABEL: define{{.*}} bfloat @identity_f16b(bfloat
+// LOONGARCH32-LABEL: define{{.*}} half @identity_f16b(half
+// LOONGARCH64-LABEL: define{{.*}} half @identity_f16b(half
+// RISCV32-LABEL: define{{.*}} half @identity_f16b(half
+// RISCV64-LABEL: define{{.*}} half @identity_f16b(half
 #[no_mangle]
 pub extern "C" fn identity_f16b(value: f16b) -> f16b {
-    // CHECK: ret bfloat
+    // GENERIC: ret bfloat
+    // LOONGARCH32: ret half
+    // LOONGARCH64: ret half
+    // RISCV32: ret half
+    // RISCV64: ret half
     value
 }
 
-// CHECK-LABEL: define{{.*}} i16 @f16b_to_bits(bfloat
+// GENERIC-LABEL: define{{.*}} i16 @f16b_to_bits(bfloat
+// LOONGARCH32-LABEL: define{{.*}} i16 @f16b_to_bits(half
+// LOONGARCH64-LABEL: define{{.*}} i16 @f16b_to_bits(half
+// RISCV32-LABEL: define{{.*}} i16 @f16b_to_bits(half
+// RISCV64-LABEL: define{{.*}} i16 @f16b_to_bits(half
 #[no_mangle]
 pub extern "C" fn f16b_to_bits(value: f16b) -> u16 {
-    // CHECK: bitcast bfloat %value to i16
+    // GENERIC: bitcast bfloat %value to i16
+    // LOONGARCH32: bitcast half %0 to i16
+    // LOONGARCH64: bitcast half %0 to i16
+    // RISCV32: bitcast half %0 to i16
+    // RISCV64: bitcast half %0 to i16
     value.to_bits()
 }
 
-// CHECK-LABEL: define{{.*}} bfloat @f16b_from_bits(i16
+// GENERIC-LABEL: define{{.*}} bfloat @f16b_from_bits(i16
+// LOONGARCH32-LABEL: define{{.*}} half @f16b_from_bits(i16
+// LOONGARCH64-LABEL: define{{.*}} half @f16b_from_bits(i16
+// RISCV32-LABEL: define{{.*}} half @f16b_from_bits(i16
+// RISCV64-LABEL: define{{.*}} half @f16b_from_bits(i16
 #[no_mangle]
 pub extern "C" fn f16b_from_bits(bits: u16) -> f16b {
-    // CHECK: bitcast i16 %bits to bfloat
+    // GENERIC: bitcast i16 %bits to bfloat
+    // LOONGARCH32: bitcast i16 %bits to half
+    // LOONGARCH64: bitcast i16 %bits to half
+    // RISCV32: bitcast i16 %bits to half
+    // RISCV64: bitcast i16 %bits to half
     f16b::from_bits(bits)
 }
 
-// CHECK-LABEL: define{{.*}} float @widen_f16b(bfloat
+// GENERIC-LABEL: define{{.*}} float @widen_f16b(bfloat
+// LOONGARCH32-LABEL: define{{.*}} float @widen_f16b(half
+// LOONGARCH64-LABEL: define{{.*}} float @widen_f16b(half
+// RISCV32-LABEL: define{{.*}} float @widen_f16b(half
+// RISCV64-LABEL: define{{.*}} float @widen_f16b(half
 #[no_mangle]
 pub extern "C" fn widen_f16b(value: f16b) -> f32 {
-    // CHECK: bitcast bfloat %value to i16
+    // GENERIC: bitcast bfloat %value to i16
+    // LOONGARCH32: bitcast half %0 to i16
+    // LOONGARCH64: bitcast half %0 to i16
+    // RISCV32: bitcast half %0 to i16
+    // RISCV64: bitcast half %0 to i16
     // CHECK: zext i16
     // CHECK: shl nuw i32 {{.*}}, 16
     // CHECK: bitcast i32 {{.*}} to float
diff --git a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs
index f449e02..8b0b92b 100644
--- a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs
+++ b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs
@@ -10,7 +10,7 @@ fn foo<'a, T>()
 where
     T: Proj<'a, Assoc = fn(<T as Proj>::Assoc)>,
     (): Trait<<T as Proj<'a>>::Assoc>,
-    //~^ ERROR the trait bound `(): Trait<fn(for<'a> fn(<T as Proj<'a>>::Assoc))>` is not satisfied
+    //~^ ERROR overflow evaluating the requirement `(): Trait<<T as Proj<'a>>::Assoc>`
 {
 }
 
diff --git a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.stderr b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.stderr
index 5e8e131..9d1c8c4 100644
--- a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.stderr
+++ b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.stderr
@@ -1,14 +1,9 @@
-error[E0277]: the trait bound `(): Trait<fn(for<'a> fn(<T as Proj<'a>>::Assoc))>` is not satisfied
+error[E0275]: overflow evaluating the requirement `(): Trait<<T as Proj<'a>>::Assoc>`
   --> $DIR/placeholder-assumptions-issue-157840.rs:12:9
    |
 LL |     (): Trait<<T as Proj<'a>>::Assoc>,
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<fn(for<'a> fn(<T as Proj<'a>>::Assoc))>` is not implemented for `()`
-   |
-help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL |     (): Trait<<T as Proj<'a>>::Assoc>, (): Trait<fn(for<'a> fn(<T as Proj<'a>>::Assoc))>
-   |                                        +++++++++++++++++++++++++++++++++++++++++++++++++
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs
index e700999..898bc28 100644
--- a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs
+++ b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs
@@ -1,7 +1,8 @@
 macro_rules! join {
     ($lhs:ident, $rhs:ident) => {
-        let ${concat($lhs, $rhs)}: () = ();
+        let ${concat($lhs, $rhs)}: &'static str = ${concat_str($lhs, $rhs)};
         //~^ ERROR the `concat` meta-variable expression is unstable
+        //~| ERROR the `concat_str` meta-variable expression is unstable
     };
 }
 
diff --git a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr
index 5b2589d..47c09a1 100644
--- a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr
+++ b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr
@@ -1,13 +1,23 @@
 error[E0658]: the `concat` meta-variable expression is unstable
   --> $DIR/feature-gate-macro-metavar-expr-concat.rs:3:14
    |
-LL |         let ${concat($lhs, $rhs)}: () = ();
+LL |         let ${concat($lhs, $rhs)}: &'static str = ${concat_str($lhs, $rhs)};
    |              ^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #124225 <https://github.com/rust-lang/rust/issues/124225> for more information
    = help: add `#![feature(macro_metavar_expr_concat)]` 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
+error[E0658]: the `concat_str` meta-variable expression is unstable
+  --> $DIR/feature-gate-macro-metavar-expr-concat.rs:3:52
+   |
+LL |         let ${concat($lhs, $rhs)}: &'static str = ${concat_str($lhs, $rhs)};
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #124225 <https://github.com/rust-lang/rust/issues/124225> for more information
+   = help: add `#![feature(macro_metavar_expr_concat)]` 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 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs
index 5ac50c9..cd0c23d 100644
--- a/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs
+++ b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs
@@ -5,7 +5,7 @@
 
 macro_rules! create_things {
     ($lhs:ident) => {
-        struct ${concat($lhs, _separated_idents_in_a_struct)} {
+       struct ${concat($lhs, _separated_idents_in_a_struct)} {
             foo: i32,
             ${concat($lhs, _separated_idents_in_a_field)}: i32,
         }
@@ -20,19 +20,23 @@ fn ${concat($lhs, _separated_idents_in_a_fn)}() {}
 
 macro_rules! many_idents {
     ($a:ident, $c:ident) => {
+        #[allow(dead_code, reason = ${concat_str($a, B, $c, D)})]
         const ${concat($a, B, $c, D)}: i32 = 1;
     };
 }
 
 macro_rules! valid_tts {
     ($_0:tt, $_1:tt) => {
+        #[allow(dead_code, reason = ${concat_str($_0, $_1)})]
         const ${concat($_0, $_1)}: i32 = 1;
     }
 }
 
 macro_rules! without_dollar_sign_is_an_ident {
     ($ident:ident) => {
+        #[allow(dead_code, reason = ${concat_str(VAR, ident)})]
         const ${concat(VAR, ident)}: i32 = 1;
+        #[allow(dead_code, reason = ${concat_str(VAR, $ident)})]
         const ${concat(VAR, $ident)}: i32 = 2;
     };
 }
@@ -40,60 +44,103 @@ macro_rules! without_dollar_sign_is_an_ident {
 macro_rules! combinations {
     ($ident:ident, $literal:literal, $tt_ident:tt, $tt_literal:tt) => {{
         // tt ident
+        #[allow(dead_code, reason = ${concat_str($tt_ident, b)})]
         let ${concat($tt_ident, b)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_ident, _b)})]
         let ${concat($tt_ident, _b)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_ident, "b")})]
         let ${concat($tt_ident, "b")} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_ident, $tt_ident)})]
         let ${concat($tt_ident, $tt_ident)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_ident, $tt_literal)})]
         let ${concat($tt_ident, $tt_literal)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_ident, $ident)})]
         let ${concat($tt_ident, $ident)} = ();
-        let ${concat($tt_ident, $literal)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_ident, $ident)})]
+        let ${concat($tt_ident, $ident)} = ();
         // tt literal
+        #[allow(dead_code, reason = ${concat_str($tt_literal, b)})]
         let ${concat($tt_literal, b)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_literal, _b)})]
         let ${concat($tt_literal, _b)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_literal, "b")})]
         let ${concat($tt_literal, "b")} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_literal, $tt_ident)})]
         let ${concat($tt_literal, $tt_ident)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_literal, $tt_literal)})]
         let ${concat($tt_literal, $tt_literal)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_literal, $ident)})]
         let ${concat($tt_literal, $ident)} = ();
+        #[allow(dead_code, reason = ${concat_str($tt_literal, $literal)})]
         let ${concat($tt_literal, $literal)} = ();
 
         // ident (adhoc)
+        #[allow(dead_code, reason = ${concat_str(_b, b)})]
         let ${concat(_b, b)} = ();
+        #[allow(dead_code, reason = ${concat_str(_b, _b)})]
         let ${concat(_b, _b)} = ();
+        #[allow(dead_code, reason = ${concat_str(_b, "b")})]
         let ${concat(_b, "b")} = ();
+        #[allow(dead_code, reason = ${concat_str(_b, $tt_ident)})]
         let ${concat(_b, $tt_ident)} = ();
+        #[allow(dead_code, reason = ${concat_str(_b, $tt_literal)})]
         let ${concat(_b, $tt_literal)} = ();
+        #[allow(dead_code, reason = ${concat_str(_b, $ident)})]
         let ${concat(_b, $ident)} = ();
+        #[allow(dead_code, reason = ${concat_str(_b, $literal)})]
         let ${concat(_b, $literal)} = ();
         // ident (param)
+        #[allow(dead_code, reason = ${concat_str($ident, b)})]
         let ${concat($ident, b)} = ();
+        #[allow(dead_code, reason = ${concat_str($ident, _b)})]
         let ${concat($ident, _b)} = ();
+        #[allow(dead_code, reason = ${concat_str($ident, "b")})]
         let ${concat($ident, "b")} = ();
+        #[allow(dead_code, reason = ${concat_str($ident, $tt_ident)})]
         let ${concat($ident, $tt_ident)} = ();
+        #[allow(dead_code, reason = ${concat_str($ident, $tt_literal)})]
         let ${concat($ident, $tt_literal)} = ();
+        #[allow(dead_code, reason = ${concat_str($ident, $ident)})]
         let ${concat($ident, $ident)} = ();
+        #[allow(dead_code, reason = ${concat_str($ident, $literal)})]
         let ${concat($ident, $literal)} = ();
 
         // literal (adhoc)
+        #[allow(dead_code, reason = ${concat_str("a", b)})]
         let ${concat("a", b)} = ();
+        #[allow(dead_code, reason = ${concat_str("a", _b)})]
         let ${concat("a", _b)} = ();
+        #[allow(dead_code, reason = ${concat_str("a", "b")})]
         let ${concat("a", "b")} = ();
+        #[allow(dead_code, reason = ${concat_str("a", $tt_ident)})]
         let ${concat("a", $tt_ident)} = ();
+        #[allow(dead_code, reason = ${concat_str("a", $tt_literal)})]
         let ${concat("a", $tt_literal)} = ();
+        #[allow(dead_code, reason = ${concat_str("a", $ident)})]
         let ${concat("a", $ident)} = ();
+        #[allow(dead_code, reason = ${concat_str("a", $literal)})]
         let ${concat("a", $literal)} = ();
         // literal (param)
+        #[allow(dead_code, reason = ${concat_str($literal, b)})]
         let ${concat($literal, b)} = ();
+        #[allow(dead_code, reason = ${concat_str($literal, _b)})]
         let ${concat($literal, _b)} = ();
+        #[allow(dead_code, reason = ${concat_str($literal, "b")})]
         let ${concat($literal, "b")} = ();
+        #[allow(dead_code, reason = ${concat_str($literal, $tt_ident)})]
         let ${concat($literal, $tt_ident)} = ();
+        #[allow(dead_code, reason = ${concat_str($literal, $tt_literal)})]
         let ${concat($literal, $tt_literal)} = ();
+        #[allow(dead_code, reason = ${concat_str($literal, $ident)})]
         let ${concat($literal, $ident)} = ();
+        #[allow(dead_code, reason = ${concat_str($literal, $literal)})]
         let ${concat($literal, $literal)} = ();
     }};
 }
 
 macro_rules! int_struct {
     ($n: literal) => {
+        #[allow(dead_code, reason = ${concat_str(E, $n)})]
         struct ${concat(E, $n)};
     }
 }
diff --git a/tests/ui/macros/metavar-expressions/concat-str-escape.rs b/tests/ui/macros/metavar-expressions/concat-str-escape.rs
new file mode 100644
index 0000000..612c957
--- /dev/null
+++ b/tests/ui/macros/metavar-expressions/concat-str-escape.rs
@@ -0,0 +1,20 @@
+//@ run-pass
+
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! escape_literal {
+    ($literal:literal, $concatted:literal) => {
+        let lit = ${concat_str("_", "\"foo", $literal)};
+        assert_eq!(lit, concat!("_", "\"foo", $literal));
+        assert_eq!(lit, $concatted);
+
+    }
+}
+
+fn main(){
+    escape_literal!("\u{00BD}", "_\"foo\u{00BD}");
+    escape_literal!("\x41", "_\"foo\x41");
+    escape_literal!("🤷", "_\"foo🤷");
+    escape_literal!("\u{1F980}", "_\"foo🦀");
+    escape_literal!("aaa \"bbb\" ccc", "_\"fooaaa \"bbb\" ccc");
+}
diff --git a/tests/ui/macros/metavar-expressions/concat-str-horror.rs b/tests/ui/macros/metavar-expressions/concat-str-horror.rs
new file mode 100644
index 0000000..558e555
--- /dev/null
+++ b/tests/ui/macros/metavar-expressions/concat-str-horror.rs
@@ -0,0 +1,13 @@
+//@ run-pass
+#![feature(macro_metavar_expr_concat)]
+
+macro_rules! format_horror{
+    ($arg1:ident, $arg2:expr, $arg3:expr) =>  {
+        format!(${concat_str("horror ", $arg1, " horror {} horror {}")}, $arg2, $arg3)
+    }
+}
+
+fn main(){
+    let x = format_horror!(a, "b", "c");
+    assert_eq!(x, "horror a horror b horror c");
+}
diff --git a/tests/ui/macros/metavar-expressions/concat-str.rs b/tests/ui/macros/metavar-expressions/concat-str.rs
new file mode 100644
index 0000000..f04e620
--- /dev/null
+++ b/tests/ui/macros/metavar-expressions/concat-str.rs
@@ -0,0 +1,20 @@
+#![feature(macro_metavar_expr_concat)]
+#![crate_type = "lib"]
+
+macro_rules! make_stuff {
+    ($prefix:literal, $name:ident) => {
+        #[deprecated(since = "1.0.0", note = ${concat_str($prefix, " ", $name, " trait")})]
+        #[diagnostic::on_unimplemented(message = ${concat_str("please do not the ", $name)})]
+        pub trait ${concat(New, $name)} {}
+    }
+}
+
+make_stuff!("blah blah blah", AAAAAA);
+
+pub fn foo(x: impl NewAAAAAA) {}
+//~^ WARN use of deprecated trait `NewAAAAAA`: blah blah blah AAAAAA trait [deprecated]
+
+fn bar(){
+    foo(());
+    //~^ ERROR please do not the AAAAAA [E0277]
+}
diff --git a/tests/ui/macros/metavar-expressions/concat-str.stderr b/tests/ui/macros/metavar-expressions/concat-str.stderr
new file mode 100644
index 0000000..2e7e8cd
--- /dev/null
+++ b/tests/ui/macros/metavar-expressions/concat-str.stderr
@@ -0,0 +1,35 @@
+warning: use of deprecated trait `NewAAAAAA`: blah blah blah AAAAAA trait
+  --> $DIR/concat-str.rs:14:20
+   |
+LL | pub fn foo(x: impl NewAAAAAA) {}
+   |                    ^^^^^^^^^
+   |
+   = note: `#[warn(deprecated)]` on by default
+
+error[E0277]: please do not the AAAAAA
+  --> $DIR/concat-str.rs:18:9
+   |
+LL | macro_rules! make_stuff {
+...
+LL |     foo(());
+   |     --- ^^ the trait `NewAAAAAA` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/concat-str.rs:8:9
+   |
+LL |         pub trait ${concat(New, $name)} {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | make_stuff!("blah blah blah", AAAAAA);
+   | ------------------------------------- in this macro invocation
+note: required by a bound in `foo`
+  --> $DIR/concat-str.rs:14:20
+   |
+LL | pub fn foo(x: impl NewAAAAAA) {}
+   |                    ^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/parser/detect-missing-else-in-let-1.rs b/tests/ui/parser/detect-missing-else-in-let-1.rs
new file mode 100644
index 0000000..9f9d11e
--- /dev/null
+++ b/tests/ui/parser/detect-missing-else-in-let-1.rs
@@ -0,0 +1,8 @@
+// detect missing else in let statement. (issue #135857)
+fn main() {
+    let foo = Some(1);
+    let Some(a) = foo{return;};
+    //~^ HELP you might have meant to write a diverging block
+    //~| HELP escape `return` to use it as an identifier
+    //~| ERROR expected identifier, found keyword `return`
+}
diff --git a/tests/ui/parser/detect-missing-else-in-let-1.stderr b/tests/ui/parser/detect-missing-else-in-let-1.stderr
new file mode 100644
index 0000000..2236bb1
--- /dev/null
+++ b/tests/ui/parser/detect-missing-else-in-let-1.stderr
@@ -0,0 +1,20 @@
+error: expected identifier, found keyword `return`
+  --> $DIR/detect-missing-else-in-let-1.rs:4:23
+   |
+LL |     let Some(a) = foo{return;};
+   |                   --- ^^^^^^ expected identifier, found keyword
+   |                   |
+   |                   while parsing this struct
+   |
+help: escape `return` to use it as an identifier
+   |
+LL |     let Some(a) = foo{r#return;};
+   |                       ++
+help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else`
+      for more information, visit <https://doc.rust-lang.org/beta/rust-by-example/flow_control/let_else.html>
+   |
+LL |     let Some(a) = foo else {return;};
+   |                       ++++
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/detect-missing-else-in-let-2.rs b/tests/ui/parser/detect-missing-else-in-let-2.rs
new file mode 100644
index 0000000..87a5a75
--- /dev/null
+++ b/tests/ui/parser/detect-missing-else-in-let-2.rs
@@ -0,0 +1,10 @@
+// the compiler currently will suggest the user to add `else` in this case
+// it shouldn't because `bar` is an irrefutable pattern, the else block would never be valid/useful
+// it is currently unmitigated
+fn main(){
+    let foo = 12;
+    let bar = foo{return;};
+    //~^ HELP you might have meant to write a diverging block
+    //~| HELP escape `return` to use it as an identifier
+    //~| ERROR expected identifier, found keyword `return`
+}
diff --git a/tests/ui/parser/detect-missing-else-in-let-2.stderr b/tests/ui/parser/detect-missing-else-in-let-2.stderr
new file mode 100644
index 0000000..5f21c9f
--- /dev/null
+++ b/tests/ui/parser/detect-missing-else-in-let-2.stderr
@@ -0,0 +1,20 @@
+error: expected identifier, found keyword `return`
+  --> $DIR/detect-missing-else-in-let-2.rs:6:19
+   |
+LL |     let bar = foo{return;};
+   |               --- ^^^^^^ expected identifier, found keyword
+   |               |
+   |               while parsing this struct
+   |
+help: escape `return` to use it as an identifier
+   |
+LL |     let bar = foo{r#return;};
+   |                   ++
+help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else`
+      for more information, visit <https://doc.rust-lang.org/beta/rust-by-example/flow_control/let_else.html>
+   |
+LL |     let bar = foo else {return;};
+   |                   ++++
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.current.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.current.stderr
new file mode 100644
index 0000000..2c9694c
--- /dev/null
+++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.current.stderr
@@ -0,0 +1,15 @@
+error[E0275]: overflow evaluating the requirement `for<'b> T: Proj<'b>`
+  --> $DIR/find-param-recursion-issue-152716.rs:15:1
+   |
+LL | / fn foo<T>()
+LL | |
+LL | | where
+LL | |     T: for<'a> Proj<'a, Assoc = for<'b> fn(<T as Proj<'b>>::Assoc)>,
+LL | |     (): Trait<<T as Proj<'static>>::Assoc>
+   | |__________________________________________^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`find_param_recursion_issue_152716`)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.next.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.next.stderr
new file mode 100644
index 0000000..c722813
--- /dev/null
+++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.next.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `(): Trait<<T as Proj<'static>>::Assoc>`
+  --> $DIR/find-param-recursion-issue-152716.rs:19:9
+   |
+LL |     (): Trait<<T as Proj<'static>>::Assoc>
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs
index 4d08807..fb1ac0d 100644
--- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs
+++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs
@@ -1,4 +1,6 @@
-//@ compile-flags: -Znext-solver
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 // Regression test for <https://github.com/rust-lang/rust/issues/152716>.
 //
@@ -11,10 +13,11 @@ trait Proj<'a> {
     type Assoc;
 }
 fn foo<T>()
+//[current]~^ ERROR: overflow evaluating the requirement `for<'b> T: Proj<'b>`
 where
     T: for<'a> Proj<'a, Assoc = for<'b> fn(<T as Proj<'b>>::Assoc)>,
     (): Trait<<T as Proj<'static>>::Assoc>
-    //~^ ERROR: the trait bound `(): Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>` is not satisfied
+    //[next]~^ ERROR: overflow evaluating the requirement `(): Trait<<T as Proj<'static>>::Assoc>`
 {
 }
 
diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr
deleted file mode 100644
index 1408890..0000000
--- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0277]: the trait bound `(): Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>` is not satisfied
-  --> $DIR/find-param-recursion-issue-152716.rs:16:9
-   |
-LL |     (): Trait<<T as Proj<'static>>::Assoc>
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>` is not implemented for `()`
-   |
-help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL |     (): Trait<<T as Proj<'static>>::Assoc>, (): Trait<fn(for<'b> fn(<T as Proj<'b>>::Assoc))>
-   |                                           +++++++++++++++++++++++++++++++++++++++++++++++++++
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.current.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.current.stderr
new file mode 100644
index 0000000..2308711
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.current.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+  --> $DIR/recursive-self-normalization-2.rs:16:1
+   |
+LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.next.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.next.stderr
new file mode 100644
index 0000000..ea8b5cd
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.next.stderr
@@ -0,0 +1,15 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+  --> $DIR/recursive-self-normalization-2.rs:16:1
+   |
+LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0275]: overflow evaluating the requirement `<T as Foo2>::Assoc2 == _`
+  --> $DIR/recursive-self-normalization-2.rs:16:1
+   |
+LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
index 8dc27c0..0e08a6b 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
@@ -1,4 +1,6 @@
-//@ compile-flags: -Znext-solver
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 trait Foo1 {
     type Assoc1;
@@ -12,8 +14,9 @@ trait Bar {}
 fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
+    //~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+    //[next]~| ERROR overflow evaluating the requirement `<T as Foo2>::Assoc2 == _`
     needs_bar::<T::Assoc1>();
-    //~^ ERROR: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
deleted file mode 100644
index 6f5111a..0000000
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0277]: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
-  --> $DIR/recursive-self-normalization-2.rs:15:17
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo1>::Assoc1`
-   |
-note: required by a bound in `needs_bar`
-  --> $DIR/recursive-self-normalization-2.rs:12:17
-   |
-LL | fn needs_bar<S: Bar>() {}
-   |                 ^^^ required by this bound in `needs_bar`
-help: consider further restricting the associated type
-   |
-LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo1>::Assoc1: Bar {
-   |                                                                                       ++++++++++++++++++++++++++++++
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.current.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.current.stderr
new file mode 100644
index 0000000..4b9be86
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.current.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
+  --> $DIR/recursive-self-normalization-simple.rs:15:1
+   |
+LL | fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.next.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.next.stderr
new file mode 100644
index 0000000..4b9be86
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.next.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
+  --> $DIR/recursive-self-normalization-simple.rs:15:1
+   |
+LL | fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs
new file mode 100644
index 0000000..b511dc4
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs
@@ -0,0 +1,19 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// A variant of `recursive-self-normalization.rs` which passes if
+// we treat inductive cycles as `NoSolution` in the trait solver.
+
+trait Foo {
+    type Assoc;
+}
+
+trait Bar {}
+fn needs_bar<S: Bar>() {}
+
+fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
+    //~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.current.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.current.stderr
new file mode 100644
index 0000000..6569be7
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.current.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
+  --> $DIR/recursive-self-normalization.rs:12:1
+   |
+LL | fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.next.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.next.stderr
new file mode 100644
index 0000000..6569be7
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.next.stderr
@@ -0,0 +1,9 @@
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
+  --> $DIR/recursive-self-normalization.rs:12:1
+   |
+LL | fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
index f441ac4..a25d028 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
@@ -1,4 +1,6 @@
-//@ compile-flags: -Znext-solver
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 trait Foo {
     type Assoc;
@@ -8,8 +10,8 @@ trait Bar {}
 fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
+    //~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
     needs_bar::<T::Assoc>();
-    //~^ ERROR the trait bound `<T as Foo>::Assoc: Bar` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
deleted file mode 100644
index c551823..0000000
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0277]: the trait bound `<T as Foo>::Assoc: Bar` is not satisfied
-  --> $DIR/recursive-self-normalization.rs:11:17
-   |
-LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo>::Assoc`
-   |
-note: required by a bound in `needs_bar`
-  --> $DIR/recursive-self-normalization.rs:8:17
-   |
-LL | fn needs_bar<S: Bar>() {}
-   |                 ^^^ required by this bound in `needs_bar`
-help: consider further restricting the associated type
-   |
-LL | fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() where <T as Foo>::Assoc: Bar {
-   |                                              ++++++++++++++++++++++++++++
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.