From d0165956fe070d12090896aa5546e509045471eb Mon Sep 17 00:00:00 2001
From: surechen <chenshuo17@huawei.com>
Date: Thu, 26 Sep 2024 12:35:44 +0800
Subject: [PATCH 1/9] Add suggestion for removing invalid path separator `::`
 in function definition.

for example: `fn invalid_path_separator::<T>() {}`

fixes: #130791
---
 compiler/rustc_parse/messages.ftl                  |  3 +++
 compiler/rustc_parse/src/errors.rs                 |  8 ++++++++
 compiler/rustc_parse/src/parser/generics.rs        |  7 +++++++
 ...id-path-sep-in-fn-definition-issue-130791.fixed |  7 +++++++
 ...valid-path-sep-in-fn-definition-issue-130791.rs |  7 +++++++
 ...d-path-sep-in-fn-definition-issue-130791.stderr | 14 ++++++++++++++
 6 files changed, 46 insertions(+)
 create mode 100644 tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.fixed
 create mode 100644 tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.rs
 create mode 100644 tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.stderr

diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 6cb851eb8df..e8bff931f83 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -415,6 +415,9 @@ parse_invalid_meta_item = expected unsuffixed literal, found `{$token}`
 
 parse_invalid_offset_of = offset_of expects dot-separated field and variant names
 
+parse_invalid_path_sep_in_fn_definition = invalid path separator in function definition
+    .suggestion = remove invalid path separator
+
 parse_invalid_unicode_escape = invalid unicode character escape
     .label = invalid escape
     .help = unicode escape must {$surrogate ->
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 20bcefd4fe1..86ed38a96c5 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1755,6 +1755,14 @@ pub(crate) struct MissingFnParams {
     pub span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(parse_invalid_path_sep_in_fn_definition)]
+pub(crate) struct InvalidPathSepInFnDefinition {
+    #[primary_span]
+    #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")]
+    pub span: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(parse_missing_trait_in_trait_impl)]
 pub(crate) struct MissingTraitInTraitImpl {
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index b9256daa725..5aebe716b0a 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -269,6 +269,13 @@ impl<'a> Parser<'a> {
     ///                  | ( < lifetimes , typaramseq ( , )? > )
     /// where   typaramseq = ( typaram ) | ( typaram , typaramseq )
     pub(super) fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
+        // invalid path separator `::` in function definition
+        // for example `fn invalid_path_separator::<T>() {}`
+        if self.eat_noexpect(&token::PathSep) {
+            self.dcx()
+                .emit_err(errors::InvalidPathSepInFnDefinition { span: self.prev_token.span });
+        }
+
         let span_lo = self.token.span;
         let (params, span) = if self.eat_lt() {
             let params = self.parse_generic_params()?;
diff --git a/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.fixed b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.fixed
new file mode 100644
index 00000000000..2c6fddccb73
--- /dev/null
+++ b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.fixed
@@ -0,0 +1,7 @@
+//@ run-rustfix
+
+#[allow(dead_code)]
+fn invalid_path_separator<T>() {}
+//~^ ERROR invalid path separator in function definition
+
+fn main() {}
diff --git a/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.rs b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.rs
new file mode 100644
index 00000000000..5f690615043
--- /dev/null
+++ b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.rs
@@ -0,0 +1,7 @@
+//@ run-rustfix
+
+#[allow(dead_code)]
+fn invalid_path_separator::<T>() {}
+//~^ ERROR invalid path separator in function definition
+
+fn main() {}
diff --git a/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.stderr b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.stderr
new file mode 100644
index 00000000000..3ad05050da0
--- /dev/null
+++ b/tests/ui/parser/issues/invalid-path-sep-in-fn-definition-issue-130791.stderr
@@ -0,0 +1,14 @@
+error: invalid path separator in function definition
+  --> $DIR/invalid-path-sep-in-fn-definition-issue-130791.rs:4:26
+   |
+LL | fn invalid_path_separator::<T>() {}
+   |                          ^^
+   |
+help: remove invalid path separator
+   |
+LL - fn invalid_path_separator::<T>() {}
+LL + fn invalid_path_separator<T>() {}
+   |
+
+error: aborting due to 1 previous error
+

From 9a523001e3c245f8f547720a176005cf5bdee4f0 Mon Sep 17 00:00:00 2001
From: Jubilee Young <workingjubilee@gmail.com>
Date: Thu, 26 Sep 2024 10:36:59 -0700
Subject: [PATCH 2/9] library: Stabilize `const_intrinsic_forget`

This is an implicit requirement of stabilizing `const_ptr_write`.

Const-stabilizes the internal `core::intrinsics`:
- `forget`
---
 library/core/src/intrinsics.rs | 2 +-
 library/core/src/lib.rs        | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index d7a2f1909ca..3be07654432 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1084,7 +1084,7 @@ extern "rust-intrinsic" {
     /// it does not require an `unsafe` block.
     /// Therefore, implementations must not require the user to uphold
     /// any safety invariants.
-    #[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
+    #[rustc_const_stable(feature = "const_intrinsic_forget", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_safe_intrinsic]
     #[rustc_nounwind]
     pub fn forget<T: ?Sized>(_: T);
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index f68f19ec6a4..3eacf7261a5 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -124,7 +124,6 @@
 #![feature(const_hash)]
 #![feature(const_heap)]
 #![feature(const_index_range_slice_index)]
-#![feature(const_intrinsic_forget)]
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
 #![feature(const_likely)]

From ddc367ded70b3145ffa92216bb4aaf178233c4ee Mon Sep 17 00:00:00 2001
From: Jubilee Young <workingjubilee@gmail.com>
Date: Thu, 26 Sep 2024 09:30:17 -0700
Subject: [PATCH 3/9] library: Stabilize `const_ptr_write`

Const-stabilizes:
- `write`
- `write_bytes`
- `write_unaligned`

In the following paths:
- `core::ptr`
- `core::ptr::NonNull`
- pointer `<*mut T>`

Const-stabilizes the internal `core::intrinsics`:
- `write_bytes`
- `write_via_move`
---
 library/alloc/src/lib.rs                       | 1 -
 library/alloc/tests/lib.rs                     | 1 -
 library/core/src/intrinsics.rs                 | 6 +++---
 library/core/src/lib.rs                        | 1 -
 library/core/src/ptr/mod.rs                    | 5 +++--
 library/core/src/ptr/mut_ptr.rs                | 6 +++---
 library/core/src/ptr/non_null.rs               | 6 +++---
 library/core/tests/lib.rs                      | 1 -
 tests/ui/consts/load-preserves-partial-init.rs | 1 -
 9 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index c60c0743c7e..1d7b7a03454 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -173,7 +173,6 @@
 #![feature(allow_internal_unstable)]
 #![feature(cfg_sanitize)]
 #![feature(const_precise_live_drops)]
-#![feature(const_ptr_write)]
 #![feature(const_try)]
 #![feature(decl_macro)]
 #![feature(dropck_eyepatch)]
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index f43143c6cef..4d146f1f5fd 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -7,7 +7,6 @@
 #![feature(const_cow_is_borrowed)]
 #![feature(const_heap)]
 #![cfg_attr(bootstrap, feature(const_mut_refs))]
-#![feature(const_ptr_write)]
 #![feature(const_try)]
 #![feature(core_intrinsics)]
 #![feature(extract_if)]
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 3be07654432..f61b675ac4e 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2635,7 +2635,7 @@ extern "rust-intrinsic" {
     /// This intrinsic can *only* be called where the pointer is a local without
     /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so
     /// that it trivially obeys runtime-MIR rules about derefs in operands.
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+    #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
     #[rustc_nounwind]
     pub fn write_via_move<T>(ptr: *mut T, value: T);
 
@@ -3472,13 +3472,13 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 #[doc(alias = "memset")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_allowed_through_unstable_modules]
-#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
 #[inline(always)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 #[rustc_diagnostic_item = "ptr_write_bytes"]
 pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
     extern "rust-intrinsic" {
-        #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+        #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
         #[rustc_nounwind]
         fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
     }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 3eacf7261a5..97df6ccfa5e 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -137,7 +137,6 @@
 #![feature(const_pointer_is_aligned)]
 #![feature(const_ptr_is_null)]
 #![feature(const_ptr_sub_ptr)]
-#![feature(const_ptr_write)]
 #![feature(const_raw_ptr_comparison)]
 #![feature(const_replace)]
 #![feature(const_size_of_val)]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 67f1b0cd16d..6f076caf533 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1611,7 +1611,7 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
 #[rustc_diagnostic_item = "ptr_write"]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn write<T>(dst: *mut T, src: T) {
@@ -1719,7 +1719,8 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
 /// ```
 #[inline]
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
-#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_refs_to_cell))]
+#[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
 #[rustc_diagnostic_item = "ptr_write_unaligned"]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index e458bb4642f..ced6cb7d520 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1449,7 +1449,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// [`ptr::write`]: crate::ptr::write()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+    #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn write(self, val: T)
@@ -1468,7 +1468,7 @@ impl<T: ?Sized> *mut T {
     /// [`ptr::write_bytes`]: crate::ptr::write_bytes()
     #[doc(alias = "memset")]
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+    #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn write_bytes(self, val: u8, count: usize)
@@ -1509,7 +1509,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// [`ptr::write_unaligned`]: crate::ptr::write_unaligned()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+    #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn write_unaligned(self, val: T)
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 6c5834a1ece..dc1a7c6220e 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -1013,7 +1013,7 @@ impl<T: ?Sized> NonNull<T> {
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     #[stable(feature = "non_null_convenience", since = "1.80.0")]
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+    #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
     pub const unsafe fn write(self, val: T)
     where
         T: Sized,
@@ -1032,7 +1032,7 @@ impl<T: ?Sized> NonNull<T> {
     #[doc(alias = "memset")]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     #[stable(feature = "non_null_convenience", since = "1.80.0")]
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+    #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
     pub const unsafe fn write_bytes(self, val: u8, count: usize)
     where
         T: Sized,
@@ -1073,7 +1073,7 @@ impl<T: ?Sized> NonNull<T> {
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     #[stable(feature = "non_null_convenience", since = "1.80.0")]
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+    #[rustc_const_stable(feature = "const_ptr_write", since = "CURRENT_RUSTC_VERSION")]
     pub const unsafe fn write_unaligned(self, val: T)
     where
         T: Sized,
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 8ee98de2a7b..5ec1b311a50 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -28,7 +28,6 @@
 #![feature(const_option_ext)]
 #![feature(const_pin)]
 #![feature(const_pointer_is_aligned)]
-#![feature(const_ptr_write)]
 #![feature(const_three_way_compare)]
 #![feature(const_trait_impl)]
 #![feature(core_intrinsics)]
diff --git a/tests/ui/consts/load-preserves-partial-init.rs b/tests/ui/consts/load-preserves-partial-init.rs
index d97e9cb3d9d..2a8adbd5e16 100644
--- a/tests/ui/consts/load-preserves-partial-init.rs
+++ b/tests/ui/consts/load-preserves-partial-init.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 
-#![feature(const_ptr_write)]
 // issue: https://github.com/rust-lang/rust/issues/69488
 // Loads of partially-initialized data could produce completely-uninitialized results.
 // Test to make sure that we no longer do such a "deinitializing" load.

From 187c8b0ce90eb3a446aa6bd838d6984764479a5a Mon Sep 17 00:00:00 2001
From: Jubilee Young <workingjubilee@gmail.com>
Date: Thu, 26 Sep 2024 11:49:53 -0700
Subject: [PATCH 4/9] library: Stabilize `const_replace`

Depends on stabilizing `const_ptr_write`.

Const-stabilizes:
- `core::mem::replace`
- `core::ptr::replace`
---
 library/core/src/lib.rs     | 1 -
 library/core/src/mem/mod.rs | 3 ++-
 library/core/src/ptr/mod.rs | 3 ++-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 97df6ccfa5e..d407efa069b 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -138,7 +138,6 @@
 #![feature(const_ptr_is_null)]
 #![feature(const_ptr_sub_ptr)]
 #![feature(const_raw_ptr_comparison)]
-#![feature(const_replace)]
 #![feature(const_size_of_val)]
 #![feature(const_size_of_val_raw)]
 #![feature(const_strict_overflow_ops)]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 414262fcf5a..9bf2aa594c0 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -857,7 +857,8 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_use = "if you don't need the old value, you can just assign the new value directly"]
-#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
+#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))]
+#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")]
 pub const fn replace<T>(dest: &mut T, src: T) -> T {
     // It may be tempting to use `swap` to avoid `unsafe` here. Don't!
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 6f076caf533..6b074492924 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1263,7 +1263,8 @@ const unsafe fn swap_nonoverlapping_simple_untyped<T>(x: *mut T, y: *mut T, coun
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
+#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))]
+#[rustc_const_stable(feature = "const_replace", since = "CURRENT_RUSTC_VERSION")]
 #[rustc_diagnostic_item = "ptr_replace"]
 pub const unsafe fn replace<T>(dst: *mut T, src: T) -> T {
     // SAFETY: the caller must guarantee that `dst` is valid to be

From e5906e1591c0aa787003f89e3f3c9236c22f4832 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Sat, 12 Oct 2024 10:59:12 +0200
Subject: [PATCH 5/9] yeet some clones

---
 compiler/rustc_borrowck/src/nll.rs                      | 2 +-
 compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index f3207c26bfc..3674053409b 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -165,7 +165,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
         universe_causes,
         type_tests,
         liveness_constraints,
-        elements.clone(),
+        elements,
     );
 
     // If requested: dump NLL facts, and run legacy polonius analysis.
diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
index fab1906eecd..e3878d90e41 100644
--- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
@@ -312,7 +312,7 @@ pub(crate) fn expand_deriving_smart_ptr(
     impl_generics.params.insert(pointee_param_idx + 1, extra_param);
 
     // Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`.
-    let gen_args = vec![GenericArg::Type(alt_self_type.clone())];
+    let gen_args = vec![GenericArg::Type(alt_self_type)];
     add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone());
     add_impl_block(impl_generics.clone(), sym::CoerceUnsized, gen_args);
 }

From 9f91c5099fb7261cf8c85cc638d2692a317060ec Mon Sep 17 00:00:00 2001
From: joboet <jonasboettiger@icloud.com>
Date: Sat, 12 Oct 2024 13:01:36 +0200
Subject: [PATCH 6/9] std: fix stdout-before-main

Fixes #130210.

Since #124881, `ReentrantLock` uses `ThreadId` to identify threads. This has the unfortunate consequence of breaking uses of `Stdout` before main: Locking the `ReentrantLock` that synchronizes the output will initialize the thread ID before the handle for the main thread is set in `rt::init`. But since that would overwrite the current thread ID, `thread::set_current` triggers an abort.

This PR fixes the problem by using the already initialized thread ID for constructing the main thread handle and allowing `set_current` calls that do not change the thread's ID.
---
 library/std/src/rt.rs                         | 21 +++++++++++++---
 library/std/src/thread/current.rs             | 20 +++++++++-------
 library/std/src/thread/mod.rs                 | 24 ++++++++++---------
 tests/ui/runtime/stdout-before-main.rs        | 24 +++++++++++++++++++
 .../ui/runtime/stdout-before-main.run.stdout  |  1 +
 5 files changed, 67 insertions(+), 23 deletions(-)
 create mode 100644 tests/ui/runtime/stdout-before-main.rs
 create mode 100644 tests/ui/runtime/stdout-before-main.run.stdout

diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index 0a841f07e3b..80e7c3c026b 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -102,9 +102,24 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
         sys::init(argc, argv, sigpipe)
     };
 
-    // Set up the current thread to give it the right name.
-    let thread = Thread::new_main();
-    thread::set_current(thread);
+    // Set up the current thread handle to give it the right name.
+    //
+    // When code running before main uses `ReentrantLock` (for example by
+    // using `println!`), the thread ID can become initialized before we
+    // create this handle. Since `set_current` fails when the ID of the
+    // handle does not match the current ID, we should attempt to use the
+    // current thread ID here instead of unconditionally creating a new
+    // one. Also see #130210.
+    let thread = Thread::new_main(thread::current_id());
+    if let Err(_thread) = thread::set_current(thread) {
+        // `thread::current` will create a new handle if none has been set yet.
+        // Thus, if someone uses it before main, this call will fail. That's a
+        // bad idea though, as we then cannot set the main thread name here.
+        //
+        // FIXME: detect the main thread in `thread::current` and use the
+        //        correct name there.
+        rtabort!("code running before main must not use thread::current");
+    }
 }
 
 /// Clean up the thread-local runtime state. This *should* be run after all other
diff --git a/library/std/src/thread/current.rs b/library/std/src/thread/current.rs
index b38149a0da7..e6eb90c4c30 100644
--- a/library/std/src/thread/current.rs
+++ b/library/std/src/thread/current.rs
@@ -110,22 +110,24 @@ mod id {
     }
 }
 
-/// Sets the thread handle for the current thread.
-///
-/// Aborts if the handle or the ID has been set already.
-pub(crate) fn set_current(thread: Thread) {
-    if CURRENT.get() != NONE || id::get().is_some() {
-        // Using `panic` here can add ~3kB to the binary size. We have complete
-        // control over where this is called, so just abort if there is a bug.
-        rtabort!("thread::set_current should only be called once per thread");
+/// Tries to set the thread handle for the current thread. Fails if a handle was
+/// already set or if the thread ID of `thread` would change an already-set ID.
+pub(crate) fn set_current(thread: Thread) -> Result<(), Thread> {
+    if CURRENT.get() != NONE {
+        return Err(thread);
     }
 
-    id::set(thread.id());
+    match id::get() {
+        Some(id) if id == thread.id() => {}
+        None => id::set(thread.id()),
+        _ => return Err(thread),
+    }
 
     // Make sure that `crate::rt::thread_cleanup` will be run, which will
     // call `drop_current`.
     crate::sys::thread_local::guard::enable();
     CURRENT.set(thread.into_raw().cast_mut());
+    Ok(())
 }
 
 /// Gets the id of the thread that invokes it.
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index d1d4eabb9bd..39753888509 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -519,9 +519,14 @@ impl Builder {
 
         let f = MaybeDangling::new(f);
         let main = move || {
-            // Immediately store the thread handle to avoid setting it or its ID
-            // twice, which would cause an abort.
-            set_current(their_thread.clone());
+            if let Err(_thread) = set_current(their_thread.clone()) {
+                // Both the current thread handle and the ID should not be
+                // initialized yet. Since only the C runtime and some of our
+                // platform code run before this, this point shouldn't be
+                // reachable. Use an abort to save binary size (see #123356).
+                rtabort!("something here is badly broken!");
+            }
+
             if let Some(name) = their_thread.cname() {
                 imp::Thread::set_name(name);
             }
@@ -1159,9 +1164,6 @@ pub fn park_timeout(dur: Duration) {
 pub struct ThreadId(NonZero<u64>);
 
 impl ThreadId {
-    // DO NOT rely on this value.
-    const MAIN_THREAD: ThreadId = ThreadId(unsafe { NonZero::new_unchecked(1) });
-
     // Generate a new unique thread ID.
     pub(crate) fn new() -> ThreadId {
         #[cold]
@@ -1173,7 +1175,7 @@ impl ThreadId {
             if #[cfg(target_has_atomic = "64")] {
                 use crate::sync::atomic::AtomicU64;
 
-                static COUNTER: AtomicU64 = AtomicU64::new(1);
+                static COUNTER: AtomicU64 = AtomicU64::new(0);
 
                 let mut last = COUNTER.load(Ordering::Relaxed);
                 loop {
@@ -1189,7 +1191,7 @@ impl ThreadId {
             } else {
                 use crate::sync::{Mutex, PoisonError};
 
-                static COUNTER: Mutex<u64> = Mutex::new(1);
+                static COUNTER: Mutex<u64> = Mutex::new(0);
 
                 let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner);
                 let Some(id) = counter.checked_add(1) else {
@@ -1326,9 +1328,9 @@ impl Thread {
         Self::new_inner(id, ThreadName::Unnamed)
     }
 
-    // Used in runtime to construct main thread
-    pub(crate) fn new_main() -> Thread {
-        Self::new_inner(ThreadId::MAIN_THREAD, ThreadName::Main)
+    /// Constructs the thread handle for the main thread.
+    pub(crate) fn new_main(id: ThreadId) -> Thread {
+        Self::new_inner(id, ThreadName::Main)
     }
 
     fn new_inner(id: ThreadId, name: ThreadName) -> Thread {
diff --git a/tests/ui/runtime/stdout-before-main.rs b/tests/ui/runtime/stdout-before-main.rs
new file mode 100644
index 00000000000..26c734d3e9e
--- /dev/null
+++ b/tests/ui/runtime/stdout-before-main.rs
@@ -0,0 +1,24 @@
+//@ run-pass
+//@ check-run-results
+//@ only-gnu
+//@ only-linux
+//
+// Regression test for #130210.
+// .init_array doesn't work everywhere, so we limit the test to just GNU/Linux.
+
+use std::ffi::c_int;
+use std::thread;
+
+#[used]
+#[link_section = ".init_array"]
+static INIT: extern "C" fn(c_int, *const *const u8, *const *const u8) = {
+    extern "C" fn init(_argc: c_int, _argv: *const *const u8, _envp: *const *const u8) {
+        print!("Hello from before ");
+    }
+
+    init
+};
+
+fn main() {
+    println!("{}!", thread::current().name().unwrap());
+}
diff --git a/tests/ui/runtime/stdout-before-main.run.stdout b/tests/ui/runtime/stdout-before-main.run.stdout
new file mode 100644
index 00000000000..d7a3a4389ec
--- /dev/null
+++ b/tests/ui/runtime/stdout-before-main.run.stdout
@@ -0,0 +1 @@
+Hello from before main!

From 52090f071524263fbe48be2e9eec51635f573f64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?=
 <39484203+jieyouxu@users.noreply.github.com>
Date: Sat, 12 Oct 2024 19:12:19 +0800
Subject: [PATCH 7/9] Take a display name for `tool_check_step!`

---
 src/bootstrap/src/core/build_steps/check.rs | 39 +++++++++++++++------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 7671fc7e013..f419bebdc12 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -398,7 +398,14 @@ impl Step for RustAnalyzer {
 }
 
 macro_rules! tool_check_step {
-    ($name:ident, $path:literal, $($alias:literal, )* $source_type:path $(, $default:literal )?) => {
+    (
+        $name:ident,
+        $display_name:literal,
+        $path:literal,
+        $($alias:literal, )*
+        $source_type:path
+        $(, $default:literal )?
+    ) => {
         #[derive(Debug, Clone, PartialEq, Eq, Hash)]
         pub struct $name {
             pub target: TargetSelection,
@@ -441,7 +448,7 @@ macro_rules! tool_check_step {
                     cargo.arg("--all-targets");
                 }
 
-                let _guard = builder.msg_check(&concat!(stringify!($name), " artifacts").to_lowercase(), target);
+                let _guard = builder.msg_check(&format!("{} artifacts", $display_name), target);
                 run_cargo(
                     builder,
                     cargo,
@@ -468,20 +475,30 @@ macro_rules! tool_check_step {
     };
 }
 
-tool_check_step!(Rustdoc, "src/tools/rustdoc", "src/librustdoc", SourceType::InTree);
+tool_check_step!(Rustdoc, "rustdoc", "src/tools/rustdoc", "src/librustdoc", SourceType::InTree);
 // Clippy, miri and Rustfmt are hybrids. They are external tools, but use a git subtree instead
 // of a submodule. Since the SourceType only drives the deny-warnings
 // behavior, treat it as in-tree so that any new warnings in clippy will be
 // rejected.
-tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
-tool_check_step!(Miri, "src/tools/miri", SourceType::InTree);
-tool_check_step!(CargoMiri, "src/tools/miri/cargo-miri", SourceType::InTree);
-tool_check_step!(Rls, "src/tools/rls", SourceType::InTree);
-tool_check_step!(Rustfmt, "src/tools/rustfmt", SourceType::InTree);
-tool_check_step!(MiroptTestTools, "src/tools/miropt-test-tools", SourceType::InTree);
-tool_check_step!(TestFloatParse, "src/etc/test-float-parse", SourceType::InTree);
+tool_check_step!(Clippy, "clippy", "src/tools/clippy", SourceType::InTree);
+tool_check_step!(Miri, "miri", "src/tools/miri", SourceType::InTree);
+tool_check_step!(CargoMiri, "cargo-miri", "src/tools/miri/cargo-miri", SourceType::InTree);
+tool_check_step!(Rls, "rls", "src/tools/rls", SourceType::InTree);
+tool_check_step!(Rustfmt, "rustfmt", "src/tools/rustfmt", SourceType::InTree);
+tool_check_step!(
+    MiroptTestTools,
+    "miropt-test-tools",
+    "src/tools/miropt-test-tools",
+    SourceType::InTree
+);
+tool_check_step!(
+    TestFloatParse,
+    "test-float-parse",
+    "src/etc/test-float-parse",
+    SourceType::InTree
+);
 
-tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree, false);
+tool_check_step!(Bootstrap, "bootstrap", "src/bootstrap", SourceType::InTree, false);
 
 /// Cargo's output path for the standard library in a given stage, compiled
 /// by a particular compiler for the specified target.

From 89623439f73d5a744ba5c8a911274b3802d79b86 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sat, 12 Oct 2024 13:13:50 +0200
Subject: [PATCH 8/9] mark InterpResult as must_use

---
 compiler/rustc_middle/src/mir/interpret/error.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 431043b0431..fcb87e19435 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -754,6 +754,7 @@ impl Drop for Guard {
 ///
 /// We also make things panic if this type is ever implicitly dropped.
 #[derive(Debug)]
+#[must_use]
 pub struct InterpResult_<'tcx, T> {
     res: Result<T, InterpErrorInfo<'tcx>>,
     guard: Guard,

From 1efffe720d40e0c88efe820da01f99d031a4c4d1 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk@dianqk.net>
Date: Sat, 12 Oct 2024 22:36:14 +0800
Subject: [PATCH 9/9] `LLVMConstInt` only allows integer types

---
 compiler/rustc_codegen_llvm/src/common.rs | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index 4ca19ab2f12..0ced37b53a8 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -5,6 +5,7 @@ use rustc_abi as abi;
 use rustc_abi::Primitive::Pointer;
 use rustc_abi::{AddressSpace, HasDataLayout};
 use rustc_ast::Mutability;
+use rustc_codegen_ssa::common::TypeKind;
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
@@ -146,6 +147,10 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     }
 
     fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
+        debug_assert!(
+            self.type_kind(t) == TypeKind::Integer,
+            "only allows integer types in const_int"
+        );
         unsafe { llvm::LLVMConstInt(t, i as u64, True) }
     }
 
@@ -176,10 +181,18 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     }
 
     fn const_uint(&self, t: &'ll Type, i: u64) -> &'ll Value {
+        debug_assert!(
+            self.type_kind(t) == TypeKind::Integer,
+            "only allows integer types in const_uint"
+        );
         unsafe { llvm::LLVMConstInt(t, i, False) }
     }
 
     fn const_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value {
+        debug_assert!(
+            self.type_kind(t) == TypeKind::Integer,
+            "only allows integer types in const_uint_big"
+        );
         unsafe {
             let words = [u as u64, (u >> 64) as u64];
             llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())