about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-09-10 15:09:18 +0000
committerbors <bors@rust-lang.org>2025-09-10 15:09:18 +0000
commit565a9ca63e9df4b223fed0da01f15e578acfb538 (patch)
treefdbc4245cfe17954d617a6f3c9b89c025ff128cb
parent7ad23f43a225546c095123de52cc07d8719f8e2b (diff)
parent212baec446dd7fc7bbda66a4b3b0e2f856d575ce (diff)
downloadrust-565a9ca63e9df4b223fed0da01f15e578acfb538.tar.gz
rust-565a9ca63e9df4b223fed0da01f15e578acfb538.zip
Auto merge of #146409 - matthiaskrgr:rollup-thju381, r=matthiaskrgr
Rollup of 5 pull requests

Successful merges:

 - rust-lang/rust#144765 (inclusive `Range`s: change `end` to `last`)
 - rust-lang/rust#146178 (Implement `#[rustc_align_static(N)]` on `static`s)
 - rust-lang/rust#146368 (CI: rfl: move job forward to Linux v6.17-rc5 to remove temporary commits)
 - rust-lang/rust#146378 (Update wasm-component-ld to 0.5.17)
 - rust-lang/rust#146391 (Trim paths less in MIR dumping)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock50
-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_codegen_gcc/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs1
-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_index/src/idx.rs15
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs11
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs12
-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--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
-rwxr-xr-xsrc/ci/docker/scripts/rfl-build.sh4
-rw-r--r--src/tools/clippy/clippy_utils/src/sym.rs1
-rw-r--r--src/tools/miri/tests/pass/static_align.rs14
-rw-r--r--src/tools/wasm-component-ld/Cargo.toml2
-rw-r--r--tests/codegen-llvm/align-static.rs31
-rw-r--r--tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir2
-rw-r--r--tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir2
-rw-r--r--tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir2
-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/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
49 files changed, 530 insertions, 97 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 24cd5b825b2..8be13e84596 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5984,9 +5984,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-component-ld"
-version = "0.5.16"
+version = "0.5.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14cd35d6cae91109a0ffd207b573cf3c741cab7e921dd376ea7aaf2c52a3408c"
+checksum = "1c9208f87cac2332fd80dcf36d54e9163d3446e28301e0c6e424984425738984"
 dependencies = [
  "anyhow",
  "clap",
@@ -5994,9 +5994,9 @@ dependencies = [
  "libc",
  "tempfile",
  "wasi-preview1-component-adapter-provider",
- "wasmparser 0.237.0",
+ "wasmparser 0.239.0",
  "wat",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
  "winsplit",
  "wit-component",
  "wit-parser",
@@ -6021,24 +6021,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.237.0"
+version = "0.239.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efe92d1321afa53ffc88a57c497bb7330c3cf84c98ffdba4a4caf6a0684fad3c"
+checksum = "5be00faa2b4950c76fe618c409d2c3ea5a3c9422013e079482d78544bb2d184c"
 dependencies = [
  "leb128fmt",
- "wasmparser 0.237.0",
+ "wasmparser 0.239.0",
 ]
 
 [[package]]
 name = "wasm-metadata"
-version = "0.237.0"
+version = "0.239.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cc0b0a0c4f35ca6efa7a797671372915d4e9659dba2d59edc6fafc931d19997"
+checksum = "20b3ec880a9ac69ccd92fbdbcf46ee833071cf09f82bb005b2327c7ae6025ae2"
 dependencies = [
  "anyhow",
  "indexmap",
- "wasm-encoder 0.237.0",
- "wasmparser 0.237.0",
+ "wasm-encoder 0.239.0",
+ "wasmparser 0.239.0",
 ]
 
 [[package]]
@@ -6063,9 +6063,9 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.237.0"
+version = "0.239.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d2a40ca0d2bdf4b0bf36c13a737d0b2c58e4c8aaefe1c57f336dd75369ca250"
+checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0"
 dependencies = [
  "bitflags",
  "hashbrown",
@@ -6076,22 +6076,22 @@ dependencies = [
 
 [[package]]
 name = "wast"
-version = "237.0.0"
+version = "239.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf66f545acbd55082485cb9a6daab54579cb8628a027162253e8e9f5963c767"
+checksum = "9139176fe8a2590e0fb174cdcaf373b224cb93c3dde08e4297c1361d2ba1ea5d"
 dependencies = [
  "bumpalo",
  "leb128fmt",
  "memchr",
  "unicode-width 0.2.1",
- "wasm-encoder 0.237.0",
+ "wasm-encoder 0.239.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.237.0"
+version = "1.239.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27975186f549e4b8d6878b627be732863883c72f7bf4dcf8f96e5f8242f73da9"
+checksum = "3e1c941927d34709f255558166f8901a2005f8ab4a9650432e9281b7cc6f3b75"
 dependencies = [
  "wast",
 ]
@@ -6580,9 +6580,9 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.237.0"
+version = "0.239.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfb7674f76c10e82fe00b256a9d4ffb2b8d037d42ab8e9a83ebb3be35c9d0bf6"
+checksum = "88a866b19dba2c94d706ec58c92a4c62ab63e482b4c935d2a085ac94caecb136"
 dependencies = [
  "anyhow",
  "bitflags",
@@ -6591,17 +6591,17 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder 0.237.0",
+ "wasm-encoder 0.239.0",
  "wasm-metadata",
- "wasmparser 0.237.0",
+ "wasmparser 0.239.0",
  "wit-parser",
 ]
 
 [[package]]
 name = "wit-parser"
-version = "0.237.0"
+version = "0.239.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce2596a5bc7c24cc965b56ad6ff9e32394c4e401764f89620a888519c6e849ab"
+checksum = "55c92c939d667b7bf0c6bf2d1f67196529758f99a2a45a3355cc56964fd5315d"
 dependencies = [
  "anyhow",
  "id-arena",
@@ -6612,7 +6612,7 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "unicode-xid",
- "wasmparser 0.237.0",
+ "wasmparser 0.239.0",
 ]
 
 [[package]]
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_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_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_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/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_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_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/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index a7d99f513a1..f9d0a5f0a3b 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -78,8 +78,9 @@ impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, pass_name: &'static str, body: &Body<'tcx>) -> Option<Self> {
         let dump_enabled = if let Some(ref filters) = tcx.sess.opts.unstable_opts.dump_mir {
             // see notes on #41697 below
-            let node_path =
-                ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id()));
+            let node_path = ty::print::with_no_trimmed_paths!(
+                ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id()))
+            );
             filters.split('|').any(|or_filter| {
                 or_filter.split('&').all(|and_filter| {
                     let and_filter_trimmed = and_filter.trim();
@@ -173,9 +174,10 @@ impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> {
     // trigger `type_of`, and this can run while we are already attempting to evaluate `type_of`.
     pub fn dump_mir_to_writer(&self, body: &Body<'tcx>, w: &mut dyn io::Write) -> io::Result<()> {
         // see notes on #41697 above
-        let def_path = ty::print::with_forced_impl_filename_line!(
-            self.tcx().def_path_str(body.source.def_id())
-        );
+        let def_path =
+            ty::print::with_no_trimmed_paths!(ty::print::with_forced_impl_filename_line!(
+                self.tcx().def_path_str(body.source.def_id())
+            ));
         // ignore-tidy-odd-backticks the literal below is fine
         write!(w, "// MIR for `{def_path}")?;
         match body.source.promoted {
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/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/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_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/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/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml
index 23dc86998e8..3def2391a13 100644
--- a/src/tools/wasm-component-ld/Cargo.toml
+++ b/src/tools/wasm-component-ld/Cargo.toml
@@ -10,4 +10,4 @@ name = "wasm-component-ld"
 path = "src/main.rs"
 
 [dependencies]
-wasm-component-ld = "0.5.16"
+wasm-component-ld = "0.5.17"
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/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir
index 7be3ab8cbae..8e47aabb9b9 100644
--- a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir
+++ b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-abort.mir
@@ -1,4 +1,4 @@
-// MIR for `drop_in_place` after SimplifyCfg-make_shim
+// MIR for `std::ptr::drop_in_place` after SimplifyCfg-make_shim
 
 fn drop_in_place(_1: *mut Test) -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir
index 6c3c1aaa2bd..2457405d996 100644
--- a/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir
+++ b/tests/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.panic-unwind.mir
@@ -1,4 +1,4 @@
-// MIR for `drop_in_place` after SimplifyCfg-make_shim
+// MIR for `std::ptr::drop_in_place` after SimplifyCfg-make_shim
 
 fn drop_in_place(_1: *mut Test) -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir
index 9d5af8e84e4..ed3f4788cea 100644
--- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir
+++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String;42].AddMovesForPackedDrops.before.mir
@@ -1,4 +1,4 @@
-// MIR for `drop_in_place` before AddMovesForPackedDrops
+// MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops
 
 fn drop_in_place(_1: *mut [String; 42]) -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
index 144880d1598..bee671af6df 100644
--- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
+++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
@@ -1,4 +1,4 @@
-// MIR for `drop_in_place` before AddMovesForPackedDrops
+// MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops
 
 fn drop_in_place(_1: *mut [String]) -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
index 51ef9f7c068..1bdb1c1debd 100644
--- a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
+++ b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
@@ -1,4 +1,4 @@
-// MIR for `drop_in_place` before AddMovesForPackedDrops
+// MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops
 
 fn drop_in_place(_1: *mut Vec<i32>) -> () {
     let mut _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/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)) };
+}