From 8366c7fe9c2db004224648239644f0fbecc185ea Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Thu, 18 Jul 2024 11:54:04 -0300
Subject: [PATCH 1/9] Stabilize unsafe extern blocks (RFC 3484)

---
 .../rustc_ast_passes/src/ast_validation.rs    | 42 ++++++-------------
 compiler/rustc_ast_passes/src/feature_gate.rs |  4 --
 compiler/rustc_feature/src/accepted.rs        |  2 +
 compiler/rustc_feature/src/unstable.rs        |  2 -
 compiler/rustc_lint_defs/src/builtin.rs       |  1 -
 compiler/rustc_parse/src/parser/mod.rs        |  3 --
 tests/rustdoc/unsafe-extern-blocks.rs         |  3 +-
 .../feature-gate-unsafe-extern-blocks.rs      | 13 ------
 .../feature-gate-unsafe-extern-blocks.stderr  | 23 ----------
 .../lint/unsafe_code/unsafe-extern-blocks.rs  |  1 -
 .../unsafe_code/unsafe-extern-blocks.stderr   |  4 +-
 tests/ui/parser/unsafe-foreign-mod-2.rs       |  2 -
 tests/ui/parser/unsafe-foreign-mod-2.stderr   | 18 +-------
 tests/ui/parser/unsafe-foreign-mod.rs         |  6 +--
 tests/ui/parser/unsafe-foreign-mod.stderr     | 12 ------
 tests/ui/rust-2024/safe-outside-extern.rs     |  8 ----
 tests/ui/rust-2024/safe-outside-extern.stderr | 38 +++++++++++++++++
 .../extern-items-unsafe.edition2021.stderr    |  4 +-
 .../extern-items-unsafe.edition2024.stderr    |  4 +-
 .../extern-items-unsafe.rs                    |  2 -
 .../extern-items.edition2024.stderr           |  2 +-
 .../unsafe-extern-blocks/extern-items.rs      |  2 -
 .../unsafe-extern-blocks/safe-impl-trait.rs   |  3 --
 ...it.gated.stderr => safe-impl-trait.stderr} |  2 +-
 .../unsafe-extern-blocks/safe-items.rs        |  2 -
 .../unsafe-extern-blocks/safe-trait.rs        |  3 --
 .../unsafe-extern-blocks/safe-trait.stderr    |  8 ++++
 ...-unadorned-extern-block.edition2021.stderr |  4 +-
 ...-unadorned-extern-block.edition2024.stderr |  6 +--
 .../safe-unsafe-on-unadorned-extern-block.rs  |  2 -
 .../unsafe-extern-suggestion.fixed            |  1 -
 .../unsafe-extern-suggestion.rs               |  1 -
 .../unsafe-extern-suggestion.stderr           |  4 +-
 .../unsafe-items.edition2021.stderr           |  4 +-
 .../unsafe-items.edition2024.stderr           |  4 +-
 .../unsafe-extern-blocks/unsafe-items.rs      |  2 -
 .../unsafe-on-extern-block-issue-126756.fixed |  1 -
 .../unsafe-on-extern-block-issue-126756.rs    |  1 -
 ...unsafe-on-extern-block-issue-126756.stderr |  2 +-
 tests/ui/unpretty/expanded-exhaustive.rs      |  1 -
 tests/ui/unpretty/expanded-exhaustive.stdout  |  1 -
 41 files changed, 85 insertions(+), 163 deletions(-)
 delete mode 100644 tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs
 delete mode 100644 tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr
 delete mode 100644 tests/ui/parser/unsafe-foreign-mod.stderr
 create mode 100644 tests/ui/rust-2024/safe-outside-extern.stderr
 rename tests/ui/rust-2024/unsafe-extern-blocks/{safe-impl-trait.gated.stderr => safe-impl-trait.stderr} (83%)
 create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr

diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 34aac6e4473..af1d9beb527 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -452,11 +452,6 @@ impl<'a> AstValidator<'a> {
                             item_span: span,
                             block: Some(self.current_extern_span().shrink_to_lo()),
                         });
-                    } else if !self.features.unsafe_extern_blocks {
-                        self.dcx().emit_err(errors::InvalidSafetyOnExtern {
-                            item_span: span,
-                            block: None,
-                        });
                     }
                 }
             }
@@ -1053,32 +1048,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         errors::VisibilityNotPermittedNote::IndividualForeignItems,
                     );
 
-                    if this.features.unsafe_extern_blocks {
-                        if &Safety::Default == safety {
-                            if item.span.at_least_rust_2024() {
-                                this.dcx()
-                                    .emit_err(errors::MissingUnsafeOnExtern { span: item.span });
-                            } else {
-                                this.lint_buffer.buffer_lint(
-                                    MISSING_UNSAFE_ON_EXTERN,
-                                    item.id,
-                                    item.span,
-                                    BuiltinLintDiag::MissingUnsafeOnExtern {
-                                        suggestion: item.span.shrink_to_lo(),
-                                    },
-                                );
-                            }
+                    if &Safety::Default == safety {
+                        if item.span.at_least_rust_2024() {
+                            this.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span });
+                        } else {
+                            this.lint_buffer.buffer_lint(
+                                MISSING_UNSAFE_ON_EXTERN,
+                                item.id,
+                                item.span,
+                                BuiltinLintDiag::MissingUnsafeOnExtern {
+                                    suggestion: item.span.shrink_to_lo(),
+                                },
+                            );
                         }
-                    } else if let &Safety::Unsafe(span) = safety {
-                        let mut diag = this
-                            .dcx()
-                            .create_err(errors::UnsafeItem { span, kind: "extern block" });
-                        rustc_session::parse::add_feature_diagnostics(
-                            &mut diag,
-                            self.session,
-                            sym::unsafe_extern_blocks,
-                        );
-                        diag.emit();
                     }
 
                     if abi.is_none() {
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index e91dfb27766..f9119c06fcf 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -561,10 +561,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
     gate_all!(global_registration, "global registration is experimental");
     gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
-    gate_all!(
-        unsafe_extern_blocks,
-        "`unsafe extern {}` blocks and `safe` keyword are experimental"
-    );
     gate_all!(return_type_notation, "return type notation is experimental");
 
     if !visitor.features.never_patterns {
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e671c768239..d5874f79a22 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -387,6 +387,8 @@ declare_features! (
     (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)),
     /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
     (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)),
+    /// Allows unsafe on extern declarations and safety qualifiers over internal items.
+    (accepted, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)),
     /// Allows importing and reexporting macros with `use`,
     /// enables macro modularization in general.
     (accepted, use_extern_macros, "1.30.0", Some(35896)),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 741c621db08..e1433a66556 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -628,8 +628,6 @@ declare_features! (
     (incomplete, unnamed_fields, "1.74.0", Some(49804)),
     /// Allows unsafe attributes.
     (unstable, unsafe_attributes, "1.80.0", Some(123757)),
-    /// Allows unsafe on extern declarations and safety qualifiers over internal items.
-    (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)),
     /// Allows const generic parameters to be defined with types that
     /// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
     (incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)),
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 04764b71b10..4e1fbe8ae9d 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4865,7 +4865,6 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust
-    /// #![feature(unsafe_extern_blocks)]
     /// #![warn(missing_unsafe_on_extern)]
     /// #![allow(dead_code)]
     ///
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 7326b9ec51f..b46653717a4 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1205,9 +1205,6 @@ impl<'a> Parser<'a> {
         if self.eat_keyword_case(kw::Unsafe, case) {
             Safety::Unsafe(self.prev_token.uninterpolated_span())
         } else if self.eat_keyword_case(kw::Safe, case) {
-            self.psess
-                .gated_spans
-                .gate(sym::unsafe_extern_blocks, self.prev_token.uninterpolated_span());
             Safety::Safe(self.prev_token.uninterpolated_span())
         } else {
             Safety::Default
diff --git a/tests/rustdoc/unsafe-extern-blocks.rs b/tests/rustdoc/unsafe-extern-blocks.rs
index 22d3beea6c3..829095f300f 100644
--- a/tests/rustdoc/unsafe-extern-blocks.rs
+++ b/tests/rustdoc/unsafe-extern-blocks.rs
@@ -1,6 +1,5 @@
 // Test to ensure the feature is working as expected.
 
-#![feature(unsafe_extern_blocks)]
 #![crate_name = "foo"]
 
 // @has 'foo/index.html'
@@ -13,7 +12,7 @@
 // @count - '//ul[@class="item-table"]//sup[@title="unsafe function"]' 1
 // @has - '//ul[@class="item-table"]//sup[@title="unsafe function"]' '⚠'
 
-unsafe extern {
+unsafe extern "C" {
     // @has 'foo/static.FOO.html'
     // @has - '//pre[@class="rust item-decl"]' 'pub static FOO: i32'
     pub safe static FOO: i32;
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs
deleted file mode 100644
index 3ea62e875b8..00000000000
--- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-unsafe extern "C" {
-    //~^ ERROR extern block cannot be declared unsafe
-}
-
-// We can't gate `unsafe extern` blocks themselves since they were previously
-// allowed, but we should gate the `safe` soft keyword.
-#[cfg(any())]
-unsafe extern "C" {
-    safe fn foo();
-    //~^ ERROR `unsafe extern {}` blocks and `safe` keyword are experimental
-}
-
-fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr
deleted file mode 100644
index 56534946308..00000000000
--- a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error: extern block cannot be declared unsafe
-  --> $DIR/feature-gate-unsafe-extern-blocks.rs:1:1
-   |
-LL | unsafe extern "C" {
-   | ^^^^^^
-   |
-   = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
-   = help: add `#![feature(unsafe_extern_blocks)]` 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]: `unsafe extern {}` blocks and `safe` keyword are experimental
-  --> $DIR/feature-gate-unsafe-extern-blocks.rs:9:5
-   |
-LL |     safe fn foo();
-   |     ^^^^
-   |
-   = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
-   = help: add `#![feature(unsafe_extern_blocks)]` 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/lint/unsafe_code/unsafe-extern-blocks.rs b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
index 6f2ead70db8..c264fa1c8da 100644
--- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
+++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.rs
@@ -1,4 +1,3 @@
-#![feature(unsafe_extern_blocks)]
 #![deny(unsafe_code)]
 
 #[allow(unsafe_code)]
diff --git a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
index 5439a311256..6d3b064da34 100644
--- a/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
+++ b/tests/ui/lint/unsafe_code/unsafe-extern-blocks.stderr
@@ -1,5 +1,5 @@
 error: usage of an `unsafe extern` block
-  --> $DIR/unsafe-extern-blocks.rs:9:1
+  --> $DIR/unsafe-extern-blocks.rs:8:1
    |
 LL | / unsafe extern "C" {
 LL | |
@@ -8,7 +8,7 @@ LL | | }
    | |_^
    |
 note: the lint level is defined here
-  --> $DIR/unsafe-extern-blocks.rs:2:9
+  --> $DIR/unsafe-extern-blocks.rs:1:9
    |
 LL | #![deny(unsafe_code)]
    |         ^^^^^^^^^^^
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs
index 0b63a993c5b..6d339cd9088 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.rs
+++ b/tests/ui/parser/unsafe-foreign-mod-2.rs
@@ -1,8 +1,6 @@
 extern "C" unsafe {
     //~^ ERROR expected `{`, found keyword `unsafe`
-    //~| ERROR extern block cannot be declared unsafe
     unsafe fn foo();
-    //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers
 }
 
 fn main() {}
diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr
index 8bd592b5d43..0625e3362ed 100644
--- a/tests/ui/parser/unsafe-foreign-mod-2.stderr
+++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr
@@ -4,21 +4,5 @@ error: expected `{`, found keyword `unsafe`
 LL | extern "C" unsafe {
    |            ^^^^^^ expected `{`
 
-error: extern block cannot be declared unsafe
-  --> $DIR/unsafe-foreign-mod-2.rs:1:12
-   |
-LL | extern "C" unsafe {
-   |            ^^^^^^
-   |
-   = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
-   = help: add `#![feature(unsafe_extern_blocks)]` 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: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/unsafe-foreign-mod-2.rs:4:5
-   |
-LL |     unsafe fn foo();
-   |     ^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/unsafe-foreign-mod.rs b/tests/ui/parser/unsafe-foreign-mod.rs
index eab134a4a4d..623c3bb81e4 100644
--- a/tests/ui/parser/unsafe-foreign-mod.rs
+++ b/tests/ui/parser/unsafe-foreign-mod.rs
@@ -1,5 +1,5 @@
-unsafe extern "C" {
-    //~^ ERROR extern block cannot be declared unsafe
-}
+//@ check-pass
+
+unsafe extern "C" {}
 
 fn main() {}
diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr
deleted file mode 100644
index 60b918a89b3..00000000000
--- a/tests/ui/parser/unsafe-foreign-mod.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error: extern block cannot be declared unsafe
-  --> $DIR/unsafe-foreign-mod.rs:1:1
-   |
-LL | unsafe extern "C" {
-   | ^^^^^^
-   |
-   = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information
-   = help: add `#![feature(unsafe_extern_blocks)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/rust-2024/safe-outside-extern.rs b/tests/ui/rust-2024/safe-outside-extern.rs
index 6773df5ef03..674b78dc571 100644
--- a/tests/ui/rust-2024/safe-outside-extern.rs
+++ b/tests/ui/rust-2024/safe-outside-extern.rs
@@ -1,29 +1,21 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
 safe fn foo() {}
 //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 
 safe static FOO: i32 = 1;
 //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 
 trait Foo {
     safe fn foo();
     //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-    //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 }
 
 impl Foo for () {
     safe fn foo() {}
     //~^ ERROR: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
-    //[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 }
 
 type FnPtr = safe fn(i32, i32) -> i32;
 //~^ ERROR: function pointers cannot be declared with `safe` safety qualifier
-//[ungated]~| ERROR: unsafe extern {}` blocks and `safe` keyword are experimental [E0658]
 
 unsafe static LOL: u8 = 0;
 //~^ ERROR: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
diff --git a/tests/ui/rust-2024/safe-outside-extern.stderr b/tests/ui/rust-2024/safe-outside-extern.stderr
new file mode 100644
index 00000000000..19d7c5fde0b
--- /dev/null
+++ b/tests/ui/rust-2024/safe-outside-extern.stderr
@@ -0,0 +1,38 @@
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:1:1
+   |
+LL | safe fn foo() {}
+   | ^^^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:4:1
+   |
+LL | safe static FOO: i32 = 1;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:8:5
+   |
+LL |     safe fn foo();
+   |     ^^^^^^^^^^^^^^
+
+error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:13:5
+   |
+LL |     safe fn foo() {}
+   |     ^^^^^^^^^^^^^^^^
+
+error: function pointers cannot be declared with `safe` safety qualifier
+  --> $DIR/safe-outside-extern.rs:17:14
+   |
+LL | type FnPtr = safe fn(i32, i32) -> i32;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
+  --> $DIR/safe-outside-extern.rs:20:1
+   |
+LL | unsafe static LOL: u8 = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
index 3a99caa719b..77554da10e6 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
-  --> $DIR/extern-items-unsafe.rs:14:5
+  --> $DIR/extern-items-unsafe.rs:12:5
    |
 LL |     test1(TEST1);
    |     ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     test1(TEST1);
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/extern-items-unsafe.rs:14:11
+  --> $DIR/extern-items-unsafe.rs:12:11
    |
 LL |     test1(TEST1);
    |           ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
index fcf937b7ac5..33b752782d5 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
-  --> $DIR/extern-items-unsafe.rs:14:5
+  --> $DIR/extern-items-unsafe.rs:12:5
    |
 LL |     test1(TEST1);
    |     ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     test1(TEST1);
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: use of extern static is unsafe and requires unsafe block
-  --> $DIR/extern-items-unsafe.rs:14:11
+  --> $DIR/extern-items-unsafe.rs:12:11
    |
 LL |     test1(TEST1);
    |           ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
index ad569a256db..721e07acca5 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs
@@ -3,8 +3,6 @@
 //@[edition2024] edition:2024
 //@[edition2024] compile-flags: -Zunstable-options
 
-#![feature(unsafe_extern_blocks)]
-
 unsafe extern "C" {
     static TEST1: i32;
     fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
index d456cfc6829..8ef7c2caf21 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr
@@ -1,5 +1,5 @@
 error: extern blocks must be unsafe
-  --> $DIR/extern-items.rs:9:1
+  --> $DIR/extern-items.rs:7:1
    |
 LL | / extern "C" {
 LL | |
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
index 16fa1bbb8a4..08805c36347 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs
@@ -4,8 +4,6 @@
 //@[edition2024] edition:2024
 //@[edition2024] compile-flags: -Zunstable-options
 
-#![feature(unsafe_extern_blocks)]
-
 extern "C" {
     //[edition2024]~^ ERROR extern blocks must be unsafe
     static TEST1: i32;
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
index 57c03e4d896..67df8c14b39 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.rs
@@ -1,6 +1,3 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
 trait Bar {}
 safe impl Bar for () { }
 //~^ ERROR expected one of `!` or `::`, found keyword `impl`
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
similarity index 83%
rename from tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr
rename to tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
index 80e7a45f57e..f1021726b18 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.gated.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.stderr
@@ -1,5 +1,5 @@
 error: expected one of `!` or `::`, found keyword `impl`
-  --> $DIR/safe-impl-trait.rs:5:6
+  --> $DIR/safe-impl-trait.rs:2:6
    |
 LL | safe impl Bar for () { }
    |      ^^^^ expected one of `!` or `::`
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
index 74cd5621fce..b0b8a8b012a 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs
@@ -4,8 +4,6 @@
 //@[edition2024] compile-flags: -Zunstable-options
 //@ check-pass
 
-#![feature(unsafe_extern_blocks)]
-
 unsafe extern "C" {
     safe static TEST1: i32;
     safe fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
index e73cb45b188..52773b4cbbb 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.rs
@@ -1,6 +1,3 @@
-//@ revisions: gated ungated
-#![cfg_attr(gated, feature(unsafe_extern_blocks))]
-
 safe trait Foo {}
 //~^ ERROR expected one of `!` or `::`, found keyword `trait`
 
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr
new file mode 100644
index 00000000000..1733336a797
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found keyword `trait`
+  --> $DIR/safe-trait.rs:1:6
+   |
+LL | safe trait Foo {}
+   |      ^^^^^ expected one of `!` or `::`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
index e90613357b1..93797987286 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr
@@ -1,5 +1,5 @@
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5
    |
 LL |     safe static TEST1: i32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -10,7 +10,7 @@ LL | unsafe extern "C" {
    | ++++++
 
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
    |
 LL |     safe fn test1(i: i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
index 1207ee158cc..e9db6006c0b 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr
@@ -1,5 +1,5 @@
 error: extern blocks must be unsafe
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:1
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:6:1
    |
 LL | / extern "C" {
 LL | |
@@ -11,7 +11,7 @@ LL | | }
    | |_^
 
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:5
    |
 LL |     safe static TEST1: i32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | unsafe extern "C" {
    | ++++++
 
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5
+  --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5
    |
 LL |     safe fn test1(i: i32);
    |     ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
index 11f55cb195f..4badb50b267 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs
@@ -3,8 +3,6 @@
 //@[edition2024] edition:2024
 //@[edition2024] compile-flags: -Zunstable-options
 
-#![feature(unsafe_extern_blocks)]
-
 extern "C" {
     //[edition2024]~^ ERROR extern blocks must be unsafe
     safe static TEST1: i32;
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
index 10c19759d8a..f686809615f 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed
@@ -1,6 +1,5 @@
 //@ run-rustfix
 
-#![feature(unsafe_extern_blocks)]
 #![deny(missing_unsafe_on_extern)]
 #![allow(unused)]
 
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
index b81e52ddc58..00f1cbdab54 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs
@@ -1,6 +1,5 @@
 //@ run-rustfix
 
-#![feature(unsafe_extern_blocks)]
 #![deny(missing_unsafe_on_extern)]
 #![allow(unused)]
 
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
index 0a3c2cd25e3..bb1d068ceb9 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr
@@ -1,5 +1,5 @@
 error: extern blocks should be unsafe
-  --> $DIR/unsafe-extern-suggestion.rs:7:1
+  --> $DIR/unsafe-extern-suggestion.rs:6:1
    |
 LL |   extern "C" {
    |   ^
@@ -16,7 +16,7 @@ LL | | }
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
    = note: for more information, see issue #123743 <https://github.com/rust-lang/rust/issues/123743>
 note: the lint level is defined here
-  --> $DIR/unsafe-extern-suggestion.rs:4:9
+  --> $DIR/unsafe-extern-suggestion.rs:3:9
    |
 LL | #![deny(missing_unsafe_on_extern)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
index 8bb7ffefeea..e3626bb497e 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-items.rs:20:5
+  --> $DIR/unsafe-items.rs:18:5
    |
 LL |     test1(TEST1);
    |     ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     test1(TEST1);
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/unsafe-items.rs:20:11
+  --> $DIR/unsafe-items.rs:18:11
    |
 LL |     test1(TEST1);
    |           ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
index 9a30142a632..89bc501b7b5 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr
@@ -1,5 +1,5 @@
 error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block
-  --> $DIR/unsafe-items.rs:20:5
+  --> $DIR/unsafe-items.rs:18:5
    |
 LL |     test1(TEST1);
    |     ^^^^^^^^^^^^ call to unsafe function
@@ -7,7 +7,7 @@ LL |     test1(TEST1);
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: use of extern static is unsafe and requires unsafe block
-  --> $DIR/unsafe-items.rs:20:11
+  --> $DIR/unsafe-items.rs:18:11
    |
 LL |     test1(TEST1);
    |           ^^^^^ use of extern static
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
index 9066953abc6..dc2bae892a9 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs
@@ -3,8 +3,6 @@
 //@[edition2024] edition:2024
 //@[edition2024] compile-flags: -Zunstable-options
 
-#![feature(unsafe_extern_blocks)]
-
 unsafe extern "C" {
     unsafe static TEST1: i32;
     unsafe fn test1(i: i32);
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
index 2ff595cc44d..857d34eef85 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.fixed
@@ -1,6 +1,5 @@
 //@ run-rustfix
 
-#![feature(unsafe_extern_blocks)]
 #![allow(dead_code)]
 
 unsafe extern "C" {
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
index 6fe43f7a5b4..edab9850d79 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.rs
@@ -1,6 +1,5 @@
 //@ run-rustfix
 
-#![feature(unsafe_extern_blocks)]
 #![allow(dead_code)]
 
 extern "C" {
diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
index 05d23d001ad..073245e650b 100644
--- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
+++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-on-extern-block-issue-126756.stderr
@@ -1,5 +1,5 @@
 error: items in unadorned `extern` blocks cannot have safety qualifiers
-  --> $DIR/unsafe-on-extern-block-issue-126756.rs:7:5
+  --> $DIR/unsafe-on-extern-block-issue-126756.rs:6:5
    |
 LL |     unsafe fn foo();
    |     ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs
index 92c2e7b4884..29472df897a 100644
--- a/tests/ui/unpretty/expanded-exhaustive.rs
+++ b/tests/ui/unpretty/expanded-exhaustive.rs
@@ -25,7 +25,6 @@
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(unnamed_fields)]
-#![feature(unsafe_extern_blocks)]
 #![feature(yeet_expr)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 137a8aa5510..cf2f6f8cbaa 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -26,7 +26,6 @@
 #![feature(trait_alias)]
 #![feature(try_blocks)]
 #![feature(unnamed_fields)]
-#![feature(unsafe_extern_blocks)]
 #![feature(yeet_expr)]
 #![allow(incomplete_features)]
 #[prelude_import]

From 77ca30f1950a062e9eb1caeff790618488058057 Mon Sep 17 00:00:00 2001
From: Scott McMurray <scottmcm@users.noreply.github.com>
Date: Thu, 1 Aug 2024 21:58:34 -0700
Subject: [PATCH 2/9] Implement `UncheckedIterator` directly for `RepeatN`

---
 library/core/src/iter/sources/repeat_n.rs   | 33 +++++++++++++--------
 tests/codegen/iter-repeat-n-trivial-drop.rs | 15 +++++++++-
 2 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index 8390dab8e54..4c4ae39f836 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -114,19 +114,12 @@ impl<A: Clone> Iterator for RepeatN<A> {
 
     #[inline]
     fn next(&mut self) -> Option<A> {
-        if self.count == 0 {
-            return None;
-        }
-
-        self.count -= 1;
-        Some(if self.count == 0 {
-            // SAFETY: the check above ensured that the count used to be non-zero,
-            // so element hasn't been dropped yet, and we just lowered the count to
-            // zero so it won't be dropped later, and thus it's okay to take it here.
-            unsafe { ManuallyDrop::take(&mut self.element) }
+        if self.count > 0 {
+            // SAFETY: Just checked it's not empty
+            unsafe { Some(self.next_unchecked()) }
         } else {
-            A::clone(&self.element)
-        })
+            None
+        }
     }
 
     #[inline]
@@ -194,4 +187,18 @@ impl<A: Clone> FusedIterator for RepeatN<A> {}
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
 #[unstable(feature = "trusted_len_next_unchecked", issue = "37572")]
-impl<A: Clone> UncheckedIterator for RepeatN<A> {}
+impl<A: Clone> UncheckedIterator for RepeatN<A> {
+    #[inline]
+    unsafe fn next_unchecked(&mut self) -> Self::Item {
+        // SAFETY: The caller promised the iterator isn't empty
+        self.count = unsafe { self.count.unchecked_sub(1) };
+        if self.count == 0 {
+            // SAFETY: the check above ensured that the count used to be non-zero,
+            // so element hasn't been dropped yet, and we just lowered the count to
+            // zero so it won't be dropped later, and thus it's okay to take it here.
+            unsafe { ManuallyDrop::take(&mut self.element) }
+        } else {
+            A::clone(&self.element)
+        }
+    }
+}
diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs
index 31020b77984..7de224b92d8 100644
--- a/tests/codegen/iter-repeat-n-trivial-drop.rs
+++ b/tests/codegen/iter-repeat-n-trivial-drop.rs
@@ -1,8 +1,9 @@
-//@ compile-flags: -O
+//@ compile-flags: -C opt-level=3
 //@ only-x86_64
 
 #![crate_type = "lib"]
 #![feature(iter_repeat_n)]
+#![feature(array_repeat)]
 
 #[derive(Clone)]
 pub struct NotCopy(u16);
@@ -54,3 +55,15 @@ pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
     v.extend(std::iter::repeat_n(42_u8, n));
     v
 }
+
+// Array repeat uses `RepeatN::next_unchecked` internally,
+// so also check that the distinction disappears there.
+
+#[no_mangle]
+// CHECK-LABEL: @array_repeat_not_copy
+pub unsafe fn array_repeat_not_copy(item: NotCopy) -> [NotCopy; 8] {
+    // CHECK: insertelement {{.+}} i16 %item
+    // CHECK: shufflevector <8 x i16> {{.+}} zeroinitializer
+    // CHECK: store <8 x i16>
+    std::array::repeat(item)
+}

From 6264d2eba9d5b237a5c5c9a9527fbda54d751203 Mon Sep 17 00:00:00 2001
From: binarycat <binarycat@envs.net>
Date: Sat, 27 Jul 2024 15:15:02 -0400
Subject: [PATCH 3/9] bootstrap: fix bug preventing the use of custom targets

the bug was caused by two factors:
1. only checking the RUST_TARGET_PATH form, not the full filepath form
2. indirectly trying to use the Debug presentation to get the file path
---
 src/bootstrap/src/core/config/config.rs |  5 +++++
 src/bootstrap/src/core/sanity.rs        | 12 +++++++++---
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 1343e257efe..776e2c5cb17 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -512,6 +512,11 @@ impl TargetSelection {
     pub fn is_windows(&self) -> bool {
         self.contains("windows")
     }
+
+    /// Path to the file defining the custom target, if any.
+    pub fn filepath(&self) -> Option<&Path> {
+        self.file.as_ref().map(Path::new)
+    }
 }
 
 impl fmt::Display for TargetSelection {
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 45f4090ef22..c42d4c56c38 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -260,7 +260,9 @@ than building it.
 
             if !has_target {
                 // This might also be a custom target, so check the target file that could have been specified by the user.
-                if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") {
+                if target.filepath().is_some_and(|p| p.exists()) {
+                    has_target = true;
+                } else if let Some(custom_target_path) = env::var_os("RUST_TARGET_PATH") {
                     let mut target_filename = OsString::from(&target_str);
                     // Target filename ends with `.json`.
                     target_filename.push(".json");
@@ -275,8 +277,12 @@ than building it.
 
             if !has_target {
                 panic!(
-                    "No such target exists in the target list,
-                specify a correct location of the JSON specification file for custom targets!"
+                    "No such target exists in the target list,\n\
+                     make sure to correctly specify the location \
+                     of the JSON specification file \
+                     for custom targets!\n\
+                     Use BOOTSTRAP_SKIP_TARGET_SANITY=1 to \
+                     bypass this check."
                 );
             }
         }

From a798e0f4883997907e6a1ffa484071c0ceb2ba85 Mon Sep 17 00:00:00 2001
From: Konippi <konippi-114@outlook.jp>
Date: Fri, 2 Aug 2024 23:58:05 +0900
Subject: [PATCH 4/9] chore: refactor backtrace style in panic

---
 library/std/src/panic.rs | 29 ++++++++++-------------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 2ca9256715c..4c496ade81c 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -463,11 +463,10 @@ static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0);
 /// environment variable; see the details in [`get_backtrace_style`].
 #[unstable(feature = "panic_backtrace_config", issue = "93346")]
 pub fn set_backtrace_style(style: BacktraceStyle) {
-    if !cfg!(feature = "backtrace") {
-        // If the `backtrace` feature of this crate isn't enabled, skip setting.
-        return;
+    if cfg!(feature = "backtrace") {
+        // If the `backtrace` feature of this crate is enabled, set the backtrace style.
+        SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release);
     }
-    SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release);
 }
 
 /// Checks whether the standard library's panic hook will capture and print a
@@ -503,21 +502,13 @@ pub fn get_backtrace_style() -> Option<BacktraceStyle> {
         return Some(style);
     }
 
-    let format = crate::env::var_os("RUST_BACKTRACE")
-        .map(|x| {
-            if &x == "0" {
-                BacktraceStyle::Off
-            } else if &x == "full" {
-                BacktraceStyle::Full
-            } else {
-                BacktraceStyle::Short
-            }
-        })
-        .unwrap_or(if crate::sys::FULL_BACKTRACE_DEFAULT {
-            BacktraceStyle::Full
-        } else {
-            BacktraceStyle::Off
-        });
+    let format = match crate::env::var_os("RUST_BACKTRACE") {
+        Some(x) if &x == "0" => BacktraceStyle::Off,
+        Some(x) if &x == "full" => BacktraceStyle::Full,
+        Some(_) => BacktraceStyle::Short,
+        None if crate::sys::FULL_BACKTRACE_DEFAULT => BacktraceStyle::Full,
+        None => BacktraceStyle::Off,
+    };
     set_backtrace_style(format);
     Some(format)
 }

From ed010dd32c55c2add60dc4baff837b281cf81be8 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 31 Jul 2024 15:56:09 +0000
Subject: [PATCH 5/9] Assert that all attributes are actually checked via
 `CheckAttrVisitor` and aren't accidentally usable on completely unrelated HIR
 nodes

Co-authored-by: Jieyou Xu <jieyouxu@outlook.com>
---
 compiler/rustc_feature/src/builtin_attrs.rs |  8 +--
 compiler/rustc_passes/messages.ftl          |  4 ++
 compiler/rustc_passes/src/check_attr.rs     | 66 ++++++++++++++++++++-
 compiler/rustc_passes/src/errors.rs         |  7 +++
 4 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index ef03a25bc16..72ea55d5999 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -703,21 +703,21 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         EncodeCrossCrate::No, allocator_internals, experimental!(needs_allocator),
     ),
     gated!(
-        panic_runtime, Normal, template!(Word), WarnFollowing,
+        panic_runtime, CrateLevel, template!(Word), WarnFollowing,
         EncodeCrossCrate::No, experimental!(panic_runtime)
     ),
     gated!(
-        needs_panic_runtime, Normal, template!(Word), WarnFollowing,
+        needs_panic_runtime, CrateLevel, template!(Word), WarnFollowing,
         EncodeCrossCrate::No, experimental!(needs_panic_runtime)
     ),
     gated!(
-        compiler_builtins, Normal, template!(Word), WarnFollowing,
+        compiler_builtins, CrateLevel, template!(Word), WarnFollowing,
         EncodeCrossCrate::No,
         "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
         which contains compiler-rt intrinsics and will never be stable",
     ),
     gated!(
-        profiler_runtime, Normal, template!(Word), WarnFollowing,
+        profiler_runtime, CrateLevel, template!(Word), WarnFollowing,
         EncodeCrossCrate::No,
         "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
         which contains the profiler runtime and will never be stable",
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 1747307a1b2..59c9d1e49f5 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -100,6 +100,10 @@ passes_continue_labeled_block =
     .label = labeled blocks cannot be `continue`'d
     .block_label = labeled block the `continue` points to
 
+passes_coroutine_on_non_closure =
+    attribute should be applied to closures
+    .label = not a closure
+
 passes_coverage_not_fn_or_closure =
     attribute should be applied to a function definition or closure
     .label = not a function or closure
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 86b18570f37..755f67b3f4f 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -20,13 +20,13 @@ use rustc_hir::{
     TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
 };
 use rustc_macros::LintDiagnostic;
-use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::{
     CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
     UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
@@ -239,7 +239,59 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     self.check_generic_attr(hir_id, attr, target, Target::Fn);
                     self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
                 }
-                _ => {}
+                [sym::coroutine] => {
+                    self.check_coroutine(attr, target);
+                }
+                [
+                    // ok
+                    sym::allow
+                    | sym::expect
+                    | sym::warn
+                    | sym::deny
+                    | sym::forbid
+                    | sym::cfg
+                    // need to be fixed
+                    | sym::cfi_encoding // FIXME(cfi_encoding)
+                    | sym::may_dangle // FIXME(dropck_eyepatch)
+                    | sym::pointee // FIXME(derive_smart_pointer)
+                    | sym::linkage // FIXME(linkage)
+                    | sym::no_sanitize // FIXME(no_sanitize)
+                    | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section)
+                    | sym::used // handled elsewhere to restrict to static items
+                    | sym::repr // handled elsewhere to restrict to type decls items
+                    | sym::instruction_set // broken on stable!!!
+                    | sym::windows_subsystem // broken on stable!!!
+                    | sym::patchable_function_entry // FIXME(patchable_function_entry)
+                    | sym::deprecated_safe // FIXME(deprecated_safe)
+                    // internal
+                    | sym::prelude_import
+                    | sym::panic_handler
+                    | sym::allow_internal_unsafe
+                    | sym::fundamental
+                    | sym::lang
+                    | sym::needs_allocator
+                    | sym::default_lib_allocator
+                    | sym::start
+                    | sym::custom_mir,
+                ] => {}
+                [name, ..] => {
+                    match BUILTIN_ATTRIBUTE_MAP.get(name) {
+                        // checked below
+                        Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {}
+                        Some(_) => {
+                            // FIXME: differentiate between unstable and internal attributes just like we do with features instead
+                            // of just accepting `rustc_` attributes by name. That should allow trimming the above list, too.
+                            if !name.as_str().starts_with("rustc_") {
+                                span_bug!(
+                                    attr.span,
+                                    "builtin attribute {name:?} not handled by `CheckAttrVisitor`"
+                                )
+                            }
+                        }
+                        None => (),
+                    }
+                }
+                [] => unreachable!(),
             }
 
             let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
@@ -376,6 +428,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
     /// Checks that `#[optimize(..)]` is applied to a function/closure/method,
     /// or to an impl block or module.
+    // FIXME(#128488): this should probably be elevated to an error?
     fn check_optimize(&self, hir_id: HirId, attr: &Attribute, target: Target) {
         match target {
             Target::Fn
@@ -2279,6 +2332,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             self.abort.set(true);
         }
     }
+
+    fn check_coroutine(&self, attr: &Attribute, target: Target) {
+        match target {
+            Target::Closure => return,
+            _ => {
+                self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr.span });
+            }
+        }
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index c4f3c8a0d6c..36dfc40e762 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -636,6 +636,13 @@ pub struct Confusables {
     pub attr_span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(passes_coroutine_on_non_closure)]
+pub struct CoroutineOnNonClosure {
+    #[primary_span]
+    pub span: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(passes_empty_confusables)]
 pub(crate) struct EmptyConfusables {

From 33cb33441de5086e5daa2d951619c279fc394681 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Thu, 1 Aug 2024 10:03:10 +0000
Subject: [PATCH 6/9] Add test for `coroutine` attribute

---
 tests/ui/coroutine/invalid_attr_usage.rs     | 11 +++++++++++
 tests/ui/coroutine/invalid_attr_usage.stderr | 14 ++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 tests/ui/coroutine/invalid_attr_usage.rs
 create mode 100644 tests/ui/coroutine/invalid_attr_usage.stderr

diff --git a/tests/ui/coroutine/invalid_attr_usage.rs b/tests/ui/coroutine/invalid_attr_usage.rs
new file mode 100644
index 00000000000..995a3aa3100
--- /dev/null
+++ b/tests/ui/coroutine/invalid_attr_usage.rs
@@ -0,0 +1,11 @@
+//! The `coroutine` attribute is only allowed on closures.
+
+#![feature(coroutines)]
+
+#[coroutine]
+//~^ ERROR: attribute should be applied to closures
+struct Foo;
+
+#[coroutine]
+//~^ ERROR: attribute should be applied to closures
+fn main() {}
diff --git a/tests/ui/coroutine/invalid_attr_usage.stderr b/tests/ui/coroutine/invalid_attr_usage.stderr
new file mode 100644
index 00000000000..316a0117e5d
--- /dev/null
+++ b/tests/ui/coroutine/invalid_attr_usage.stderr
@@ -0,0 +1,14 @@
+error: attribute should be applied to closures
+  --> $DIR/invalid_attr_usage.rs:5:1
+   |
+LL | #[coroutine]
+   | ^^^^^^^^^^^^
+
+error: attribute should be applied to closures
+  --> $DIR/invalid_attr_usage.rs:9:1
+   |
+LL | #[coroutine]
+   | ^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+

From b564b70d1cb3678108f9045e8fcf2627270d544b Mon Sep 17 00:00:00 2001
From: Chris Denton <chris@chrisdenton.dev>
Date: Sat, 3 Aug 2024 12:26:50 +0000
Subject: [PATCH 7/9] Update run-make/used to use `any_symbol_contains`

---
 tests/run-make/used/rmake.rs | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs
index 56ef5c6b9cc..eb5d026feda 100644
--- a/tests/run-make/used/rmake.rs
+++ b/tests/run-make/used/rmake.rs
@@ -4,12 +4,11 @@
 // It comes from #39987 which implements this RFC for the #[used] attribute:
 // https://rust-lang.github.io/rfcs/2386-used.html
 
-//@ ignore-msvc
-
-use run_make_support::{cmd, rustc};
+use run_make_support::rustc;
+use run_make_support::symbols::any_symbol_contains;
 
 fn main() {
     rustc().opt_level("3").emit("obj").input("used.rs").run();
-
-    cmd("nm").arg("used.o").run().assert_stdout_contains("FOO");
+    assert!(any_symbol_contains("used.o", &["FOO"]));
+    assert!(!any_symbol_contains("used.o", &["BAR"]));
 }

From eb451464a7557f2d8115183a92e6a300d20d75e5 Mon Sep 17 00:00:00 2001
From: Chris Denton <chris@chrisdenton.dev>
Date: Sat, 3 Aug 2024 13:01:34 +0000
Subject: [PATCH 8/9] Remove BAR for run-make/used.rs

---
 tests/run-make/used/rmake.rs | 1 -
 tests/run-make/used/used.rs  | 2 --
 2 files changed, 3 deletions(-)

diff --git a/tests/run-make/used/rmake.rs b/tests/run-make/used/rmake.rs
index eb5d026feda..39f36b2eea8 100644
--- a/tests/run-make/used/rmake.rs
+++ b/tests/run-make/used/rmake.rs
@@ -10,5 +10,4 @@ use run_make_support::symbols::any_symbol_contains;
 fn main() {
     rustc().opt_level("3").emit("obj").input("used.rs").run();
     assert!(any_symbol_contains("used.o", &["FOO"]));
-    assert!(!any_symbol_contains("used.o", &["BAR"]));
 }
diff --git a/tests/run-make/used/used.rs b/tests/run-make/used/used.rs
index dca0a5e1167..133f8121a8e 100644
--- a/tests/run-make/used/used.rs
+++ b/tests/run-make/used/used.rs
@@ -2,5 +2,3 @@
 
 #[used]
 static FOO: u32 = 0;
-
-static BAR: u32 = 0;

From a3a09b488fde8fbe66c2be44491cdb87201d32a2 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume.gomez@huawei.com>
Date: Sat, 3 Aug 2024 00:14:45 +0200
Subject: [PATCH 9/9] Simplify `body` usage in rustdoc

---
 src/librustdoc/html/static/js/main.js | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index e0ea234f9e7..ee771a40595 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -1115,8 +1115,7 @@ function preLoadCss(cssUrl) {
         wrapper.style.left = 0;
         wrapper.style.right = "auto";
         wrapper.style.visibility = "hidden";
-        const body = document.getElementsByTagName("body")[0];
-        body.appendChild(wrapper);
+        document.body.appendChild(wrapper);
         const wrapperPos = wrapper.getBoundingClientRect();
         // offset so that the arrow points at the center of the "(i)"
         const finalPos = pos.left + window.scrollX - wrapperPos.width + 24;
@@ -1235,8 +1234,7 @@ function preLoadCss(cssUrl) {
                 }
                 window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE = false;
             }
-            const body = document.getElementsByTagName("body")[0];
-            body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);
+            document.body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);
             clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);
             window.CURRENT_TOOLTIP_ELEMENT = null;
         }
@@ -1833,7 +1831,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
         let elem = event.target;
         while (!hasClass(elem, "example-wrap")) {
             elem = elem.parentElement;
-            if (elem.tagName === "body" || hasClass(elem, "docblock")) {
+            if (elem === document.body || hasClass(elem, "docblock")) {
                 return null;
             }
         }