about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock6
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs29
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/repr.rs27
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs3
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/traits.rs7
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs11
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs15
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs73
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/inline_asm.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs6
-rw-r--r--compiler/rustc_index/src/idx.rs15
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs4
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs2
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs11
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs12
-rw-r--r--compiler/rustc_middle/src/query/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs2
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs28
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs5
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs4
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/util.rs11
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs2
-rw-r--r--compiler/rustc_mir_build/src/check_tail_calls.rs6
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs13
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs2
-rw-r--r--compiler/rustc_mir_transform/src/add_subtyping_projections.rs4
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs3
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_parse/messages.ftl3
-rw-r--r--compiler/rustc_parse/src/errors.rs4
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs26
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs5
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs8
-rw-r--r--compiler/rustc_passes/src/errors.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs7
-rw-r--r--compiler/rustc_symbol_mangling/src/test.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs7
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs6
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs7
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs6
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs4
-rw-r--r--compiler/rustc_traits/src/codegen.rs2
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs2
-rw-r--r--compiler/rustc_transmute/src/layout/mod.rs2
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs37
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs8
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs4
-rw-r--r--compiler/rustc_type_ir/src/search_graph/stack.rs4
-rw-r--r--compiler/rustc_type_ir/src/visit.rs4
-rw-r--r--library/Cargo.lock15
-rw-r--r--library/core/src/range.rs140
-rw-r--r--library/core/src/range/iter.rs2
-rw-r--r--library/core/src/range/legacy.rs4
-rw-r--r--library/core/src/slice/index.rs41
-rw-r--r--library/core/src/str/traits.rs8
-rw-r--r--library/std/tests/floats/f32.rs10
-rw-r--r--library/test/Cargo.toml2
-rwxr-xr-xsrc/ci/docker/scripts/rfl-build.sh4
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sym.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/mod.rs2
-rw-r--r--src/tools/miri/tests/pass/static_align.rs14
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--tests/codegen-llvm/align-static.rs31
-rw-r--r--tests/ui/attributes/malformed-static-align.rs17
-rw-r--r--tests/ui/attributes/malformed-static-align.stderr45
-rw-r--r--tests/ui/const-generics/std/const-generics-range.full.stderr2
-rw-r--r--tests/ui/const-generics/std/const-generics-range.min.stderr2
-rw-r--r--tests/ui/const-generics/std/const-generics-range.rs14
-rw-r--r--tests/ui/feature-gates/feature-gate-static_align.rs11
-rw-r--r--tests/ui/feature-gates/feature-gate-static_align.stderr23
-rw-r--r--tests/ui/iterators/ranges.stderr6
-rw-r--r--tests/ui/new-range/disabled.rs4
-rw-r--r--tests/ui/new-range/enabled.rs4
-rw-r--r--tests/ui/parser/auxiliary/tuple-index-suffix-proc-macro-aux.rs33
-rw-r--r--tests/ui/parser/issues/issue-59418.rs18
-rw-r--r--tests/ui/parser/issues/issue-59418.stderr26
-rw-r--r--tests/ui/parser/tuple-index-suffix-proc-macro.rs32
-rw-r--r--tests/ui/parser/tuple-index-suffix-proc-macro.stderr26
-rw-r--r--tests/ui/parser/tuple-index-suffix.rs79
-rw-r--r--tests/ui/parser/tuple-index-suffix.stderr134
-rw-r--r--tests/ui/range/issue-54505-no-literals.stderr4
-rw-r--r--tests/ui/range/issue-54505-no-std.stderr2
-rw-r--r--tests/ui/range/issue-54505.stderr2
-rw-r--r--tests/ui/static/static-align.rs26
-rw-r--r--tests/ui/suggestions/apitit-unimplemented-method.rs12
-rw-r--r--tests/ui/suggestions/apitit-unimplemented-method.stderr12
-rw-r--r--tests/ui/suggestions/auxiliary/dep.rs4
-rw-r--r--triagebot.toml15
125 files changed, 1070 insertions, 327 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cff5864dbbe..8be13e84596 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -674,7 +674,7 @@ checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81"
 dependencies = [
  "serde",
  "termcolor",
- "unicode-width 0.2.1",
+ "unicode-width 0.1.14",
 ]
 
 [[package]]
@@ -1458,9 +1458,9 @@ dependencies = [
 
 [[package]]
 name = "getopts"
-version = "0.2.23"
+version = "0.2.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
+checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"
 dependencies = [
  "unicode-width 0.2.1",
 ]
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 3674814b796..bb6b25baf01 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1536,7 +1536,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::LangItem::Range
                 }
             }
-            (None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
+            (None, Some(..), Closed) => {
+                if self.tcx.features().new_range() {
+                    hir::LangItem::RangeToInclusiveCopy
+                } else {
+                    hir::LangItem::RangeToInclusive
+                }
+            }
             (Some(e1), Some(e2), Closed) => {
                 if self.tcx.features().new_range() {
                     hir::LangItem::RangeInclusiveCopy
@@ -1560,13 +1566,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
 
         let fields = self.arena.alloc_from_iter(
-            e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map(
-                |(s, e)| {
+            e1.iter()
+                .map(|e| (sym::start, e))
+                .chain(e2.iter().map(|e| {
+                    (
+                        if matches!(
+                            lang_item,
+                            hir::LangItem::RangeInclusiveCopy | hir::LangItem::RangeToInclusiveCopy
+                        ) {
+                            sym::last
+                        } else {
+                            sym::end
+                        },
+                        e,
+                    )
+                }))
+                .map(|(s, e)| {
                     let expr = self.lower_expr(e);
                     let ident = Ident::new(s, self.lower_span(e.span));
                     self.expr_field(ident, expr, e.span)
-                },
-            ),
+                }),
         );
 
         hir::ExprKind::Struct(
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index ffdacff7152..d5d51f2e79a 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -218,6 +218,7 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
             sym::rustc_std_internal_symbol,
             // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
             sym::rustc_align,
+            sym::rustc_align_static,
             // obviously compatible with self
             sym::naked,
             // documentation
diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs
index 23aabd15597..0330e2515c7 100644
--- a/compiler/rustc_attr_parsing/src/attributes/repr.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs
@@ -331,3 +331,30 @@ impl<S: Stage> AttributeParser<S> for AlignParser {
         Some(AttributeKind::Align { align, span })
     }
 }
+
+#[derive(Default)]
+pub(crate) struct AlignStaticParser(AlignParser);
+
+impl AlignStaticParser {
+    const PATH: &'static [Symbol] = &[sym::rustc_align_static];
+    const TEMPLATE: AttributeTemplate = AlignParser::TEMPLATE;
+
+    fn parse<'c, S: Stage>(
+        &mut self,
+        cx: &'c mut AcceptContext<'_, '_, S>,
+        args: &'c ArgParser<'_>,
+    ) {
+        self.0.parse(cx, args)
+    }
+}
+
+impl<S: Stage> AttributeParser<S> for AlignStaticParser {
+    const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)];
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Static), Allow(Target::ForeignStatic)]);
+
+    fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
+        let (align, span) = self.0.0?;
+        Some(AttributeKind::Align { align, span })
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 98e86838a3a..d2b35090135 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -50,7 +50,7 @@ use crate::attributes::proc_macro_attrs::{
     ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
 };
 use crate::attributes::prototype::CustomMirParser;
-use crate::attributes::repr::{AlignParser, ReprParser};
+use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
 use crate::attributes::rustc_internal::{
     RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
     RustcObjectLifetimeDefaultParser,
@@ -152,6 +152,7 @@ attribute_parsers!(
     pub(crate) static ATTRIBUTE_PARSERS = [
         // tidy-alphabetical-start
         AlignParser,
+        AlignStaticParser,
         BodyStabilityParser,
         ConfusablesParser,
         ConstStabilityParser,
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 9990f4cb3f2..f57456949bb 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -615,7 +615,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
 
             // Type-test failed. Report the error.
-            let erased_generic_kind = infcx.tcx.erase_regions(type_test.generic_kind);
+            let erased_generic_kind = infcx.tcx.erase_and_anonymize_regions(type_test.generic_kind);
 
             // Skip duplicate-ish errors.
             if deduplicate_errors.insert((
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
index 95c5366a6c8..0af636aa734 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
@@ -341,7 +341,7 @@ fn compute_concrete_types_from_defining_uses<'tcx>(
         //
         // FIXME(-Znext-solver): This isn't necessary after all. We can remove this check again.
         if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
-            rcx.infcx.tcx.erase_regions(opaque_type_key),
+            rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key),
             (opaque_type_key, hidden_type.span),
         ) && let Some((arg1, arg2)) = std::iter::zip(
             prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 02be78f90b0..8c5447fe1e9 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1892,7 +1892,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if is_diverging {
             // The signature in this call can reference region variables,
             // so erase them before calling a query.
-            let output_ty = self.tcx().erase_regions(sig.output());
+            let output_ty = self.tcx().erase_and_anonymize_regions(sig.output());
             if !output_ty
                 .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env))
             {
@@ -1986,7 +1986,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
             let op_arg_ty = self.normalize(op_arg_ty, term_location);
             let category = if call_source.from_hir_call() {
-                ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
+                ConstraintCategory::CallArgument(Some(
+                    self.infcx.tcx.erase_and_anonymize_regions(func_ty),
+                ))
             } else {
                 ConstraintCategory::Boring
             };
@@ -2120,7 +2122,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // Erase the regions from `ty` to get a global type. The
         // `Sized` bound in no way depends on precise regions, so this
         // shouldn't affect `is_sized`.
-        let erased_ty = tcx.erase_regions(ty);
+        let erased_ty = tcx.erase_and_anonymize_regions(ty);
         // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
         if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
             // in current MIR construction, all non-control-flow rvalue
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 619277eba8b..7fe8fc122b3 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -81,6 +81,8 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
         if global.to_rvalue().get_type() != val_llty {
             global.to_rvalue().set_type(val_llty);
         }
+
+        // NOTE: Alignment from attributes has already been applied to the allocation.
         set_global_alignment(self, global, alloc.align);
 
         global.global_set_initializer_rvalue(value);
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 093f902bc3d..93202483eed 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -240,7 +240,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
 
         // Make sure lifetimes are erased, to avoid generating distinct LLVM
         // types for Rust types that only differ in the choice of lifetimes.
-        let normal_ty = cx.tcx.erase_regions(self.ty);
+        let normal_ty = cx.tcx.erase_and_anonymize_regions(self.ty);
 
         let mut defer = None;
         let ty = if self.ty != normal_ty {
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 9ec7b0f80ae..dc9bb743560 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -452,6 +452,8 @@ impl<'ll> CodegenCx<'ll, '_> {
             self.statics_to_rauw.borrow_mut().push((g, new_g));
             new_g
         };
+
+        // NOTE: Alignment from attributes has already been applied to the allocation.
         set_global_alignment(self, g, alloc.align);
         llvm::set_initializer(g, v);
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 1790e212252..dc3a84b6a15 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -1436,7 +1436,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
 
     let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
         let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
-        let trait_ref = tcx.erase_regions(trait_ref);
+        let trait_ref = tcx.erase_and_anonymize_regions(trait_ref);
 
         tcx.vtable_entries(trait_ref)
     } else {
@@ -1563,7 +1563,7 @@ pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
     // Unwrap potential addrspacecast
     let vtable = find_vtable_behind_cast(vtable);
     let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty);
-    let trait_ref_self = cx.tcx.erase_regions(trait_ref_self);
+    let trait_ref_self = cx.tcx.erase_and_anonymize_regions(trait_ref_self);
     let trait_def_id = trait_ref_self.def_id;
     let trait_vis = cx.tcx.visibility(trait_def_id);
 
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 53218340414..84998b5499b 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -231,7 +231,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
 
         // Make sure lifetimes are erased, to avoid generating distinct LLVM
         // types for Rust types that only differ in the choice of lifetimes.
-        let normal_ty = cx.tcx.erase_regions(self.ty);
+        let normal_ty = cx.tcx.erase_and_anonymize_regions(self.ty);
 
         let mut defer = None;
         let llty = if self.ty != normal_ty {
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 6ec85648d6d..ebcdb9461d0 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -953,6 +953,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
 
         // # Global allocations
         if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) {
+            // NOTE: `static` alignment from attributes has already been applied to the allocation.
             let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env);
             let mutbl = global_alloc.mutability(*self.tcx, self.typing_env);
             let kind = match global_alloc {
diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index e4b5c82853a..870f9a396ae 100644
--- a/compiler/rustc_const_eval/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
@@ -23,7 +23,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ) -> InterpResult<'tcx, Pointer<Option<M::Provenance>>> {
         trace!("get_vtable(ty={ty:?}, dyn_ty={dyn_ty:?})");
 
-        let (ty, dyn_ty) = self.tcx.erase_regions((ty, dyn_ty));
+        let (ty, dyn_ty) = self.tcx.erase_and_anonymize_regions((ty, dyn_ty));
 
         // All vtables must be monomorphic, bail out otherwise.
         ensure_monomorphic_enough(*self.tcx, ty)?;
@@ -53,8 +53,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
     ) -> &'tcx [VtblEntry<'tcx>] {
         if let Some(trait_) = trait_ {
             let trait_ref = trait_.with_self_ty(*self.tcx, dyn_ty);
-            let trait_ref =
-                self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_ref));
+            let trait_ref = self.tcx.erase_and_anonymize_regions(
+                self.tcx.instantiate_bound_regions_with_erased(trait_ref),
+            );
             self.tcx.vtable_entries(trait_ref)
         } else {
             TyCtxt::COMMON_VTABLE_ENTRIES
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index 72bee345406..f667823723c 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -1,6 +1,6 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{AllocInit, Allocation, InterpResult, Pointer};
+use rustc_middle::mir::interpret::{AllocInit, Allocation, GlobalAlloc, InterpResult, Pointer};
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{TyCtxt, TypeVisitable, TypeVisitableExt};
 use tracing::debug;
@@ -38,7 +38,14 @@ pub(crate) fn create_static_alloc<'tcx>(
     static_def_id: LocalDefId,
     layout: TyAndLayout<'tcx>,
 ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
-    let alloc = Allocation::try_new(layout.size, layout.align.abi, AllocInit::Uninit, ())?;
+    // Inherit size and align from the `GlobalAlloc::Static` so we can avoid duplicating
+    // the alignment attribute logic.
+    let (size, align) =
+        GlobalAlloc::Static(static_def_id.into()).size_and_align(*ecx.tcx, ecx.typing_env);
+    assert_eq!(size, layout.size);
+    assert!(align >= layout.align.abi);
+
+    let alloc = Allocation::try_new(size, align, AllocInit::Uninit, ())?;
     let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into());
     assert_eq!(ecx.machine.static_root_ids, None);
     ecx.machine.static_root_ids = Some((alloc_id, static_def_id));
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index e81003b1897..129ab7eccb5 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -621,6 +621,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
     gated!(rustc_align, Normal, template!(List: &["alignment"]), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(rustc_align)),
+    gated!(rustc_align_static, Normal, template!(List: &["alignment"]), DuplicatesOk, EncodeCrossCrate::No, static_align, experimental!(rustc_align_static)),
     ungated!(
         unsafe(Edition2024) export_name, Normal,
         template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute"),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 4f35bf63a1a..93e5588146e 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -632,6 +632,8 @@ declare_features! (
     (unstable, simd_ffi, "1.0.0", Some(27731)),
     /// Allows specialization of implementations (RFC 1210).
     (incomplete, specialization, "1.7.0", Some(31844)),
+    /// Allows using `#[rustc_align_static(...)]` on static items.
+    (unstable, static_align, "CURRENT_RUSTC_VERSION", Some(146177)),
     /// Allows attributes on expressions and non-item statements.
     (unstable, stmt_expr_attributes, "1.6.0", Some(15701)),
     /// Allows lints part of the strict provenance effort.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index ae03121e5f7..75551fe4c19 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2616,6 +2616,18 @@ impl Expr<'_> {
             )
             | (
                 ExprKind::Struct(
+                    QPath::LangItem(LangItem::RangeToInclusiveCopy, _),
+                    [val1],
+                    StructTailExpr::None,
+                ),
+                ExprKind::Struct(
+                    QPath::LangItem(LangItem::RangeToInclusiveCopy, _),
+                    [val2],
+                    StructTailExpr::None,
+                ),
+            )
+            | (
+                ExprKind::Struct(
                     QPath::LangItem(LangItem::RangeFrom, _),
                     [val1],
                     StructTailExpr::None,
@@ -2705,7 +2717,8 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
                     | LangItem::RangeToInclusive
                     | LangItem::RangeCopy
                     | LangItem::RangeFromCopy
-                    | LangItem::RangeInclusiveCopy,
+                    | LangItem::RangeInclusiveCopy
+                    | LangItem::RangeToInclusiveCopy,
                 ..
             )
         ),
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 0464665b41f..67d2f15d414 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -422,6 +422,7 @@ language_item_table! {
     RangeFromCopy,           sym::RangeFromCopy,       range_from_copy_struct,     Target::Struct,         GenericRequirement::None;
     RangeCopy,               sym::RangeCopy,           range_copy_struct,          Target::Struct,         GenericRequirement::None;
     RangeInclusiveCopy,      sym::RangeInclusiveCopy,  range_inclusive_copy_struct, Target::Struct,         GenericRequirement::None;
+    RangeToInclusiveCopy,    sym::RangeToInclusiveCopy,     range_to_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
 
     String,                  sym::String,              string,                     Target::Struct,         GenericRequirement::None;
     CStr,                    sym::CStr,                c_str,                      Target::Struct,         GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index b5c0ca4727c..63d0f400aef 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -85,7 +85,9 @@ use rustc_infer::traits::ObligationCause;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::print::with_types_for_signature;
-use rustc_middle::ty::{self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypingMode};
+use rustc_middle::ty::{
+    self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
+};
 use rustc_middle::{bug, span_bug};
 use rustc_session::parse::feature_err;
 use rustc_span::def_id::CRATE_DEF_ID;
@@ -233,8 +235,7 @@ fn missing_items_err(
     };
 
     // Obtain the level of indentation ending in `sugg_sp`.
-    let padding =
-        tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
+    let padding = tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(String::new);
     let (mut missing_trait_item, mut missing_trait_item_none, mut missing_trait_item_label) =
         (Vec::new(), Vec::new(), Vec::new());
 
@@ -331,6 +332,7 @@ fn default_body_is_unstable(
 fn bounds_from_generic_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     predicates: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
+    assoc: ty::AssocItem,
 ) -> (String, String) {
     let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
     let mut projections = vec![];
@@ -354,34 +356,50 @@ fn bounds_from_generic_predicates<'tcx>(
     }
 
     let mut where_clauses = vec![];
-    let mut types_str = vec![];
-    for (ty, bounds) in types {
-        if let ty::Param(_) = ty.kind() {
-            let mut bounds_str = vec![];
-            for bound in bounds {
-                let mut projections_str = vec![];
-                for projection in &projections {
-                    let p = projection.skip_binder();
-                    if bound == tcx.parent(p.projection_term.def_id)
-                        && p.projection_term.self_ty() == ty
-                    {
-                        let name = tcx.item_name(p.projection_term.def_id);
-                        projections_str.push(format!("{} = {}", name, p.term));
+    let generics = tcx.generics_of(assoc.def_id);
+    let types_str = generics
+        .own_params
+        .iter()
+        .filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
+        .map(|p| {
+            // we just checked that it's a type, so the unwrap can't fail
+            let ty = tcx.mk_param_from_def(p).as_type().unwrap();
+            if let Some(bounds) = types.get(&ty) {
+                let mut bounds_str = vec![];
+                for bound in bounds.iter().copied() {
+                    let mut projections_str = vec![];
+                    for projection in &projections {
+                        let p = projection.skip_binder();
+                        if bound == tcx.parent(p.projection_term.def_id)
+                            && p.projection_term.self_ty() == ty
+                        {
+                            let name = tcx.item_name(p.projection_term.def_id);
+                            projections_str.push(format!("{} = {}", name, p.term));
+                        }
+                    }
+                    let bound_def_path = tcx.def_path_str(bound);
+                    if projections_str.is_empty() {
+                        where_clauses.push(format!("{}: {}", ty, bound_def_path));
+                    } else {
+                        bounds_str.push(format!(
+                            "{}<{}>",
+                            bound_def_path,
+                            projections_str.join(", ")
+                        ));
                     }
                 }
-                let bound_def_path = tcx.def_path_str(bound);
-                if projections_str.is_empty() {
-                    where_clauses.push(format!("{}: {}", ty, bound_def_path));
+                if bounds_str.is_empty() {
+                    ty.to_string()
                 } else {
-                    bounds_str.push(format!("{}<{}>", bound_def_path, projections_str.join(", ")));
+                    format!("{}: {}", ty, bounds_str.join(" + "))
                 }
-            }
-            if bounds_str.is_empty() {
-                types_str.push(ty.to_string());
             } else {
-                types_str.push(format!("{}: {}", ty, bounds_str.join(" + ")));
+                ty.to_string()
             }
-        } else {
+        })
+        .collect::<Vec<_>>();
+    for (ty, bounds) in types.into_iter() {
+        if !matches!(ty.kind(), ty::Param(_)) {
             // Avoid suggesting the following:
             // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
             where_clauses.extend(
@@ -473,10 +491,10 @@ fn fn_sig_suggestion<'tcx>(
     let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
 
     let safety = sig.safety.prefix_str();
-    let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates);
+    let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates, assoc);
 
     // FIXME: this is not entirely correct, as the lifetimes from borrowed params will
-    // not be present in the `fn` definition, not will we account for renamed
+    // not be present in the `fn` definition, nor will we account for renamed
     // lifetimes between the `impl` and the `trait`, but this should be good enough to
     // fill in a significant portion of the missing code, and other subsequent
     // suggestions can help the user fix the code.
@@ -512,6 +530,7 @@ fn suggestion_signature<'tcx>(
             let (generics, where_clauses) = bounds_from_generic_predicates(
                 tcx,
                 tcx.predicates_of(assoc.def_id).instantiate_own(tcx, args),
+                assoc,
             );
             format!("type {}{generics} = /* Type */{where_clauses};", assoc.name())
         }
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index e6a1f6d8d8b..22a9446fd4c 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1047,7 +1047,7 @@ fn check_type_defn<'tcx>(
             let needs_drop_copy = || {
                 packed && {
                     let ty = tcx.type_of(variant.tail().did).instantiate_identity();
-                    let ty = tcx.erase_regions(ty);
+                    let ty = tcx.erase_and_anonymize_regions(ty);
                     assert!(!ty.has_infer());
                     ty.needs_drop(tcx, wfcx.infcx.typing_env(wfcx.param_env))
                 }
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index f707196c816..621431ae234 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -404,7 +404,7 @@ fn emit_orphan_check_error<'tcx>(
                     of_trait.trait_ref.path.span
                 };
 
-                ty = tcx.erase_regions(ty);
+                ty = tcx.erase_and_anonymize_regions(ty);
 
                 let is_foreign =
                     !trait_ref.def_id.is_local() && matches!(is_target_ty, IsFirstInputType::No);
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 93b82acf621..0cf9cb7193f 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -482,7 +482,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 .map(|header| header.trait_ref.instantiate_identity().self_ty())
                 // We don't care about blanket impls.
                 .filter(|self_ty| !self_ty.has_non_region_param())
-                .map(|self_ty| tcx.erase_regions(self_ty).to_string())
+                .map(|self_ty| tcx.erase_and_anonymize_regions(self_ty).to_string())
                 .collect()
         };
         // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 3eeb0eac023..27540fd1a43 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -851,8 +851,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         debug!("check_ptr_ptr_cast m_src={m_src:?} m_dst={m_dst:?}");
         // ptr-ptr cast. metadata must match.
 
-        let src_kind = fcx.tcx.erase_regions(fcx.pointer_kind(m_src.ty, self.span)?);
-        let dst_kind = fcx.tcx.erase_regions(fcx.pointer_kind(m_dst.ty, self.span)?);
+        let src_kind = fcx.tcx.erase_and_anonymize_regions(fcx.pointer_kind(m_src.ty, self.span)?);
+        let dst_kind = fcx.tcx.erase_and_anonymize_regions(fcx.pointer_kind(m_dst.ty, self.span)?);
 
         // We can't cast if target pointer kind is unknown
         let Some(dst_kind) = dst_kind else {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 84ea2ec0f8a..d7ddbcc8b53 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1358,7 +1358,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .infcx
                 .type_implements_trait(
                     clone_trait_def,
-                    [self.tcx.erase_regions(expected_ty)],
+                    [self.tcx.erase_and_anonymize_regions(expected_ty)],
                     self.param_env,
                 )
                 .must_apply_modulo_regions()
diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs
index b59c1752c25..c0cd23be690 100644
--- a/compiler/rustc_hir_typeck/src/inline_asm.rs
+++ b/compiler/rustc_hir_typeck/src/inline_asm.rs
@@ -44,7 +44,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
         if ty.has_non_region_infer() {
             Ty::new_misc_error(self.tcx())
         } else {
-            self.tcx().erase_regions(ty)
+            self.tcx().erase_and_anonymize_regions(ty)
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index d75bc9edab2..90301d1b391 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -802,7 +802,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                         format!("unexpected inference variable after writeback: {predicate:?}"),
                     );
                 } else {
-                    let predicate = self.tcx().erase_regions(predicate);
+                    let predicate = self.tcx().erase_and_anonymize_regions(predicate);
                     if cause.has_infer() || cause.has_placeholders() {
                         // We can't use the the obligation cause as it references
                         // information local to this query.
@@ -984,8 +984,8 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         // borrowck, and specifically region constraints will be populated during
         // MIR typeck which is run on the new body.
         //
-        // We're not using `tcx.erase_regions` as that also anonymizes bound variables,
-        // regressing borrowck diagnostics.
+        // We're not using `tcx.erase_and_anonymize_regions` as that also
+        // anonymizes bound variables, regressing borrowck diagnostics.
         value = fold_regions(tcx, value, |_, _| tcx.lifetimes.re_erased);
 
         // Normalize consts in writeback, because GCE doesn't normalize eagerly.
diff --git a/compiler/rustc_index/src/idx.rs b/compiler/rustc_index/src/idx.rs
index 33f406e2113..9cd7134659c 100644
--- a/compiler/rustc_index/src/idx.rs
+++ b/compiler/rustc_index/src/idx.rs
@@ -130,7 +130,22 @@ impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeFrom<I> {
 impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
     type Output = core::range::RangeInclusive<usize>;
     #[inline]
+    #[cfg(bootstrap)]
     fn into_slice_idx(self) -> Self::Output {
         core::range::RangeInclusive { start: self.start.index(), end: self.end.index() }
     }
+    #[inline]
+    #[cfg(not(bootstrap))]
+    fn into_slice_idx(self) -> Self::Output {
+        core::range::RangeInclusive { start: self.start.index(), last: self.last.index() }
+    }
+}
+
+#[cfg(all(feature = "nightly", not(bootstrap)))]
+impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeToInclusive<I> {
+    type Output = core::range::RangeToInclusive<usize>;
+    #[inline]
+    fn into_slice_idx(self) -> Self::Output {
+        core::range::RangeToInclusive { last: self.last.index() }
+    }
 }
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index bfdd282d7e1..f06eb58a371 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -76,7 +76,7 @@ pub(super) fn can_match_erased_ty<'tcx>(
     erased_ty: Ty<'tcx>,
 ) -> bool {
     assert!(!outlives_predicate.has_escaping_bound_vars());
-    let erased_outlives_predicate = tcx.erase_regions(outlives_predicate);
+    let erased_outlives_predicate = tcx.erase_and_anonymize_regions(outlives_predicate);
     let outlives_ty = erased_outlives_predicate.skip_binder().0;
     if outlives_ty == erased_ty {
         // pointless micro-optimization
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 69feecfe30a..f67b99cb3f8 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -96,7 +96,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         &self,
         alias_ty: ty::AliasTy<'tcx>,
     ) -> Vec<ty::PolyTypeOutlivesPredicate<'tcx>> {
-        let erased_alias_ty = self.tcx.erase_regions(alias_ty.to_ty(self.tcx));
+        let erased_alias_ty = self.tcx.erase_and_anonymize_regions(alias_ty.to_ty(self.tcx));
         self.declared_generic_bounds_from_env_for_erased_ty(erased_alias_ty)
     }
 
@@ -241,7 +241,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
             }
 
             let p_ty = p.to_ty(tcx);
-            let erased_p_ty = self.tcx.erase_regions(p_ty);
+            let erased_p_ty = self.tcx.erase_and_anonymize_regions(p_ty);
             (erased_p_ty == erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r)))
         }));
 
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index 943fcc0801b..e1c51ff8299 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
         {
             // erase regions in self type for better diagnostic presentation
             let (self_ty, target_principal, supertrait_principal) =
-                tcx.erase_regions((self_ty, target_principal, supertrait_principal));
+                tcx.erase_and_anonymize_regions((self_ty, target_principal, supertrait_principal));
             let label2 = tcx
                 .associated_items(item.owner_id)
                 .find_by_ident_and_kind(
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index a56b753bda7..9e1fc598171 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -176,7 +176,7 @@ fn suggest_question_mark<'tcx>(
         cause,
         param_env,
         // Erase any region vids from the type, which may not be resolved
-        infcx.tcx.erase_regions(ty),
+        infcx.tcx.erase_and_anonymize_regions(ty),
         into_iterator_did,
     );
 
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index a72b802eb5d..88527fa2e6e 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -935,7 +935,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
         if let hir::ItemKind::Enum(_, _, ref enum_definition) = it.kind {
             let t = cx.tcx.type_of(it.owner_id).instantiate_identity();
-            let ty = cx.tcx.erase_regions(t);
+            let ty = cx.tcx.erase_and_anonymize_regions(t);
             let Ok(layout) = cx.layout_of(ty) else { return };
             let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, variants, .. } =
                 &layout.variants
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index bed99a4ff2a..9762e0f21da 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -386,7 +386,16 @@ impl<'tcx> GlobalAlloc<'tcx> {
                         .expect("statics should not have generic parameters");
                     let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap();
                     assert!(layout.is_sized());
-                    (layout.size, layout.align.abi)
+
+                    // Take over-alignment from attributes into account.
+                    let align = match tcx.codegen_fn_attrs(def_id).alignment {
+                        Some(align_from_attribute) => {
+                            Ord::max(align_from_attribute, layout.align.abi)
+                        }
+                        None => layout.align.abi,
+                    };
+
+                    (layout.size, align)
                 }
             }
             GlobalAlloc::Memory(alloc) => {
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index e25f35c59c2..ecf35d9dd6d 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -41,7 +41,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let instance = ty::Instance::new_raw(def_id, args);
         let cid = GlobalId { instance, promoted: None };
         let typing_env = ty::TypingEnv::post_analysis(self, def_id);
-        let inputs = self.erase_regions(typing_env.as_query_input(cid));
+        let inputs = self.erase_and_anonymize_regions(typing_env.as_query_input(cid));
         self.eval_to_allocation_raw(inputs)
     }
 
@@ -172,8 +172,9 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> EvalToConstValueResult<'tcx> {
         // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
         // improve caching of queries.
-        let inputs =
-            self.erase_regions(typing_env.with_post_analysis_normalized(self).as_query_input(cid));
+        let inputs = self.erase_and_anonymize_regions(
+            typing_env.with_post_analysis_normalized(self).as_query_input(cid),
+        );
         if !span.is_dummy() {
             // The query doesn't know where it is being invoked, so we need to fix the span.
             self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span))
@@ -192,8 +193,9 @@ impl<'tcx> TyCtxt<'tcx> {
     ) -> ConstToValTreeResult<'tcx> {
         // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
         // improve caching of queries.
-        let inputs =
-            self.erase_regions(typing_env.with_post_analysis_normalized(self).as_query_input(cid));
+        let inputs = self.erase_and_anonymize_regions(
+            typing_env.with_post_analysis_normalized(self).as_query_input(cid),
+        );
         debug!(?inputs);
         let res = if !span.is_dummy() {
             // The query doesn't know where it is being invoked, so we need to fix the span.
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 8fba218cc71..2aa32dfa0d8 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -761,9 +761,9 @@ rustc_queries! {
     }
 
     /// Erases regions from `ty` to yield a new type.
-    /// Normally you would just use `tcx.erase_regions(value)`,
+    /// Normally you would just use `tcx.erase_and_anonymize_regions(value)`,
     /// however, which uses this query as a kind of cache.
-    query erase_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> {
+    query erase_and_anonymize_regions_ty(ty: Ty<'tcx>) -> Ty<'tcx> {
         // This query is not expected to have input -- as a result, it
         // is not a good candidates for "replay" because it is essentially a
         // pure function of its input (and hence the expectation is that
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index c9b9ec771b3..463e4c58805 100644
--- a/compiler/rustc_middle/src/ty/abstract_const.rs
+++ b/compiler/rustc_middle/src/ty/abstract_const.rs
@@ -55,7 +55,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) {
                         Err(e) => ty::Const::new_error(self.tcx, e),
                         Ok(Some(bac)) => {
-                            let args = self.tcx.erase_regions(uv.args);
+                            let args = self.tcx.erase_and_anonymize_regions(uv.args);
                             let bac = bac.instantiate(self.tcx, args);
                             return bac.fold_with(self);
                         }
diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs
index f4fead7e952..74b4adda7fd 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -6,20 +6,20 @@ use crate::ty::{
 };
 
 pub(super) fn provide(providers: &mut Providers) {
-    *providers = Providers { erase_regions_ty, ..*providers };
+    *providers = Providers { erase_and_anonymize_regions_ty, ..*providers };
 }
 
-fn erase_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+fn erase_and_anonymize_regions_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     // N.B., use `super_fold_with` here. If we used `fold_with`, it
-    // could invoke the `erase_regions_ty` query recursively.
-    ty.super_fold_with(&mut RegionEraserVisitor { tcx })
+    // could invoke the `erase_and_anonymize_regions_ty` query recursively.
+    ty.super_fold_with(&mut RegionEraserAndAnonymizerVisitor { tcx })
 }
 
 impl<'tcx> TyCtxt<'tcx> {
-    /// Returns an equivalent value with all free regions removed (note
-    /// that late-bound regions remain, because they are important for
-    /// subtyping, but they are anonymized and normalized as well)..
-    pub fn erase_regions<T>(self, value: T) -> T
+    /// Returns an equivalent value with all free regions removed and
+    /// bound regions anonymized. (note that bound regions are important
+    /// for subtyping and generally type equality so *cannot* be removed)
+    pub fn erase_and_anonymize_regions<T>(self, value: T) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
     {
@@ -27,18 +27,18 @@ impl<'tcx> TyCtxt<'tcx> {
         if !value.has_type_flags(TypeFlags::HAS_BINDER_VARS | TypeFlags::HAS_FREE_REGIONS) {
             return value;
         }
-        debug!("erase_regions({:?})", value);
-        let value1 = value.fold_with(&mut RegionEraserVisitor { tcx: self });
-        debug!("erase_regions = {:?}", value1);
+        debug!("erase_and_anonymize_regions({:?})", value);
+        let value1 = value.fold_with(&mut RegionEraserAndAnonymizerVisitor { tcx: self });
+        debug!("erase_and_anonymize_regions = {:?}", value1);
         value1
     }
 }
 
-struct RegionEraserVisitor<'tcx> {
+struct RegionEraserAndAnonymizerVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
 }
 
-impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserAndAnonymizerVisitor<'tcx> {
     fn cx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -49,7 +49,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
         } else if ty.has_infer() {
             ty.super_fold_with(self)
         } else {
-            self.tcx.erase_regions_ty(ty)
+            self.tcx.erase_and_anonymize_regions_ty(ty)
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 3a51f79f121..e76993e0542 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -544,7 +544,9 @@ impl<'tcx> Instance<'tcx> {
 
         // All regions in the result of this query are erased, so it's
         // fine to erase all of the input regions.
-        tcx.resolve_instance_raw(tcx.erase_regions(typing_env.as_query_input((def_id, args))))
+        tcx.resolve_instance_raw(
+            tcx.erase_and_anonymize_regions(typing_env.as_query_input((def_id, args))),
+        )
     }
 
     pub fn expect_resolve(
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index aed94f9aa04..2114d080dfa 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -401,7 +401,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
                 match tail.kind() {
                     ty::Param(_) | ty::Alias(ty::Projection | ty::Inherent, _) => {
                         debug_assert!(tail.has_non_region_param());
-                        Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
+                        Ok(SizeSkeleton::Pointer {
+                            non_zero,
+                            tail: tcx.erase_and_anonymize_regions(tail),
+                        })
                     }
                     ty::Error(guar) => {
                         // Fixes ICE #124031
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index f2a4a5a4ecf..69c1eb9b345 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -51,7 +51,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         // Erase first before we do the real query -- this keeps the
         // cache from being too polluted.
-        let value = self.erase_regions(value);
+        let value = self.erase_and_anonymize_regions(value);
         debug!(?value);
 
         if !value.has_aliases() {
@@ -83,7 +83,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         // Erase first before we do the real query -- this keeps the
         // cache from being too polluted.
-        let value = self.erase_regions(value);
+        let value = self.erase_and_anonymize_regions(value);
         debug!(?value);
 
         if !value.has_aliases() {
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 8101cabccdd..fc821ffdaa6 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1436,8 +1436,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                                 // anonymized regions, but the super projections can still
                                 // contain named regions. So we erase and anonymize everything
                                 // here to compare the types modulo regions below.
-                                let proj = p.tcx().erase_regions(proj);
-                                let super_proj = p.tcx().erase_regions(super_proj);
+                                let proj = p.tcx().erase_and_anonymize_regions(proj);
+                                let super_proj = p.tcx().erase_and_anonymize_regions(super_proj);
 
                                 proj == super_proj
                             });
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index b8c99e83a8f..96fbdf44791 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -131,10 +131,9 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Creates a hash of the type `Ty` which will be the same no matter what crate
     /// context it's calculated within. This is used by the `type_id` intrinsic.
     pub fn type_id_hash(self, ty: Ty<'tcx>) -> Hash128 {
-        // We want the type_id be independent of the types free regions, so we
-        // erase them. The erase_regions() call will also anonymize bound
-        // regions, which is desirable too.
-        let ty = self.erase_regions(ty);
+        // We don't have region information, so we erase all free regions. Equal types
+        // must have the same `TypeId`, so we must anonymize all bound regions as well.
+        let ty = self.erase_and_anonymize_regions(ty);
 
         self.with_stable_hashing_context(|mut hcx| {
             let mut hasher = StableHasher::new();
@@ -1309,7 +1308,7 @@ impl<'tcx> Ty<'tcx> {
                 debug_assert!(!typing_env.param_env.has_infer());
                 let query_ty = tcx
                     .try_normalize_erasing_regions(typing_env, query_ty)
-                    .unwrap_or_else(|_| tcx.erase_regions(query_ty));
+                    .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(query_ty));
 
                 tcx.needs_drop_raw(typing_env.as_query_input(query_ty))
             }
@@ -1346,7 +1345,7 @@ impl<'tcx> Ty<'tcx> {
                 debug_assert!(!typing_env.has_infer());
                 let query_ty = tcx
                     .try_normalize_erasing_regions(typing_env, query_ty)
-                    .unwrap_or_else(|_| tcx.erase_regions(query_ty));
+                    .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(query_ty));
 
                 tcx.needs_async_drop_raw(typing_env.as_query_input(query_ty))
             }
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index 6fc19c82342..e2f09fdcb4b 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -89,7 +89,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
 
     let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
         let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
-        let trait_ref = tcx.erase_regions(trait_ref);
+        let trait_ref = tcx.erase_and_anonymize_regions(trait_ref);
 
         tcx.vtable_entries(trait_ref)
     } else {
diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs
index e0cbe8519ed..d40c77d145f 100644
--- a/compiler/rustc_mir_build/src/check_tail_calls.rs
+++ b/compiler/rustc_mir_build/src/check_tail_calls.rs
@@ -64,10 +64,10 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
                 "`become` outside of functions should have been disallowed by hir_typeck"
             )
         };
-        // While the `caller_sig` does have its regions erased, it does not have its
-        // binders anonymized. We call `erase_regions` once again to anonymize any binders
+        // While the `caller_sig` does have its free regions erased, it does not have its
+        // binders anonymized. We call `erase_and_anonymize_regions` once again to anonymize any binders
         // within the signature, such as in function pointer or `dyn Trait` args.
-        let caller_sig = self.tcx.erase_regions(caller_sig);
+        let caller_sig = self.tcx.erase_and_anonymize_regions(caller_sig);
 
         let ExprKind::Scope { value, .. } = call.kind else {
             span_bug!(call.span, "expected scope, found: {call:?}")
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 81b0e21a5f5..0b9bc018a09 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -792,10 +792,9 @@ impl<'tcx> ThirBuildCx<'tcx> {
                             let ty = self.typeck_results.node_type(anon_const.hir_id);
                             let did = anon_const.def_id.to_def_id();
                             let typeck_root_def_id = tcx.typeck_root_def_id(did);
-                            let parent_args = tcx.erase_regions(GenericArgs::identity_for_item(
-                                tcx,
-                                typeck_root_def_id,
-                            ));
+                            let parent_args = tcx.erase_and_anonymize_regions(
+                                GenericArgs::identity_for_item(tcx, typeck_root_def_id),
+                            );
                             let args =
                                 InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty })
                                     .args;
@@ -831,8 +830,10 @@ impl<'tcx> ThirBuildCx<'tcx> {
                 let ty = self.typeck_results.node_type(anon_const.hir_id);
                 let did = anon_const.def_id.to_def_id();
                 let typeck_root_def_id = tcx.typeck_root_def_id(did);
-                let parent_args =
-                    tcx.erase_regions(GenericArgs::identity_for_item(tcx, typeck_root_def_id));
+                let parent_args = tcx.erase_and_anonymize_regions(GenericArgs::identity_for_item(
+                    tcx,
+                    typeck_root_def_id,
+                ));
                 let args = InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty }).args;
 
                 ExprKind::ConstBlock { did, args }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index d46c4678bcf..6316ccf1b8c 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -105,9 +105,11 @@ impl<'tcx> ConstToPat<'tcx> {
         //
         // FIXME: `const_eval_resolve_for_typeck` should probably just modify the env itself
         // instead of having this logic here
-        let typing_env =
-            self.tcx.erase_regions(self.typing_env).with_post_analysis_normalized(self.tcx);
-        let uv = self.tcx.erase_regions(uv);
+        let typing_env = self
+            .tcx
+            .erase_and_anonymize_regions(self.typing_env)
+            .with_post_analysis_normalized(self.tcx);
+        let uv = self.tcx.erase_and_anonymize_regions(uv);
 
         // try to resolve e.g. associated constants to their definition on an impl, and then
         // evaluate the const.
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 9a00831dc01..bf5ec8f459e 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -891,7 +891,7 @@ pub fn iter_fields<'tcx>(
                     let field_ty = f_def.ty(tcx, args);
                     let field_ty = tcx
                         .try_normalize_erasing_regions(typing_env, field_ty)
-                        .unwrap_or_else(|_| tcx.erase_regions(field_ty));
+                        .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(field_ty));
                     f(variant, f_index.into(), field_ty);
                 }
             }
diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
index 92ee80eaa35..be4f84d64d0 100644
--- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
+++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
@@ -32,8 +32,8 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> {
         let mut rval_ty = rvalue.ty(self.local_decls, self.tcx);
         // Not erasing this causes `Free Regions` errors in validator,
         // when rval is `ReStatic`.
-        rval_ty = self.tcx.erase_regions(rval_ty);
-        place_ty = self.tcx.erase_regions(place_ty);
+        rval_ty = self.tcx.erase_and_anonymize_regions(rval_ty);
+        place_ty = self.tcx.erase_and_anonymize_regions(place_ty);
         if place_ty != rval_ty {
             let temp = self
                 .patcher
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index 462ddfa3dd3..9ea2eb4f25d 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -875,7 +875,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             let mut promoted_operand = |ty, span| {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
-                let args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def));
+                let args =
+                    tcx.erase_and_anonymize_regions(GenericArgs::identity_for_item(tcx, def));
                 let uneval =
                     mir::UnevaluatedConst { def, args, promoted: Some(next_promoted_index) };
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 3169f2d4e1a..378d71cb1fc 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1558,7 +1558,7 @@ impl<'v> RootCollector<'_, 'v> {
                         ty::Closure(def_id, args)
                         | ty::Coroutine(def_id, args)
                         | ty::CoroutineClosure(def_id, args) => {
-                            Instance::new_raw(def_id, self.tcx.erase_regions(args))
+                            Instance::new_raw(def_id, self.tcx.erase_and_anonymize_regions(args))
                         }
                         _ => unreachable!(),
                     };
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 77dd313d9b8..72cd75f6d89 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -479,9 +479,6 @@ parse_invalid_identifier_with_leading_number = identifiers cannot start with a n
 
 parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid
     .label = invalid suffix `{$suffix}`
-    .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
-    .tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
-    .tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
 
 parse_invalid_logical_operator = `{$incorrect}` is not a logical operator
     .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 797d4830c2f..00ca5acd84d 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1017,10 +1017,6 @@ pub(crate) struct InvalidLiteralSuffixOnTupleIndex {
     #[label]
     pub span: Span,
     pub suffix: Symbol,
-    #[help(parse_tuple_exception_line_1)]
-    #[help(parse_tuple_exception_line_2)]
-    #[help(parse_tuple_exception_line_3)]
-    pub exception: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 4c02547357e..81a5d48d94e 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1163,7 +1163,10 @@ impl<'a> Parser<'a> {
                         suffix,
                     }) => {
                         if let Some(suffix) = suffix {
-                            self.expect_no_tuple_index_suffix(current.span, suffix);
+                            self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
+                                span: current.span,
+                                suffix,
+                            });
                         }
                         match self.break_up_float(symbol, current.span) {
                             // 1e2
@@ -1239,7 +1242,8 @@ impl<'a> Parser<'a> {
         suffix: Option<Symbol>,
     ) -> Box<Expr> {
         if let Some(suffix) = suffix {
-            self.expect_no_tuple_index_suffix(ident_span, suffix);
+            self.dcx()
+                .emit_err(errors::InvalidLiteralSuffixOnTupleIndex { span: ident_span, suffix });
         }
         self.mk_expr(lo.to(ident_span), ExprKind::Field(base, Ident::new(field, ident_span)))
     }
@@ -2225,24 +2229,6 @@ impl<'a> Parser<'a> {
         })
     }
 
-    pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) {
-        if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) {
-            // #59553: warn instead of reject out of hand to allow the fix to percolate
-            // through the ecosystem when people fix their macros
-            self.dcx().emit_warn(errors::InvalidLiteralSuffixOnTupleIndex {
-                span,
-                suffix,
-                exception: true,
-            });
-        } else {
-            self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
-                span,
-                suffix,
-                exception: false,
-            });
-        }
-    }
-
     /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
     /// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
     pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, Box<Expr>> {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 3bbca622975..ed4069dae93 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1335,7 +1335,10 @@ impl<'a> Parser<'a> {
         if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind
         {
             if let Some(suffix) = suffix {
-                self.expect_no_tuple_index_suffix(self.token.span, suffix);
+                self.dcx().emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
+                    span: self.token.span,
+                    suffix,
+                });
             }
             self.bump();
             Ok(Ident::new(symbol, self.prev_token.span))
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index afd08319738..ab7885905a6 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -501,6 +501,10 @@ passes_repr_align_should_be_align =
     `#[repr(align(...))]` is not supported on {$item}
     .help = use `#[rustc_align(...)]` instead
 
+passes_repr_align_should_be_align_static =
+    `#[repr(align(...))]` is not supported on {$item}
+    .help = use `#[rustc_align_static(...)]` instead
+
 passes_repr_conflicting =
     conflicting representation hints
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 487bdd2a888..38a6b4b16c9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1606,12 +1606,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 ReprAttr::ReprAlign(align) => {
                     match target {
                         Target::Struct | Target::Union | Target::Enum => {}
-                        Target::Fn | Target::Method(_) => {
+                        Target::Fn | Target::Method(_) if self.tcx.features().fn_align() => {
                             self.dcx().emit_err(errors::ReprAlignShouldBeAlign {
                                 span: *repr_span,
                                 item: target.plural_name(),
                             });
                         }
+                        Target::Static if self.tcx.features().static_align() => {
+                            self.dcx().emit_err(errors::ReprAlignShouldBeAlignStatic {
+                                span: *repr_span,
+                                item: target.plural_name(),
+                            });
+                        }
                         _ => {
                             self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
                                 hint_span: *repr_span,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 23dcabef1a1..2da4b6f52cf 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1610,6 +1610,15 @@ pub(crate) struct ReprAlignShouldBeAlign {
 }
 
 #[derive(Diagnostic)]
+#[diag(passes_repr_align_should_be_align_static)]
+pub(crate) struct ReprAlignShouldBeAlignStatic {
+    #[primary_span]
+    #[help]
+    pub span: Span,
+    pub item: &'static str,
+}
+
+#[derive(Diagnostic)]
 #[diag(passes_custom_mir_phase_requires_dialect)]
 pub(crate) struct CustomMirPhaseRequiresDialect {
     #[primary_span]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index e5108d8b7e9..e21ff83c400 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -326,6 +326,7 @@ symbols! {
         RangeSub,
         RangeTo,
         RangeToInclusive,
+        RangeToInclusiveCopy,
         Rc,
         RcWeak,
         Ready,
@@ -1280,6 +1281,7 @@ symbols! {
         lang,
         lang_items,
         large_assignments,
+        last,
         lateout,
         lazy_normalization_consts,
         lazy_type_alias,
@@ -1846,6 +1848,7 @@ symbols! {
         rustc_abi,
         // FIXME(#82232, #143834): temporary name to mitigate `#[align]` nameres ambiguity
         rustc_align,
+        rustc_align_static,
         rustc_allocator,
         rustc_allocator_zeroed,
         rustc_allocator_zeroed_variant,
@@ -2097,6 +2100,7 @@ symbols! {
         staged_api,
         start,
         state,
+        static_align,
         static_in_const,
         static_nobundle,
         static_recursion,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 4d9741f1d11..95a7ec61868 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -54,7 +54,7 @@ pub(super) fn mangle<'tcx>(
 
     // Erase regions because they may not be deterministic when hashed
     // and should not matter anyhow.
-    let instance_ty = tcx.erase_regions(instance_ty);
+    let instance_ty = tcx.erase_and_anonymize_regions(instance_ty);
 
     let hash = get_symbol_hash(tcx, instance, instance_ty, instantiating_crate);
 
@@ -422,7 +422,10 @@ impl<'tcx> Printer<'tcx> for LegacySymbolMangler<'tcx> {
             || &args[..generics.count()]
                 == self
                     .tcx
-                    .erase_regions(ty::GenericArgs::identity_for_item(self.tcx, impl_def_id))
+                    .erase_and_anonymize_regions(ty::GenericArgs::identity_for_item(
+                        self.tcx,
+                        impl_def_id,
+                    ))
                     .as_slice()
         {
             (
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index 0c6d1495e39..50935e7caf3 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -58,7 +58,7 @@ impl SymbolNamesTest<'_> {
             let def_id = def_id.to_def_id();
             let instance = Instance::new_raw(
                 def_id,
-                tcx.erase_regions(GenericArgs::identity_for_item(tcx, def_id)),
+                tcx.erase_and_anonymize_regions(GenericArgs::identity_for_item(tcx, def_id)),
             );
             let mangled = tcx.symbol_name(instance);
             tcx.dcx().emit_err(TestOutput {
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 0655c2d5e81..1605b4958ba 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -329,7 +329,10 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> {
             || &args[..generics.count()]
                 == self
                     .tcx
-                    .erase_regions(ty::GenericArgs::identity_for_item(self.tcx, impl_def_id))
+                    .erase_and_anonymize_regions(ty::GenericArgs::identity_for_item(
+                        self.tcx,
+                        impl_def_id,
+                    ))
                     .as_slice()
         {
             (
@@ -339,7 +342,7 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> {
             )
         } else {
             assert!(
-                !args.has_non_region_param(),
+                !args.has_non_region_param() && !args.has_free_regions(),
                 "should not be mangling partially substituted \
                 polymorphic instance: {impl_def_id:?} {args:?}"
             );
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index d3a17232a40..d71110521ff 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -1616,8 +1616,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             && let Some((e, f)) = values.ty()
             && let TypeError::ArgumentSorts(..) | TypeError::Sorts(_) = terr
         {
-            let e = self.tcx.erase_regions(e);
-            let f = self.tcx.erase_regions(f);
+            let e = self.tcx.erase_and_anonymize_regions(e);
+            let f = self.tcx.erase_and_anonymize_regions(f);
             let mut expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
             let mut found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
             if let ObligationCauseCode::Pattern { span, .. } = cause.code()
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index 40285e5d0e9..e042ce84955 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -629,7 +629,11 @@ impl<T> Trait<T> for X {
         let tcx = self.tcx;
 
         // Don't suggest constraining a projection to something containing itself
-        if self.tcx.erase_regions(values.found).contains(self.tcx.erase_regions(values.expected)) {
+        if self
+            .tcx
+            .erase_and_anonymize_regions(values.found)
+            .contains(self.tcx.erase_and_anonymize_regions(values.expected))
+        {
             return;
         }
 
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index bc984f30472..c82043f0222 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -75,7 +75,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 {
                     if let Some(cause) = self
                         .tcx
-                        .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc))
+                        .diagnostic_hir_wf_check((tcx.erase_and_anonymize_regions(obligation.predicate), *wf_loc))
                     {
                         obligation.cause = cause.clone();
                         span = obligation.cause.span;
@@ -2612,8 +2612,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
 
             // Erase regions because layout code doesn't particularly care about regions.
-            let trait_pred =
-                self.tcx.erase_regions(self.tcx.instantiate_bound_regions_with_erased(trait_pred));
+            let trait_pred = self.tcx.erase_and_anonymize_regions(
+                self.tcx.instantiate_bound_regions_with_erased(trait_pred),
+            );
 
             let src_and_dst = rustc_transmute::Types {
                 dst: trait_pred.trait_ref.args.type_at(0),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index f6dbbeb51ca..cb84d583e6e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -2442,7 +2442,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         // Look for a type inside the coroutine interior that matches the target type to get
         // a span.
-        let target_ty_erased = self.tcx.erase_regions(target_ty);
+        let target_ty_erased = self.tcx.erase_and_anonymize_regions(target_ty);
         let ty_matches = |ty| -> bool {
             // Careful: the regions for types that appear in the
             // coroutine interior are not generally known, so we
@@ -2454,10 +2454,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             // interior generally contain "bound regions" to
             // represent regions that are part of the suspended
             // coroutine frame. Bound regions are preserved by
-            // `erase_regions` and so we must also call
+            // `erase_and_anonymize_regions` and so we must also call
             // `instantiate_bound_regions_with_erased`.
             let ty_erased = self.tcx.instantiate_bound_regions_with_erased(ty);
-            let ty_erased = self.tcx.erase_regions(ty_erased);
+            let ty_erased = self.tcx.erase_and_anonymize_regions(ty_erased);
             let eq = ty_erased == target_ty_erased;
             debug!(?ty_erased, ?target_ty_erased, ?eq);
             eq
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index 16f444486a6..b6bdf1067a3 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -300,7 +300,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
     ) -> Result<Certainty, NoSolution> {
         // Erase regions because we compute layouts in `rustc_transmute`,
         // which will ICE for region vars.
-        let (dst, src) = self.tcx.erase_regions((dst, src));
+        let (dst, src) = self.tcx.erase_and_anonymize_regions((dst, src));
 
         let Some(assume) = rustc_transmute::Assume::from_const(self.tcx, assume) else {
             return Err(NoSolution);
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index 4b493c95d59..bcd11d6918d 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -759,7 +759,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IllegalSelfTypeVisitor<'tcx> {
                                     )),
                                 )
                                 .map(|trait_ref| {
-                                    self.tcx.erase_regions(
+                                    self.tcx.erase_and_anonymize_regions(
                                         self.tcx.instantiate_bound_regions_with_erased(trait_ref),
                                     )
                                 })
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index a9fb16b8000..6fefac43699 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -576,7 +576,7 @@ pub fn try_evaluate_const<'tcx>(
                                     let args =
                                         replace_param_and_infer_args_with_placeholder(tcx, uv.args);
                                     let typing_env = infcx
-                                        .typing_env(tcx.erase_regions(param_env))
+                                        .typing_env(tcx.erase_and_anonymize_regions(param_env))
                                         .with_post_analysis_normalized(tcx);
                                     (args, typing_env)
                                 }
@@ -589,7 +589,7 @@ pub fn try_evaluate_const<'tcx>(
                         }
                     } else {
                         let typing_env = infcx
-                            .typing_env(tcx.erase_regions(param_env))
+                            .typing_env(tcx.erase_and_anonymize_regions(param_env))
                             .with_post_analysis_normalized(tcx);
                         (uv.args, typing_env)
                     }
@@ -634,14 +634,14 @@ pub fn try_evaluate_const<'tcx>(
                     }
 
                     let typing_env = infcx
-                        .typing_env(tcx.erase_regions(param_env))
+                        .typing_env(tcx.erase_and_anonymize_regions(param_env))
                         .with_post_analysis_normalized(tcx);
                     (uv.args, typing_env)
                 }
             };
 
             let uv = ty::UnevaluatedConst::new(uv.def, args);
-            let erased_uv = tcx.erase_regions(uv);
+            let erased_uv = tcx.erase_and_anonymize_regions(uv);
 
             use rustc_middle::mir::interpret::ErrorHandled;
             // FIXME: `def_span` will point at the definition of this const; ideally, we'd point at
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index de404532899..945ca7c3775 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -350,7 +350,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
             // Note that we don't care about whether the resume type has any drops since this is
             // redundant; there is no storage for the resume type, so if it is actually stored
             // in the interior, we'll already detect the need for a drop by checking the interior.
-            let typing_env = tcx.erase_regions(typing_env);
+            //
+            // FIXME(@lcnr): Why do we erase regions in the env here? Seems odd
+            let typing_env = tcx.erase_and_anonymize_regions(typing_env);
             let needs_drop = tcx.mir_coroutine_witnesses(def_id).is_some_and(|witness| {
                 witness.field_tys.iter().any(|field| field.ty.needs_drop(tcx, typing_env))
             });
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 7dd3c59edd0..4b05e2cc381 100644
--- a/compiler/rustc_traits/src/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -73,7 +73,7 @@ pub(crate) fn codegen_select_candidate<'tcx>(
     }
 
     let impl_source = infcx.resolve_vars_if_possible(impl_source);
-    let impl_source = tcx.erase_regions(impl_source);
+    let impl_source = tcx.erase_and_anonymize_regions(impl_source);
     if impl_source.has_non_region_infer() {
         // Unused generic types or consts on an impl get replaced with inference vars,
         // but never resolved, causing the return value of a query to contain inference
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index c1b848a2e79..c98b56abe9c 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -41,7 +41,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Par
             // fresh `InferCtxt`. If this assert does trigger, it will give
             // us a test case.
             debug_assert_eq!(normalized_value, resolved_value);
-            let erased = infcx.tcx.erase_regions(resolved_value);
+            let erased = infcx.tcx.erase_and_anonymize_regions(resolved_value);
             debug_assert!(!erased.has_infer(), "{erased:?}");
             Ok(erased)
         }
diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs
index acbce258f39..4e548ff8fe2 100644
--- a/compiler/rustc_transmute/src/layout/mod.rs
+++ b/compiler/rustc_transmute/src/layout/mod.rs
@@ -163,7 +163,7 @@ pub mod rustc {
         ty: Ty<'tcx>,
     ) -> Result<Layout<'tcx>, &'tcx LayoutError<'tcx>> {
         use rustc_middle::ty::layout::LayoutOf;
-        let ty = cx.tcx().erase_regions(ty);
+        let ty = cx.tcx().erase_and_anonymize_regions(ty);
         cx.layout_of(ty).map(|tl| tl.layout)
     }
 }
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 3f83b4d50aa..d7ea26a2ab1 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -426,24 +426,23 @@ pub(crate) mod rustc {
             assert!(def.is_enum());
 
             // Computes the layout of a variant.
-            let layout_of_variant =
-                |index, encoding: Option<TagEncoding<VariantIdx>>| -> Result<Self, Err> {
-                    let variant_layout = ty_variant(cx, (ty, layout), index);
-                    if variant_layout.is_uninhabited() {
-                        return Ok(Self::uninhabited());
-                    }
-                    let tag = cx.tcx().tag_for_variant(
-                        cx.typing_env.as_query_input((cx.tcx().erase_regions(ty), index)),
-                    );
-                    let variant_def = Def::Variant(def.variant(index));
-                    Self::from_variant(
-                        variant_def,
-                        tag.map(|tag| (tag, index, encoding.unwrap())),
-                        (ty, variant_layout),
-                        layout.size,
-                        cx,
-                    )
-                };
+            let layout_of_variant = |index, encoding: Option<_>| -> Result<Self, Err> {
+                let variant_layout = ty_variant(cx, (ty, layout), index);
+                if variant_layout.is_uninhabited() {
+                    return Ok(Self::uninhabited());
+                }
+                let tag = cx.tcx().tag_for_variant(
+                    cx.typing_env.as_query_input((cx.tcx().erase_and_anonymize_regions(ty), index)),
+                );
+                let variant_def = Def::Variant(def.variant(index));
+                Self::from_variant(
+                    variant_def,
+                    tag.map(|tag| (tag, index, encoding.unwrap())),
+                    (ty, variant_layout),
+                    layout.size,
+                    cx,
+                )
+            };
 
             match layout.variants() {
                 Variants::Empty => Ok(Self::uninhabited()),
@@ -634,7 +633,7 @@ pub(crate) mod rustc {
         (ty, layout): (Ty<'tcx>, Layout<'tcx>),
         i: VariantIdx,
     ) -> Layout<'tcx> {
-        let ty = cx.tcx().erase_regions(ty);
+        let ty = cx.tcx().erase_and_anonymize_regions(ty);
         TyAndLayout { ty, layout }.for_variant(&cx, i).layout
     }
 }
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 5c3f7d491a5..e28ebaabc0a 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -176,7 +176,7 @@ fn resolve_associated_item<'tcx>(
                 args,
                 leaf_def.defining_node,
             );
-            let args = infcx.tcx.erase_regions(args);
+            let args = infcx.tcx.erase_and_anonymize_regions(args);
 
             // HACK: We may have overlapping `dyn Trait` built-in impls and
             // user-provided blanket impls. Detect that case here, and return
@@ -222,7 +222,7 @@ fn resolve_associated_item<'tcx>(
                 return Err(guar);
             }
 
-            let args = tcx.erase_regions(args);
+            let args = tcx.erase_and_anonymize_regions(args);
 
             // We check that the impl item is compatible with the trait item
             // because otherwise we may ICE in const eval due to type mismatches,
@@ -279,7 +279,7 @@ fn resolve_associated_item<'tcx>(
                     assert_eq!(name, sym::clone_from);
 
                     // Use the default `fn clone_from` from `trait Clone`.
-                    let args = tcx.erase_regions(rcvr_args);
+                    let args = tcx.erase_and_anonymize_regions(rcvr_args);
                     Some(ty::Instance::new_raw(trait_item_id, args))
                 }
             } else if tcx.is_lang_item(trait_ref.def_id, LangItem::FnPtrTrait) {
@@ -380,7 +380,7 @@ fn resolve_associated_item<'tcx>(
             } else if tcx.is_lang_item(trait_ref.def_id, LangItem::TransmuteTrait) {
                 let name = tcx.item_name(trait_item_id);
                 assert_eq!(name, sym::transmute);
-                let args = tcx.erase_regions(rcvr_args);
+                let args = tcx.erase_and_anonymize_regions(rcvr_args);
                 Some(ty::Instance::new_raw(trait_item_id, args))
             } else {
                 Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args)
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index dbbc0c217d7..8f8f019510f 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -1262,7 +1262,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             encountered_overflow |= stack_entry.encountered_overflow;
             debug_assert_eq!(stack_entry.input, input);
 
-            // If the current goal is not the root of a cycle, we are done.
+            // If the current goal is not a cycle head, we are done.
             //
             // There are no provisional cache entries which depend on this goal.
             let Some(usages) = stack_entry.usages else {
@@ -1278,7 +1278,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             //
             // Check whether we reached a fixpoint, either because the final result
             // is equal to the provisional result of the previous iteration, or because
-            // this was only the root of either coinductive or inductive cycles, and the
+            // this was only the head of either coinductive or inductive cycles, and the
             // final result is equal to the initial response for that case.
             if self.reached_fixpoint(cx, &stack_entry, usages, result) {
                 self.rebase_provisional_cache_entries(&stack_entry, |_, result| result);
diff --git a/compiler/rustc_type_ir/src/search_graph/stack.rs b/compiler/rustc_type_ir/src/search_graph/stack.rs
index 3fd8e2bd16e..8348666be41 100644
--- a/compiler/rustc_type_ir/src/search_graph/stack.rs
+++ b/compiler/rustc_type_ir/src/search_graph/stack.rs
@@ -13,7 +13,7 @@ rustc_index::newtype_index! {
     pub(super) struct StackDepth {}
 }
 
-/// Stack entries of the evaluation stack. Its fields tend to be lazily
+/// Stack entries of the evaluation stack. Its fields tend to be lazily updated
 /// when popping a child goal or completely immutable.
 #[derive_where(Debug; X: Cx)]
 pub(super) struct StackEntry<X: Cx> {
@@ -42,7 +42,7 @@ pub(super) struct StackEntry<X: Cx> {
     /// Whether evaluating this goal encountered overflow. Lazily updated.
     pub encountered_overflow: bool,
 
-    /// Whether and how this goal has been used as the root of a cycle. Lazily updated.
+    /// Whether and how this goal has been used as a cycle head. Lazily updated.
     pub usages: Option<HeadUsages>,
 
     /// We want to be able to ignore head usages if they happen inside of candidates
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 5104484e9c4..6e62e1031a9 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -398,9 +398,9 @@ impl std::fmt::Debug for HasTypeFlagsVisitor {
 // looks, particular for `Ty`/`Predicate` where it's just a field access.
 //
 // N.B. The only case where this isn't totally true is binders, which also
-// add `HAS_{RE,TY,CT}_LATE_BOUND` flag depending on the *bound variables* that
+// add `HAS_BINDER_VARS` flag depending on the *bound variables* that
 // are present, regardless of whether those bound variables are used. This
-// is important for anonymization of binders in `TyCtxt::erase_regions`. We
+// is important for anonymization of binders in `TyCtxt::erase_and_anonymize_regions`. We
 // specifically detect this case in `visit_binder`.
 impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
     type Result = ControlFlow<FoundFlags>;
diff --git a/library/Cargo.lock b/library/Cargo.lock
index e601137e005..e4b3839847b 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -99,13 +99,12 @@ dependencies = [
 
 [[package]]
 name = "getopts"
-version = "0.2.23"
+version = "0.2.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
+checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"
 dependencies = [
  "rustc-std-workspace-core",
  "rustc-std-workspace-std",
- "unicode-width",
 ]
 
 [[package]]
@@ -362,16 +361,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "unicode-width"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
-dependencies = [
- "rustc-std-workspace-core",
- "rustc-std-workspace-std",
-]
-
-[[package]]
 name = "unwind"
 version = "0.0.0"
 dependencies = [
diff --git a/library/core/src/range.rs b/library/core/src/range.rs
index 332ae51d848..8c49123fdaf 100644
--- a/library/core/src/range.rs
+++ b/library/core/src/range.rs
@@ -31,9 +31,7 @@ pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
 #[doc(inline)]
 pub use crate::iter::Step;
 #[doc(inline)]
-pub use crate::ops::{
-    Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive,
-};
+pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo};
 
 /// A (half-open) range bounded inclusively below and exclusively above
 /// (`start..end` in a future edition).
@@ -209,20 +207,20 @@ impl<T> const From<legacy::Range<T>> for Range<T> {
     }
 }
 
-/// A range bounded inclusively below and above (`start..=end`).
+/// A range bounded inclusively below and above (`start..=last`).
 ///
-/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
-/// and `x <= end`. It is empty unless `start <= end`.
+/// The `RangeInclusive` `start..=last` contains all values with `x >= start`
+/// and `x <= last`. It is empty unless `start <= last`.
 ///
 /// # Examples
 ///
-/// The `start..=end` syntax is a `RangeInclusive`:
+/// The `start..=last` syntax is a `RangeInclusive`:
 ///
 /// ```
 /// #![feature(new_range_api)]
 /// use core::range::RangeInclusive;
 ///
-/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
+/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
 /// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
 /// ```
 #[lang = "RangeInclusiveCopy"]
@@ -234,7 +232,7 @@ pub struct RangeInclusive<Idx> {
     pub start: Idx,
     /// The upper bound of the range (inclusive).
     #[unstable(feature = "new_range_api", issue = "125687")]
-    pub end: Idx,
+    pub last: Idx,
 }
 
 #[unstable(feature = "new_range_api", issue = "125687")]
@@ -242,7 +240,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         self.start.fmt(fmt)?;
         write!(fmt, "..=")?;
-        self.end.fmt(fmt)?;
+        self.last.fmt(fmt)?;
         Ok(())
     }
 }
@@ -306,7 +304,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
     #[unstable(feature = "new_range_api", issue = "125687")]
     #[inline]
     pub fn is_empty(&self) -> bool {
-        !(self.start <= self.end)
+        !(self.start <= self.last)
     }
 }
 
@@ -335,10 +333,10 @@ impl<Idx: Step> RangeInclusive<Idx> {
 
 impl RangeInclusive<usize> {
     /// Converts to an exclusive `Range` for `SliceIndex` implementations.
-    /// The caller is responsible for dealing with `end == usize::MAX`.
+    /// The caller is responsible for dealing with `last == usize::MAX`.
     #[inline]
     pub(crate) const fn into_slice_range(self) -> Range<usize> {
-        Range { start: self.start, end: self.end + 1 }
+        Range { start: self.start, end: self.last + 1 }
     }
 }
 
@@ -348,7 +346,7 @@ impl<T> RangeBounds<T> for RangeInclusive<T> {
         Included(&self.start)
     }
     fn end_bound(&self) -> Bound<&T> {
-        Included(&self.end)
+        Included(&self.last)
     }
 }
 
@@ -364,7 +362,7 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> {
         Included(self.start)
     }
     fn end_bound(&self) -> Bound<&T> {
-        Included(self.end)
+        Included(self.last)
     }
 }
 
@@ -372,7 +370,7 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> {
 #[unstable(feature = "new_range_api", issue = "125687")]
 impl<T> IntoBounds<T> for RangeInclusive<T> {
     fn into_bounds(self) -> (Bound<T>, Bound<T>) {
-        (Included(self.start), Included(self.end))
+        (Included(self.start), Included(self.last))
     }
 }
 
@@ -381,7 +379,7 @@ impl<T> IntoBounds<T> for RangeInclusive<T> {
 impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
     #[inline]
     fn from(value: RangeInclusive<T>) -> Self {
-        Self::new(value.start, value.end)
+        Self::new(value.start, value.last)
     }
 }
 #[unstable(feature = "new_range_api", issue = "125687")]
@@ -394,8 +392,8 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
             "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
         );
 
-        let (start, end) = value.into_inner();
-        RangeInclusive { start, end }
+        let (start, last) = value.into_inner();
+        RangeInclusive { start, last }
     }
 }
 
@@ -544,3 +542,107 @@ impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
         Self { start: value.start }
     }
 }
+
+/// A range only bounded inclusively above (`..=last`).
+///
+/// The `RangeToInclusive` `..=last` contains all values with `x <= last`.
+/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
+///
+/// # Examples
+///
+/// The `..=last` syntax is a `RangeToInclusive`:
+///
+/// ```
+/// #![feature(new_range_api)]
+/// #![feature(new_range)]
+/// assert_eq!((..=5), std::range::RangeToInclusive{ last: 5 });
+/// ```
+///
+/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
+/// `for` loop directly. This won't compile:
+///
+/// ```compile_fail,E0277
+/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
+/// // std::iter::Iterator` is not satisfied
+/// for i in ..=5 {
+///     // ...
+/// }
+/// ```
+///
+/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
+/// array elements up to and including the index indicated by `last`.
+///
+/// ```
+/// let arr = [0, 1, 2, 3, 4];
+/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
+/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
+/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]); // This is a `RangeToInclusive`
+/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
+/// assert_eq!(arr[1.. 3], [   1, 2      ]);
+/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
+/// ```
+///
+/// [slicing index]: crate::slice::SliceIndex
+#[lang = "RangeToInclusiveCopy"]
+#[doc(alias = "..=")]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[unstable(feature = "new_range_api", issue = "125687")]
+pub struct RangeToInclusive<Idx> {
+    /// The upper bound of the range (inclusive)
+    #[unstable(feature = "new_range_api", issue = "125687")]
+    pub last: Idx,
+}
+
+#[unstable(feature = "new_range_api", issue = "125687")]
+impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "..=")?;
+        self.last.fmt(fmt)?;
+        Ok(())
+    }
+}
+
+impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
+    /// Returns `true` if `item` is contained in the range.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// assert!( (..=5).contains(&-1_000_000_000));
+    /// assert!( (..=5).contains(&5));
+    /// assert!(!(..=5).contains(&6));
+    ///
+    /// assert!( (..=1.0).contains(&1.0));
+    /// assert!(!(..=1.0).contains(&f32::NAN));
+    /// assert!(!(..=f32::NAN).contains(&0.5));
+    /// ```
+    #[inline]
+    #[unstable(feature = "new_range_api", issue = "125687")]
+    pub fn contains<U>(&self, item: &U) -> bool
+    where
+        Idx: PartialOrd<U>,
+        U: ?Sized + PartialOrd<Idx>,
+    {
+        <Self as RangeBounds<Idx>>::contains(self, item)
+    }
+}
+
+// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
+// because underflow would be possible with (..0).into()
+
+#[unstable(feature = "new_range_api", issue = "125687")]
+impl<T> RangeBounds<T> for RangeToInclusive<T> {
+    fn start_bound(&self) -> Bound<&T> {
+        Unbounded
+    }
+    fn end_bound(&self) -> Bound<&T> {
+        Included(&self.last)
+    }
+}
+
+#[unstable(feature = "range_into_bounds", issue = "136903")]
+impl<T> IntoBounds<T> for RangeToInclusive<T> {
+    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
+        (Unbounded, Included(self.last))
+    }
+}
diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs
index 1e261d8c1d9..24efd4a204a 100644
--- a/library/core/src/range/iter.rs
+++ b/library/core/src/range/iter.rs
@@ -164,7 +164,7 @@ impl<A: Step> IterRangeInclusive<A> {
             return None;
         }
 
-        Some(RangeInclusive { start: self.0.start, end: self.0.end })
+        Some(RangeInclusive { start: self.0.start, last: self.0.end })
     }
 }
 
diff --git a/library/core/src/range/legacy.rs b/library/core/src/range/legacy.rs
index 6723c4903f7..aa11331382d 100644
--- a/library/core/src/range/legacy.rs
+++ b/library/core/src/range/legacy.rs
@@ -1,10 +1,10 @@
 //! # Legacy range types
 //!
 //! The types within this module will be replaced by the types
-//! [`Range`], [`RangeInclusive`], and [`RangeFrom`] in the parent
+//! [`Range`], [`RangeInclusive`], [`RangeToInclusive`], and [`RangeFrom`] in the parent
 //! module, [`core::range`].
 //!
 //! The types here are equivalent to those in [`core::ops`].
 
 #[doc(inline)]
-pub use crate::ops::{Range, RangeFrom, RangeInclusive};
+pub use crate::ops::{Range, RangeFrom, RangeInclusive, RangeToInclusive};
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 8e1bc0bae70..a8147d745f3 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -129,6 +129,8 @@ mod private_slice_index {
     #[unstable(feature = "new_range_api", issue = "125687")]
     impl Sealed for range::RangeInclusive<usize> {}
     #[unstable(feature = "new_range_api", issue = "125687")]
+    impl Sealed for range::RangeToInclusive<usize> {}
+    #[unstable(feature = "new_range_api", issue = "125687")]
     impl Sealed for range::RangeFrom<usize> {}
 
     impl Sealed for ops::IndexRange {}
@@ -788,6 +790,45 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
     }
 }
 
+/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
+#[stable(feature = "inclusive_range", since = "1.26.0")]
+#[rustc_const_unstable(feature = "const_index", issue = "143775")]
+unsafe impl<T> const SliceIndex<[T]> for range::RangeToInclusive<usize> {
+    type Output = [T];
+
+    #[inline]
+    fn get(self, slice: &[T]) -> Option<&[T]> {
+        (0..=self.last).get(slice)
+    }
+
+    #[inline]
+    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
+        (0..=self.last).get_mut(slice)
+    }
+
+    #[inline]
+    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
+        unsafe { (0..=self.last).get_unchecked(slice) }
+    }
+
+    #[inline]
+    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
+        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
+        unsafe { (0..=self.last).get_unchecked_mut(slice) }
+    }
+
+    #[inline]
+    fn index(self, slice: &[T]) -> &[T] {
+        (0..=self.last).index(slice)
+    }
+
+    #[inline]
+    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
+        (0..=self.last).index_mut(slice)
+    }
+}
+
 /// Performs bounds checking of a range.
 ///
 /// This method is similar to [`Index::index`] for slices, but it returns a
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 4f228edf78e..5adae62b7e6 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -677,11 +677,11 @@ unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
     type Output = str;
     #[inline]
     fn get(self, slice: &str) -> Option<&Self::Output> {
-        if self.end == usize::MAX { None } else { self.into_slice_range().get(slice) }
+        if self.last == usize::MAX { None } else { self.into_slice_range().get(slice) }
     }
     #[inline]
     fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
-        if self.end == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
+        if self.last == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
     }
     #[inline]
     unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
@@ -695,14 +695,14 @@ unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
     }
     #[inline]
     fn index(self, slice: &str) -> &Self::Output {
-        if self.end == usize::MAX {
+        if self.last == usize::MAX {
             str_index_overflow_fail();
         }
         self.into_slice_range().index(slice)
     }
     #[inline]
     fn index_mut(self, slice: &mut str) -> &mut Self::Output {
-        if self.end == usize::MAX {
+        if self.last == usize::MAX {
             str_index_overflow_fail();
         }
         self.into_slice_range().index_mut(slice)
diff --git a/library/std/tests/floats/f32.rs b/library/std/tests/floats/f32.rs
index c29d803b25e..3acd0670914 100644
--- a/library/std/tests/floats/f32.rs
+++ b/library/std/tests/floats/f32.rs
@@ -193,13 +193,13 @@ fn test_atanh() {
 #[test]
 fn test_gamma() {
     // precision can differ between platforms
-    assert_approx_eq!(1.0f32.gamma(), 1.0f32);
-    assert_approx_eq!(2.0f32.gamma(), 1.0f32);
-    assert_approx_eq!(3.0f32.gamma(), 2.0f32);
+    assert_approx_eq!(1.0f32.gamma(), 1.0f32, APPROX_DELTA);
+    assert_approx_eq!(2.0f32.gamma(), 1.0f32, APPROX_DELTA);
+    assert_approx_eq!(3.0f32.gamma(), 2.0f32, APPROX_DELTA);
     assert_approx_eq!(4.0f32.gamma(), 6.0f32, APPROX_DELTA);
     assert_approx_eq!(5.0f32.gamma(), 24.0f32, APPROX_DELTA);
-    assert_approx_eq!(0.5f32.gamma(), consts::PI.sqrt());
-    assert_approx_eq!((-0.5f32).gamma(), -2.0 * consts::PI.sqrt());
+    assert_approx_eq!(0.5f32.gamma(), consts::PI.sqrt(), APPROX_DELTA);
+    assert_approx_eq!((-0.5f32).gamma(), -2.0 * consts::PI.sqrt(), APPROX_DELTA);
     assert_eq!(0.0f32.gamma(), f32::INFINITY);
     assert_eq!((-0.0f32).gamma(), f32::NEG_INFINITY);
     assert!((-1.0f32).gamma().is_nan());
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
index 2a32a7dd76e..fe749847b7c 100644
--- a/library/test/Cargo.toml
+++ b/library/test/Cargo.toml
@@ -6,7 +6,7 @@ version = "0.0.0"
 edition = "2024"
 
 [dependencies]
-getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
+getopts = { version = "0.2.24", default-features = false, features = ['rustc-dep-of-std'] }
 std = { path = "../std", public = true }
 core = { path = "../core", public = true }
 
diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index 7e0fb5794f4..b7d7151b171 100755
--- a/src/ci/docker/scripts/rfl-build.sh
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -2,9 +2,7 @@
 
 set -euo pipefail
 
-# https://github.com/rust-lang/rust/pull/144443
-# https://github.com/rust-lang/rust/pull/145928
-LINUX_VERSION=8851e27d2cb947ea8bbbe8e812068f7bf5cbd00b
+LINUX_VERSION=v6.17-rc5
 
 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt
 ../x.py build --stage 2 library rustdoc clippy rustfmt
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 9aa2f3cf0a5..9645a26a68a 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -364,7 +364,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
                                 //   priority.
                                 if let Some(fn_id) = typeck.type_dependent_def_id(hir_id)
                                     && let Some(trait_id) = cx.tcx.trait_of_assoc(fn_id)
-                                    && let arg_ty = cx.tcx.erase_regions(adjusted_ty)
+                                    && let arg_ty = cx.tcx.erase_and_anonymize_regions(adjusted_ty)
                                     && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
                                     && let args =
                                         typeck.node_args_opt(hir_id).map(|args| &args[1..]).unwrap_or_default()
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index 010652e1cb9..6ce7f0b1f0b 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -140,7 +140,7 @@ fn is_ref_iterable<'tcx>(
 
         let res_ty = cx
             .tcx
-            .erase_regions(EarlyBinder::bind(req_res_ty).instantiate(cx.tcx, typeck.node_args(call_expr.hir_id)));
+            .erase_and_anonymize_regions(EarlyBinder::bind(req_res_ty).instantiate(cx.tcx, typeck.node_args(call_expr.hir_id)));
         let mutbl = if let ty::Ref(_, _, mutbl) = *req_self_ty.kind() {
             Some(mutbl)
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
index a42763172f5..809a6728e12 100644
--- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
                 {
                     (
                         trait_item_id,
-                        FnKind::ImplTraitFn(std::ptr::from_ref(cx.tcx.erase_regions(trait_ref.args)) as usize),
+                        FnKind::ImplTraitFn(std::ptr::from_ref(cx.tcx.erase_and_anonymize_regions(trait_ref.args)) as usize),
                         usize::from(sig.decl.implicit_self.has_implicit_self()),
                     )
                 } else {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
index 3842c4eb60e..6aeb22d41a7 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
@@ -45,7 +45,7 @@ pub(super) fn check<'tcx>(
                 Applicability::MaybeIncorrect,
             );
             triggered = true;
-        } else if (cx.tcx.erase_regions(from_ty) != cx.tcx.erase_regions(to_ty)) && !const_context {
+        } else if (cx.tcx.erase_and_anonymize_regions(from_ty) != cx.tcx.erase_and_anonymize_regions(to_ty)) && !const_context {
             span_lint_and_then(
                 cx,
                 TRANSMUTE_PTR_TO_PTR,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index 26323af3122..3e6aae475ec 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -12,8 +12,8 @@ pub(super) fn check<'tcx>(
     from_ty_orig: Ty<'tcx>,
     to_ty_orig: Ty<'tcx>,
 ) -> bool {
-    let mut from_ty = cx.tcx.erase_regions(from_ty_orig);
-    let mut to_ty = cx.tcx.erase_regions(to_ty_orig);
+    let mut from_ty = cx.tcx.erase_and_anonymize_regions(from_ty_orig);
+    let mut to_ty = cx.tcx.erase_and_anonymize_regions(to_ty_orig);
 
     while from_ty != to_ty {
         let reduced_tys = reduce_refs(cx, from_ty, to_ty);
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index 70ae982a445..e45f884cfcb 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -98,7 +98,7 @@ fn into_iter_bound<'tcx>(
             if tr.def_id() == into_iter_did {
                 into_iter_span = Some(*span);
             } else {
-                let tr = cx.tcx.erase_regions(tr);
+                let tr = cx.tcx.erase_and_anonymize_regions(tr);
                 if tr.has_escaping_bound_vars() {
                     return None;
                 }
diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs
index 278101ac27f..8033b74a8d2 100644
--- a/src/tools/clippy/clippy_utils/src/sym.rs
+++ b/src/tools/clippy/clippy_utils/src/sym.rs
@@ -194,7 +194,6 @@ generate! {
     itertools,
     join,
     kw,
-    last,
     lazy_static,
     lint_vec,
     ln,
diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs
index 8e302f9d2ad..9f77a1c4d9b 100644
--- a/src/tools/clippy/clippy_utils/src/ty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs
@@ -285,7 +285,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
         let _ = tcx.hir_body_owner_kind(callee_id);
     }
 
-    let ty = tcx.erase_regions(ty);
+    let ty = tcx.erase_and_anonymize_regions(ty);
     if ty.has_escaping_bound_vars() {
         return false;
     }
diff --git a/src/tools/miri/tests/pass/static_align.rs b/src/tools/miri/tests/pass/static_align.rs
new file mode 100644
index 00000000000..f292f028568
--- /dev/null
+++ b/src/tools/miri/tests/pass/static_align.rs
@@ -0,0 +1,14 @@
+#![feature(static_align)]
+
+// When a static uses `align(N)`, its address should be a multiple of `N`.
+
+#[rustc_align_static(256)]
+static FOO: u64 = 0;
+
+#[rustc_align_static(512)]
+static BAR: u64 = 0;
+
+fn main() {
+    assert!(core::ptr::from_ref(&FOO).addr().is_multiple_of(256));
+    assert!(core::ptr::from_ref(&BAR).addr().is_multiple_of(512));
+}
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index fee48bea144..60347b2ea64 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -477,7 +477,6 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[
     "rustc-demangle",
     "rustc-literal-escaper",
     "shlex",
-    "unicode-width",
     "unwinding",
     "wasi",
     "windows-sys",
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index ee06707415f..849dcb9e88f 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -2021,7 +2021,6 @@ ui/parser/issues/issue-5806.rs
 ui/parser/issues/issue-58094-missing-right-square-bracket.rs
 ui/parser/issues/issue-58856-1.rs
 ui/parser/issues/issue-58856-2.rs
-ui/parser/issues/issue-59418.rs
 ui/parser/issues/issue-60075.rs
 ui/parser/issues/issue-61858.rs
 ui/parser/issues/issue-62524.rs
diff --git a/tests/codegen-llvm/align-static.rs b/tests/codegen-llvm/align-static.rs
new file mode 100644
index 00000000000..53db998919a
--- /dev/null
+++ b/tests/codegen-llvm/align-static.rs
@@ -0,0 +1,31 @@
+//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
+
+#![crate_type = "lib"]
+#![feature(static_align)]
+
+// CHECK: @STATIC_ALIGN =
+// CHECK-SAME: align 16
+#[no_mangle]
+#[rustc_align_static(16)]
+pub static STATIC_ALIGN: u64 = 0;
+
+// CHECK: @ALIGN_SPECIFIED_TWICE_1 =
+// CHECK-SAME: align 64
+#[no_mangle]
+#[rustc_align_static(32)]
+#[rustc_align_static(64)]
+pub static ALIGN_SPECIFIED_TWICE_1: u64 = 0;
+
+// CHECK: @ALIGN_SPECIFIED_TWICE_2 =
+// CHECK-SAME: align 128
+#[no_mangle]
+#[rustc_align_static(128)]
+#[rustc_align_static(32)]
+pub static ALIGN_SPECIFIED_TWICE_2: u64 = 0;
+
+// CHECK: @ALIGN_SPECIFIED_TWICE_3 =
+// CHECK-SAME: align 256
+#[no_mangle]
+#[rustc_align_static(32)]
+#[rustc_align_static(256)]
+pub static ALIGN_SPECIFIED_TWICE_3: u64 = 0;
diff --git a/tests/ui/attributes/malformed-static-align.rs b/tests/ui/attributes/malformed-static-align.rs
new file mode 100644
index 00000000000..305d8acf8af
--- /dev/null
+++ b/tests/ui/attributes/malformed-static-align.rs
@@ -0,0 +1,17 @@
+#![feature(static_align)]
+#![crate_type = "lib"]
+
+#[rustc_align_static = 16] //~ ERROR malformed `rustc_align_static` attribute input
+static S1: () = ();
+
+#[rustc_align_static("hello")] //~ ERROR invalid alignment value: not an unsuffixed integer
+static S2: () = ();
+
+#[rustc_align_static(0)] //~ ERROR invalid alignment value: not a power of two
+static S3: () = ();
+
+#[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on static
+static S4: () = ();
+
+#[rustc_align_static(16)] //~ ERROR `#[rustc_align_static]` attribute cannot be used on structs
+struct Struct1;
diff --git a/tests/ui/attributes/malformed-static-align.stderr b/tests/ui/attributes/malformed-static-align.stderr
new file mode 100644
index 00000000000..35f654d3990
--- /dev/null
+++ b/tests/ui/attributes/malformed-static-align.stderr
@@ -0,0 +1,45 @@
+error[E0539]: malformed `rustc_align_static` attribute input
+  --> $DIR/malformed-static-align.rs:4:1
+   |
+LL | #[rustc_align_static = 16]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[rustc_align_static(<alignment in bytes>)]`
+
+error[E0589]: invalid alignment value: not an unsuffixed integer
+  --> $DIR/malformed-static-align.rs:7:22
+   |
+LL | #[rustc_align_static("hello")]
+   |                      ^^^^^^^
+
+error[E0589]: invalid alignment value: not a power of two
+  --> $DIR/malformed-static-align.rs:10:22
+   |
+LL | #[rustc_align_static(0)]
+   |                      ^
+
+error: `#[rustc_align_static]` attribute cannot be used on structs
+  --> $DIR/malformed-static-align.rs:16:1
+   |
+LL | #[rustc_align_static(16)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `#[rustc_align_static]` can be applied to statics and foreign statics
+
+error: `#[repr(align(...))]` is not supported on statics
+  --> $DIR/malformed-static-align.rs:13:8
+   |
+LL | #[repr(align(16))]
+   |        ^^^^^^^^^
+   |
+help: use `#[rustc_align_static(...)]` instead
+  --> $DIR/malformed-static-align.rs:13:8
+   |
+LL | #[repr(align(16))]
+   |        ^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0539, E0589.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/const-generics/std/const-generics-range.full.stderr b/tests/ui/const-generics/std/const-generics-range.full.stderr
index 2b5c63e6643..ccede2af9e5 100644
--- a/tests/ui/const-generics/std/const-generics-range.full.stderr
+++ b/tests/ui/const-generics/std/const-generics-range.full.stderr
@@ -28,7 +28,7 @@ error[E0741]: `RangeTo<usize>` must implement `ConstParamTy` to be used as the t
 LL | struct _RangeTo<const R: std::ops::RangeTo<usize>>;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0741]: `RangeToInclusive<usize>` must implement `ConstParamTy` to be used as the type of a const generic parameter
+error[E0741]: `std::ops::RangeToInclusive<usize>` must implement `ConstParamTy` to be used as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:34:35
    |
 LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr
index 04e3fe74453..43a57c880d5 100644
--- a/tests/ui/const-generics/std/const-generics-range.min.stderr
+++ b/tests/ui/const-generics/std/const-generics-range.min.stderr
@@ -58,7 +58,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
 LL + #![feature(adt_const_params)]
    |
 
-error: `RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
+error: `std::ops::RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:34:35
    |
 LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
diff --git a/tests/ui/const-generics/std/const-generics-range.rs b/tests/ui/const-generics/std/const-generics-range.rs
index 3a238ed177e..391366dadba 100644
--- a/tests/ui/const-generics/std/const-generics-range.rs
+++ b/tests/ui/const-generics/std/const-generics-range.rs
@@ -7,32 +7,32 @@
 // `Range` should be usable within const generics:
 struct _Range<const R: std::ops::Range<usize>>;
 //[min]~^ ERROR `std::ops::Range<usize>` is forbidden
-const RANGE : _Range<{ 0 .. 1000 }> = _Range;
+const RANGE: _Range<{ 0..1000 }> = _Range;
 
 // `RangeFrom` should be usable within const generics:
 struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
 //[min]~^ ERROR `std::ops::RangeFrom<usize>` is forbidden
-const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom;
+const RANGE_FROM: _RangeFrom<{ 0.. }> = _RangeFrom;
 
 // `RangeFull` should be usable within const generics:
 struct _RangeFull<const R: std::ops::RangeFull>;
 //[min]~^ ERROR `RangeFull` is forbidden
-const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull;
+const RANGE_FULL: _RangeFull<{ .. }> = _RangeFull;
 
 // Regression test for #70155
 // `RangeInclusive` should be usable within const generics:
 struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
 //[min]~^ ERROR `std::ops::RangeInclusive<usize>` is forbidden
-const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive;
+const RANGE_INCLUSIVE: _RangeInclusive<{ 0..=999 }> = _RangeInclusive;
 
 // `RangeTo` should be usable within const generics:
 struct _RangeTo<const R: std::ops::RangeTo<usize>>;
 //[min]~^ ERROR `RangeTo<usize>` is forbidden
-const RANGE_TO : _RangeTo<{ .. 1000 }> = _RangeTo;
+const RANGE_TO: _RangeTo<{ ..1000 }> = _RangeTo;
 
 // `RangeToInclusive` should be usable within const generics:
 struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
-//[min]~^ ERROR `RangeToInclusive<usize>` is forbidden
-const RANGE_TO_INCLUSIVE : _RangeToInclusive<{ ..= 999 }> = _RangeToInclusive;
+//[min]~^ ERROR `std::ops::RangeToInclusive<usize>` is forbidden
+const RANGE_TO_INCLUSIVE: _RangeToInclusive<{ ..=999 }> = _RangeToInclusive;
 
 pub fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-static_align.rs b/tests/ui/feature-gates/feature-gate-static_align.rs
new file mode 100644
index 00000000000..4d8f0e18d94
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-static_align.rs
@@ -0,0 +1,11 @@
+#![crate_type = "lib"]
+
+#[rustc_align_static(16)]
+//~^ ERROR the `#[rustc_align_static]` attribute is an experimental feature
+static REQUIRES_ALIGNMENT: u64 = 0;
+
+extern "C" {
+    #[rustc_align_static(16)]
+    //~^ ERROR the `#[rustc_align_static]` attribute is an experimental feature
+    static FOREIGN_STATIC: u32;
+}
diff --git a/tests/ui/feature-gates/feature-gate-static_align.stderr b/tests/ui/feature-gates/feature-gate-static_align.stderr
new file mode 100644
index 00000000000..b45fcdefc9c
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-static_align.stderr
@@ -0,0 +1,23 @@
+error[E0658]: the `#[rustc_align_static]` attribute is an experimental feature
+  --> $DIR/feature-gate-static_align.rs:3:1
+   |
+LL | #[rustc_align_static(16)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #146177 <https://github.com/rust-lang/rust/issues/146177> for more information
+   = help: add `#![feature(static_align)]` 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[E0658]: the `#[rustc_align_static]` attribute is an experimental feature
+  --> $DIR/feature-gate-static_align.rs:8:5
+   |
+LL |     #[rustc_align_static(16)]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #146177 <https://github.com/rust-lang/rust/issues/146177> for more information
+   = help: add `#![feature(static_align)]` 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/iterators/ranges.stderr b/tests/ui/iterators/ranges.stderr
index b9fbcd5304b..f85ce644073 100644
--- a/tests/ui/iterators/ranges.stderr
+++ b/tests/ui/iterators/ranges.stderr
@@ -8,15 +8,15 @@ LL |     for _ in ..10 {}
    = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end`
    = note: required for `RangeTo<{integer}>` to implement `IntoIterator`
 
-error[E0277]: `RangeToInclusive<{integer}>` is not an iterator
+error[E0277]: `std::ops::RangeToInclusive<{integer}>` is not an iterator
   --> $DIR/ranges.rs:4:14
    |
 LL |     for _ in ..=10 {}
    |              ^^^^^ if you meant to iterate until a value (including it), add a starting value
    |
-   = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`
+   = help: the trait `Iterator` is not implemented for `std::ops::RangeToInclusive<{integer}>`
    = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end`
-   = note: required for `RangeToInclusive<{integer}>` to implement `IntoIterator`
+   = note: required for `std::ops::RangeToInclusive<{integer}>` to implement `IntoIterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/new-range/disabled.rs b/tests/ui/new-range/disabled.rs
index 1a5fe3f9743..6ba29f5ca9a 100644
--- a/tests/ui/new-range/disabled.rs
+++ b/tests/ui/new-range/disabled.rs
@@ -6,20 +6,20 @@ fn main() {
     // Unchanged
     let a: core::range::RangeFull = ..;
     let b: core::range::RangeTo<u8> = ..2;
-    let c: core::range::RangeToInclusive<u8> = ..=3;
 
     let _: core::ops::RangeFull = a;
     let _: core::ops::RangeTo<u8> = b;
-    let _: core::ops::RangeToInclusive<u8> = c;
 
     // Changed
     let a: core::range::legacy::RangeFrom<u8> = 1..;
     let b: core::range::legacy::Range<u8> = 2..3;
     let c: core::range::legacy::RangeInclusive<u8> = 4..=5;
+    let d: core::range::legacy::RangeToInclusive<u8> = ..=3;
 
     let a: core::ops::RangeFrom<u8> = a;
     let b: core::ops::Range<u8> = b;
     let c: core::ops::RangeInclusive<u8> = c;
+    let d: core::ops::RangeToInclusive<u8> = d;
 
     let _: core::ops::RangeFrom<u8> = a.into_iter();
     let _: core::ops::Range<u8> = b.into_iter();
diff --git a/tests/ui/new-range/enabled.rs b/tests/ui/new-range/enabled.rs
index a5fb76ad52b..5ddbba492e7 100644
--- a/tests/ui/new-range/enabled.rs
+++ b/tests/ui/new-range/enabled.rs
@@ -7,18 +7,18 @@ fn main() {
     // Unchanged
     let a: core::range::RangeFull = ..;
     let b: core::range::RangeTo<u8> = ..2;
-    let c: core::range::RangeToInclusive<u8> = ..=3;
 
     let _: core::ops::RangeFull = a;
     let _: core::ops::RangeTo<u8> = b;
-    let _: core::ops::RangeToInclusive<u8> = c;
 
     // Changed
     let a: core::range::RangeFrom<u8> = 1..;
     let b: core::range::Range<u8> = 2..3;
     let c: core::range::RangeInclusive<u8> = 4..=5;
+    let d: core::range::RangeToInclusive<u8> = ..=3;
 
     let _: core::range::IterRangeFrom<u8> = a.into_iter();
     let _: core::range::IterRange<u8> = b.into_iter();
     let _: core::range::IterRangeInclusive<u8> = c.into_iter();
+    // RangeToInclusive has no Iterator implementation
 }
diff --git a/tests/ui/parser/auxiliary/tuple-index-suffix-proc-macro-aux.rs b/tests/ui/parser/auxiliary/tuple-index-suffix-proc-macro-aux.rs
new file mode 100644
index 00000000000..a5084b55aac
--- /dev/null
+++ b/tests/ui/parser/auxiliary/tuple-index-suffix-proc-macro-aux.rs
@@ -0,0 +1,33 @@
+#![feature(proc_macro_quote, proc_macro_span)]
+
+extern crate proc_macro;
+
+use proc_macro::{Ident, Literal, Span, TokenStream, TokenTree, quote};
+
+#[proc_macro]
+pub fn bad_tup_indexing(input: TokenStream) -> TokenStream {
+    let tt = input.into_iter().next().unwrap();
+    let TokenTree::Literal(indexing_expr) = tt else {
+        unreachable!();
+    };
+    quote! { (42,).$indexing_expr }
+}
+
+// Expects {IDENT, COMMA, LITERAL}
+#[proc_macro]
+pub fn bad_tup_struct_indexing(input: TokenStream) -> TokenStream {
+    let mut input = input.into_iter();
+
+    let ident = input.next().unwrap();
+    let _comma = input.next().unwrap();
+    let lit = input.next().unwrap();
+
+    let TokenTree::Ident(ident) = ident else {
+        unreachable!("id");
+    };
+    let TokenTree::Literal(indexing_expr) = lit else {
+        unreachable!("lit");
+    };
+
+    quote! { $ident.$indexing_expr }
+}
diff --git a/tests/ui/parser/issues/issue-59418.rs b/tests/ui/parser/issues/issue-59418.rs
deleted file mode 100644
index 0fa191d4a7e..00000000000
--- a/tests/ui/parser/issues/issue-59418.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-struct X(i32,i32,i32);
-
-fn main() {
-    let a = X(1, 2, 3);
-    let b = a.1suffix;
-    //~^ ERROR suffixes on a tuple index are invalid
-    println!("{}", b);
-    let c = (1, 2, 3);
-    let d = c.1suffix;
-    //~^ ERROR suffixes on a tuple index are invalid
-    println!("{}", d);
-    let s = X { 0suffix: 0, 1: 1, 2: 2 };
-    //~^ ERROR suffixes on a tuple index are invalid
-    match s {
-        X { 0suffix: _, .. } => {}
-        //~^ ERROR suffixes on a tuple index are invalid
-    }
-}
diff --git a/tests/ui/parser/issues/issue-59418.stderr b/tests/ui/parser/issues/issue-59418.stderr
deleted file mode 100644
index 347051e9f92..00000000000
--- a/tests/ui/parser/issues/issue-59418.stderr
+++ /dev/null
@@ -1,26 +0,0 @@
-error: suffixes on a tuple index are invalid
-  --> $DIR/issue-59418.rs:5:15
-   |
-LL |     let b = a.1suffix;
-   |               ^^^^^^^ invalid suffix `suffix`
-
-error: suffixes on a tuple index are invalid
-  --> $DIR/issue-59418.rs:9:15
-   |
-LL |     let d = c.1suffix;
-   |               ^^^^^^^ invalid suffix `suffix`
-
-error: suffixes on a tuple index are invalid
-  --> $DIR/issue-59418.rs:12:17
-   |
-LL |     let s = X { 0suffix: 0, 1: 1, 2: 2 };
-   |                 ^^^^^^^ invalid suffix `suffix`
-
-error: suffixes on a tuple index are invalid
-  --> $DIR/issue-59418.rs:15:13
-   |
-LL |         X { 0suffix: _, .. } => {}
-   |             ^^^^^^^ invalid suffix `suffix`
-
-error: aborting due to 4 previous errors
-
diff --git a/tests/ui/parser/tuple-index-suffix-proc-macro.rs b/tests/ui/parser/tuple-index-suffix-proc-macro.rs
new file mode 100644
index 00000000000..557c67738d3
--- /dev/null
+++ b/tests/ui/parser/tuple-index-suffix-proc-macro.rs
@@ -0,0 +1,32 @@
+//! See #59418.
+//!
+//! Like `tuple-index-suffix.rs`, but exercises the proc-macro interaction.
+
+//@ proc-macro: tuple-index-suffix-proc-macro-aux.rs
+
+extern crate tuple_index_suffix_proc_macro_aux;
+use tuple_index_suffix_proc_macro_aux as aux;
+
+fn main() {
+    struct TupStruct(i32);
+    let tup_struct = TupStruct(42);
+
+    // Previously, #60186 had carve outs for `{i,u}{32,usize}` as non-lint pseudo-FCW warnings. Now,
+    // they all hard error.
+
+    aux::bad_tup_indexing!(0usize);
+    //~^ ERROR suffixes on a tuple index are invalid
+    aux::bad_tup_struct_indexing!(tup_struct, 0isize);
+    //~^ ERROR suffixes on a tuple index are invalid
+
+    // Not part of the #60186 carve outs.
+
+    aux::bad_tup_indexing!(0u8);
+    //~^ ERROR suffixes on a tuple index are invalid
+    aux::bad_tup_struct_indexing!(tup_struct, 0u64);
+    //~^ ERROR suffixes on a tuple index are invalid
+
+    // NOTE: didn't bother with trying to figure out how to generate `struct P { 0u32: u32 }` using
+    // *only* `proc_macro` without help with `syn`/`quote`, looks like you can't with just
+    // `proc_macro::quote`?
+}
diff --git a/tests/ui/parser/tuple-index-suffix-proc-macro.stderr b/tests/ui/parser/tuple-index-suffix-proc-macro.stderr
new file mode 100644
index 00000000000..47d179d3555
--- /dev/null
+++ b/tests/ui/parser/tuple-index-suffix-proc-macro.stderr
@@ -0,0 +1,26 @@
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix-proc-macro.rs:17:28
+   |
+LL |     aux::bad_tup_indexing!(0usize);
+   |                            ^^^^^^ invalid suffix `usize`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix-proc-macro.rs:19:47
+   |
+LL |     aux::bad_tup_struct_indexing!(tup_struct, 0isize);
+   |                                               ^^^^^^ invalid suffix `isize`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix-proc-macro.rs:24:28
+   |
+LL |     aux::bad_tup_indexing!(0u8);
+   |                            ^^^ invalid suffix `u8`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix-proc-macro.rs:26:47
+   |
+LL |     aux::bad_tup_struct_indexing!(tup_struct, 0u64);
+   |                                               ^^^^ invalid suffix `u64`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/parser/tuple-index-suffix.rs b/tests/ui/parser/tuple-index-suffix.rs
new file mode 100644
index 00000000000..c4769500005
--- /dev/null
+++ b/tests/ui/parser/tuple-index-suffix.rs
@@ -0,0 +1,79 @@
+//! Regression test for both the original regression in #59418 where invalid suffixes in indexing
+//! positions were accidentally accepted, and also for the removal of the temporary carve out that
+//! mitigated ecosystem impact following trying to reject #59418 (this was implemented as a FCW
+//! tracked in #60210).
+//!
+//! Check that we hard error on invalid suffixes in tuple indexing subexpressions and struct numeral
+//! field names.
+
+struct X(i32,i32,i32);
+
+fn main() {
+    let tup_struct = X(1, 2, 3);
+    let invalid_tup_struct_suffix = tup_struct.0suffix;
+    //~^ ERROR suffixes on a tuple index are invalid
+    let previous_carve_out_tup_struct_suffix = tup_struct.0i32;
+    //~^ ERROR suffixes on a tuple index are invalid
+
+    let tup = (1, 2, 3);
+    let invalid_tup_suffix = tup.0suffix;
+    //~^ ERROR suffixes on a tuple index are invalid
+    let previous_carve_out_tup_suffix = tup.0u32;
+    //~^ ERROR suffixes on a tuple index are invalid
+
+    numeral_struct_field_name_suffix_invalid();
+    numeral_struct_field_name_suffix_previous_carve_out();
+}
+
+// Previously, there were very limited carve outs as a ecosystem impact mitigation implemented in
+// #60186. *Only* `{i,u}{32,usize}` suffixes were temporarily accepted. Now, they all hard error.
+fn previous_carve_outs() {
+    // Previously temporarily accepted by a pseudo-FCW (#60210), now hard error.
+
+    let previous_carve_out_i32 = (42,).0i32;     //~ ERROR suffixes on a tuple index are invalid
+    let previous_carve_out_i32 = (42,).0u32;     //~ ERROR suffixes on a tuple index are invalid
+    let previous_carve_out_isize = (42,).0isize; //~ ERROR suffixes on a tuple index are invalid
+    let previous_carve_out_usize = (42,).0usize; //~ ERROR suffixes on a tuple index are invalid
+
+    // Not part of the carve outs!
+    let error_i8 = (42,).0i8;      //~ ERROR suffixes on a tuple index are invalid
+    let error_u8 = (42,).0u8;      //~ ERROR suffixes on a tuple index are invalid
+    let error_i16 = (42,).0i16;    //~ ERROR suffixes on a tuple index are invalid
+    let error_u16 = (42,).0u16;    //~ ERROR suffixes on a tuple index are invalid
+    let error_i64 = (42,).0i64;    //~ ERROR suffixes on a tuple index are invalid
+    let error_u64 = (42,).0u64;    //~ ERROR suffixes on a tuple index are invalid
+    let error_i128 = (42,).0i128;  //~ ERROR suffixes on a tuple index are invalid
+    let error_u128 = (42,).0u128;  //~ ERROR suffixes on a tuple index are invalid
+}
+
+fn numeral_struct_field_name_suffix_invalid() {
+    let invalid_struct_name = X { 0suffix: 0, 1: 1, 2: 2 };
+    //~^ ERROR suffixes on a tuple index are invalid
+    match invalid_struct_name {
+        X { 0suffix: _, .. } => {}
+        //~^ ERROR suffixes on a tuple index are invalid
+    }
+}
+
+fn numeral_struct_field_name_suffix_previous_carve_out() {
+    let carve_out_struct_name = X { 0u32: 0, 1: 1, 2: 2 };
+    //~^ ERROR suffixes on a tuple index are invalid
+    match carve_out_struct_name {
+        X { 0u32: _, .. } => {}
+        //~^ ERROR suffixes on a tuple index are invalid
+    }
+}
+
+// Unfortunately, it turns out `std::mem::offset_of!` uses the same expect suffix code path.
+fn offset_of_suffix() {
+    #[repr(C)]
+    pub struct Struct<T>(u8, T);
+
+    // Previous pseudo-FCW carve outs
+    assert_eq!(std::mem::offset_of!(Struct<u32>, 0usize), 0);
+    //~^ ERROR suffixes on a tuple index are invalid
+
+    // Not part of carve outs
+    assert_eq!(std::mem::offset_of!(Struct<u32>, 0u8), 0);
+    //~^ ERROR suffixes on a tuple index are invalid
+}
diff --git a/tests/ui/parser/tuple-index-suffix.stderr b/tests/ui/parser/tuple-index-suffix.stderr
new file mode 100644
index 00000000000..6d96c6d3cbf
--- /dev/null
+++ b/tests/ui/parser/tuple-index-suffix.stderr
@@ -0,0 +1,134 @@
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:13:48
+   |
+LL |     let invalid_tup_struct_suffix = tup_struct.0suffix;
+   |                                                ^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:15:59
+   |
+LL |     let previous_carve_out_tup_struct_suffix = tup_struct.0i32;
+   |                                                           ^^^^ invalid suffix `i32`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:19:34
+   |
+LL |     let invalid_tup_suffix = tup.0suffix;
+   |                                  ^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:21:45
+   |
+LL |     let previous_carve_out_tup_suffix = tup.0u32;
+   |                                             ^^^^ invalid suffix `u32`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:33:40
+   |
+LL |     let previous_carve_out_i32 = (42,).0i32;
+   |                                        ^^^^ invalid suffix `i32`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:34:40
+   |
+LL |     let previous_carve_out_i32 = (42,).0u32;
+   |                                        ^^^^ invalid suffix `u32`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:35:42
+   |
+LL |     let previous_carve_out_isize = (42,).0isize;
+   |                                          ^^^^^^ invalid suffix `isize`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:36:42
+   |
+LL |     let previous_carve_out_usize = (42,).0usize;
+   |                                          ^^^^^^ invalid suffix `usize`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:39:26
+   |
+LL |     let error_i8 = (42,).0i8;
+   |                          ^^^ invalid suffix `i8`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:40:26
+   |
+LL |     let error_u8 = (42,).0u8;
+   |                          ^^^ invalid suffix `u8`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:41:27
+   |
+LL |     let error_i16 = (42,).0i16;
+   |                           ^^^^ invalid suffix `i16`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:42:27
+   |
+LL |     let error_u16 = (42,).0u16;
+   |                           ^^^^ invalid suffix `u16`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:43:27
+   |
+LL |     let error_i64 = (42,).0i64;
+   |                           ^^^^ invalid suffix `i64`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:44:27
+   |
+LL |     let error_u64 = (42,).0u64;
+   |                           ^^^^ invalid suffix `u64`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:45:28
+   |
+LL |     let error_i128 = (42,).0i128;
+   |                            ^^^^^ invalid suffix `i128`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:46:28
+   |
+LL |     let error_u128 = (42,).0u128;
+   |                            ^^^^^ invalid suffix `u128`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:50:35
+   |
+LL |     let invalid_struct_name = X { 0suffix: 0, 1: 1, 2: 2 };
+   |                                   ^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:53:13
+   |
+LL |         X { 0suffix: _, .. } => {}
+   |             ^^^^^^^ invalid suffix `suffix`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:59:37
+   |
+LL |     let carve_out_struct_name = X { 0u32: 0, 1: 1, 2: 2 };
+   |                                     ^^^^ invalid suffix `u32`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:62:13
+   |
+LL |         X { 0u32: _, .. } => {}
+   |             ^^^^ invalid suffix `u32`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:73:50
+   |
+LL |     assert_eq!(std::mem::offset_of!(Struct<u32>, 0usize), 0);
+   |                                                  ^^^^^^ invalid suffix `usize`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/tuple-index-suffix.rs:77:50
+   |
+LL |     assert_eq!(std::mem::offset_of!(Struct<u32>, 0u8), 0);
+   |                                                  ^^^ invalid suffix `u8`
+
+error: aborting due to 22 previous errors
+
diff --git a/tests/ui/range/issue-54505-no-literals.stderr b/tests/ui/range/issue-54505-no-literals.stderr
index c6d4384bcd3..62e2fe4a838 100644
--- a/tests/ui/range/issue-54505-no-literals.stderr
+++ b/tests/ui/range/issue-54505-no-literals.stderr
@@ -207,7 +207,7 @@ LL |     take_range(std::ops::RangeToInclusive { end: 5 });
    |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
-                 found struct `RangeToInclusive<{integer}>`
+                 found struct `std::ops::RangeToInclusive<{integer}>`
 note: function defined here
   --> $DIR/issue-54505-no-literals.rs:12:4
    |
@@ -227,7 +227,7 @@ LL |     take_range(::std::ops::RangeToInclusive { end: 5 });
    |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
-                 found struct `RangeToInclusive<{integer}>`
+                 found struct `std::ops::RangeToInclusive<{integer}>`
 note: function defined here
   --> $DIR/issue-54505-no-literals.rs:12:4
    |
diff --git a/tests/ui/range/issue-54505-no-std.stderr b/tests/ui/range/issue-54505-no-std.stderr
index 2aa1d584046..866a82afb7e 100644
--- a/tests/ui/range/issue-54505-no-std.stderr
+++ b/tests/ui/range/issue-54505-no-std.stderr
@@ -112,7 +112,7 @@ LL |     take_range(..=42);
    |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
-                 found struct `RangeToInclusive<{integer}>`
+                 found struct `core::ops::RangeToInclusive<{integer}>`
 note: function defined here
   --> $DIR/issue-54505-no-std.rs:25:4
    |
diff --git a/tests/ui/range/issue-54505.stderr b/tests/ui/range/issue-54505.stderr
index 8b669b2910f..4d94c6c2d09 100644
--- a/tests/ui/range/issue-54505.stderr
+++ b/tests/ui/range/issue-54505.stderr
@@ -112,7 +112,7 @@ LL |     take_range(..=42);
    |     arguments to this function are incorrect
    |
    = note: expected reference `&_`
-                 found struct `RangeToInclusive<{integer}>`
+                 found struct `std::ops::RangeToInclusive<{integer}>`
 note: function defined here
   --> $DIR/issue-54505.rs:10:4
    |
diff --git a/tests/ui/static/static-align.rs b/tests/ui/static/static-align.rs
new file mode 100644
index 00000000000..93241db09f9
--- /dev/null
+++ b/tests/ui/static/static-align.rs
@@ -0,0 +1,26 @@
+//@ run-pass
+#![feature(static_align)]
+
+#[rustc_align_static(64)]
+static A: u8 = 0;
+
+#[rustc_align_static(64)]
+static B: u8 = 0;
+
+#[rustc_align_static(128)]
+#[no_mangle]
+static EXPORTED: u64 = 0;
+
+unsafe extern "C" {
+    #[rustc_align_static(128)]
+    #[link_name = "EXPORTED"]
+    static C: u64;
+}
+
+fn main() {
+    assert!(core::ptr::from_ref(&A).addr().is_multiple_of(64));
+    assert!(core::ptr::from_ref(&B).addr().is_multiple_of(64));
+
+    assert!(core::ptr::from_ref(&EXPORTED).addr().is_multiple_of(128));
+    unsafe { assert!(core::ptr::from_ref(&C).addr().is_multiple_of(128)) };
+}
diff --git a/tests/ui/suggestions/apitit-unimplemented-method.rs b/tests/ui/suggestions/apitit-unimplemented-method.rs
new file mode 100644
index 00000000000..b182e1939b3
--- /dev/null
+++ b/tests/ui/suggestions/apitit-unimplemented-method.rs
@@ -0,0 +1,12 @@
+//@ aux-build:dep.rs
+
+extern crate dep;
+use dep::*;
+
+struct Local;
+impl Trait for Local {}
+//~^ ERROR not all trait items implemented
+//~| HELP implement the missing item: `fn foo(_: impl Sized) { todo!() }`
+//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
+
+fn main() {}
diff --git a/tests/ui/suggestions/apitit-unimplemented-method.stderr b/tests/ui/suggestions/apitit-unimplemented-method.stderr
new file mode 100644
index 00000000000..b309a64e958
--- /dev/null
+++ b/tests/ui/suggestions/apitit-unimplemented-method.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `foo`, `bar`
+  --> $DIR/apitit-unimplemented-method.rs:7:1
+   |
+LL | impl Trait for Local {}
+   | ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation
+   |
+   = help: implement the missing item: `fn foo(_: impl Sized) { todo!() }`
+   = help: implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/suggestions/auxiliary/dep.rs b/tests/ui/suggestions/auxiliary/dep.rs
new file mode 100644
index 00000000000..ac0de418313
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/dep.rs
@@ -0,0 +1,4 @@
+pub trait Trait {
+    fn foo(_: impl Sized);
+    fn bar<T>(_: impl Sized);
+}
diff --git a/triagebot.toml b/triagebot.toml
index bf9bfee4306..2d58c616bc2 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1308,21 +1308,32 @@ cc = ["@m-ou-se"]
 [mentions."compiler/rustc_ast_lowering/src/format.rs"]
 cc = ["@m-ou-se"]
 
+# Content-based mentions
+
 [mentions."#[miri::intrinsic_fallback_is_spec]"]
 type = "content"
 message = """
-`#[miri::intrinsic_fallback_is_spec]` must only be used if the function actively checks for all UB cases,
+⚠️ `#[miri::intrinsic_fallback_is_spec]` must only be used if the function actively checks for all UB cases,
 and explores the possible non-determinism of the intrinsic.
 """
 cc = ["@rust-lang/miri"]
+
 [mentions."#[rustc_allow_const_fn_unstable"]
 type = "content"
 message = """
-`#[rustc_allow_const_fn_unstable]` needs careful audit to avoid accidentally exposing unstable
+⚠️ `#[rustc_allow_const_fn_unstable]` needs careful audit to avoid accidentally exposing unstable
 implementation details on stable.
 """
 cc = ["@rust-lang/wg-const-eval"]
 
+[mentions."#[rustc_intrinsic_const_stable_indirect]"]
+type = "content"
+message = """
+⚠️ `#[rustc_intrinsic_const_stable_indirect]` controls whether intrinsics can be exposed to stable const
+code; adding it needs t-lang approval.
+"""
+cc = ["@rust-lang/wg-const-eval"]
+
 
 # ------------------------------------------------------------------------------
 # PR assignments