From 65bd61d2fbef50d28caed626ce601a908d5be77f Mon Sep 17 00:00:00 2001
From: Mads Marquart <mads@marquart.dk>
Date: Wed, 12 Mar 2025 09:47:11 +0100
Subject: [PATCH 01/11] Fix armv7-sony-vita-newlibeabihf LLVM target triple

It was previously normalized by LLVM to `thumbv7a-vita-unknown-eabihf`,
which is probably wrong, as Vita is the OS.
---
 .../src/spec/targets/armv7_sony_vita_newlibeabihf.rs            | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
index 5d292bbf8adf0..6a83835059eee 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
@@ -15,7 +15,7 @@ pub(crate) fn target() -> Target {
     );
 
     Target {
-        llvm_target: "thumbv7a-vita-eabihf".into(),
+        llvm_target: "thumbv7a-sony-vita-eabihf".into(),
         metadata: TargetMetadata {
             description: Some(
                 "Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)".into(),

From 41fdd280ff1089d1618487d59ed49f83160d2513 Mon Sep 17 00:00:00 2001
From: jyn <github@jyn.dev>
Date: Sat, 22 Mar 2025 16:09:37 -0400
Subject: [PATCH 02/11] rustc_resolve: Test the order that preludes are
 resolved

---
 tests/ui/resolve/auxiliary/macro_helpers.rs | 16 ++++
 tests/ui/resolve/prelude-order.rs           | 89 +++++++++++++++++++++
 tests/ui/resolve/prelude-order.stderr       | 47 +++++++++++
 3 files changed, 152 insertions(+)
 create mode 100644 tests/ui/resolve/auxiliary/macro_helpers.rs
 create mode 100644 tests/ui/resolve/prelude-order.rs
 create mode 100644 tests/ui/resolve/prelude-order.stderr

diff --git a/tests/ui/resolve/auxiliary/macro_helpers.rs b/tests/ui/resolve/auxiliary/macro_helpers.rs
new file mode 100644
index 0000000000000..43aa336457de7
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/macro_helpers.rs
@@ -0,0 +1,16 @@
+/* macro namespace. */
+
+extern crate proc_macro;
+use proc_macro::*;
+use std::str::FromStr;
+
+const ERROR: &str = "fn helper() { \"helper\" }";
+// https://doc.rust-lang.org/nightly/std/prelude/v1/index.html#attributes
+// NOTE: all the bang macros in std are currently unstable.
+#[proc_macro_attribute] pub fn test       // lang.
+    (_: TokenStream, _: TokenStream) -> TokenStream {
+        TokenStream::from_str("fn test_macro() { \"\" }").unwrap() }
+// https://doc.rust-lang.org/nightly/reference/attributes.html#built-in-attributes-index
+#[proc_macro_attribute] pub fn global_allocator // lang.
+    (_: TokenStream, _: TokenStream) -> TokenStream {
+        TokenStream::from_str("fn global_allocator_macro() { \"\" }").unwrap() }
diff --git a/tests/ui/resolve/prelude-order.rs b/tests/ui/resolve/prelude-order.rs
new file mode 100644
index 0000000000000..a3f194270d483
--- /dev/null
+++ b/tests/ui/resolve/prelude-order.rs
@@ -0,0 +1,89 @@
+//@ proc-macro:macro_helpers.rs
+//@ compile-flags: --crate-type=lib
+
+/* There are 5 preludes and 3 namespaces. Test the order in which they are resolved.
+ * See https://doc.rust-lang.org/nightly/reference/names/preludes.html.
+ *
+ * Macros cannot be in the type or value namespace.
+ * Tools and extern crates cannot be in the macro or value namespace.
+ *
+ * Test the following truth tables:
+
+Type:
+| ...... |  tool  | extern | macro  | lang   | libs |
+|   tool |    N/A |                   mirror
+| extern | extern |    N/A |             universe
+|  macro |    N/A |    N/A |    N/A |
+|   lang |   tool | extern |    N/A |   N/A  |
+|   libs |   tool | extern |    N/A |   X    |  N/A |
+
+Macro:
+| ...... |  tool  | extern | macro  | lang   | libs |
+|   tool |    N/A |                   mirror
+| extern |    N/A |    N/A |             universe
+|  macro |    N/A |    N/A |    N/A |
+|   lang |    N/A |    N/A |  macro |   N/A  |
+|   libs |    N/A |    N/A |  macro |   X    | N/A  |
+
+Value: N/A. Only libs has items in the value namespace.
+
+† ambiguous
+X don't care (controlled namespace with no overlap)
+
+* Types are tested with `#[name::inner]`. Macros are tested with `#[name]`.
+* WARNING: I have found in testing that attribute macros give ambiguity errors in some contexts
+* instead of choosing a prelude. Have not been able to replicate.
+*
+* There should be 7 total tests.
+* See `rustc_resolve::ident::visit_scopes` for more information,
+* and for a definition of "controlled namespace".
+*/
+
+#![feature(register_tool)]
+
+/* tool prelude */
+#![register_tool(type_ns)] // extern prelude. type.
+#![register_tool(i8)]      // lang   prelude. type.
+#![register_tool(Sync)]    // libs   prelude. type.
+
+/* extern prelude */
+extern crate macro_helpers as type_ns; // tool prelude. type.
+extern crate macro_helpers as usize;   // lang prelude. type.
+extern crate macro_helpers as Option;  // libs prelude. type.
+
+/* macro_use prelude */
+#[macro_use]
+extern crate macro_helpers as _;
+
+/* lang and libs implicitly in scope */
+
+// tool/extern -> extern
+#[type_ns::inner] //~ ERROR could not find `inner` in `type_ns`
+fn t1() {}
+
+// tool/lang -> tool
+#[i8::inner] // ok
+fn t2() {}
+
+// tool/libs -> tool
+#[Sync::not_real] // ok
+fn t3() {}
+
+// extern/lang -> extern
+#[usize::inner] //~ ERROR could not find `inner` in `usize`
+fn e1() {} // NOTE: testing with `-> usize` isn't valid, crates aren't considered in that scope
+           // (unless they have generic arguments, for some reason.)
+
+// extern/libs -> extern
+// https://github.com/rust-lang/rust/issues/139095
+fn e2() -> Option<i32> { None } //~ ERROR: expected type, found crate
+
+// macro/libs -> macro
+#[test] //~ ERROR mismatched types
+fn m1() {}
+
+// macro/lang -> macro
+#[global_allocator] //~ ERROR mismatched types
+fn m2() {}
+
+// lang/libs: no items that currently overlap, in either macro or type ns.
diff --git a/tests/ui/resolve/prelude-order.stderr b/tests/ui/resolve/prelude-order.stderr
new file mode 100644
index 0000000000000..1b9cc94285aa5
--- /dev/null
+++ b/tests/ui/resolve/prelude-order.stderr
@@ -0,0 +1,47 @@
+error[E0433]: failed to resolve: could not find `inner` in `type_ns`
+  --> $DIR/prelude-order.rs:61:12
+   |
+LL | #[type_ns::inner]
+   |            ^^^^^ could not find `inner` in `type_ns`
+
+error[E0433]: failed to resolve: could not find `inner` in `usize`
+  --> $DIR/prelude-order.rs:73:10
+   |
+LL | #[usize::inner]
+   |          ^^^^^ could not find `inner` in `usize`
+
+error[E0573]: expected type, found crate `Option`
+  --> $DIR/prelude-order.rs:79:12
+   |
+LL | fn e2() -> Option<i32> { None }
+   |            ^^^^^^^^^^^ not a type
+   |
+help: consider importing this enum instead
+   |
+LL + use std::option::Option;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/prelude-order.rs:82:1
+   |
+LL | #[test]
+   | ^^^^^^^- help: try adding a return type: `-> &'static str`
+   | |
+   | expected `()`, found `&str`
+   |
+   = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/prelude-order.rs:86:1
+   |
+LL | #[global_allocator]
+   | ^^^^^^^^^^^^^^^^^^^- help: try adding a return type: `-> &'static str`
+   | |
+   | expected `()`, found `&str`
+   |
+   = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0433, E0573.
+For more information about an error, try `rustc --explain E0308`.

From f3cbc3992e1428e92c608410614c3e7b7a64b815 Mon Sep 17 00:00:00 2001
From: mejrs <59372212+mejrs@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:13:47 +0200
Subject: [PATCH 03/11] Remove duplicate c-variadic.md

---
 .../src/library-features/c-variadic.md        | 26 -------------------
 src/tools/tidy/src/unstable_book.rs           | 12 ++++-----
 2 files changed, 5 insertions(+), 33 deletions(-)
 delete mode 100644 src/doc/unstable-book/src/library-features/c-variadic.md

diff --git a/src/doc/unstable-book/src/library-features/c-variadic.md b/src/doc/unstable-book/src/library-features/c-variadic.md
deleted file mode 100644
index 77762116e6b1c..0000000000000
--- a/src/doc/unstable-book/src/library-features/c-variadic.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# `c_variadic`
-
-The tracking issue for this feature is: [#44930]
-
-[#44930]: https://github.com/rust-lang/rust/issues/44930
-
-------------------------
-
-The `c_variadic` library feature exposes the `VaList` structure,
-Rust's analogue of C's `va_list` type.
-
-## Examples
-
-```rust
-#![feature(c_variadic)]
-
-use std::ffi::VaList;
-
-pub unsafe extern "C" fn vadd(n: usize, mut args: VaList) -> usize {
-    let mut sum = 0;
-    for _ in 0..n {
-        sum += args.arg::<usize>();
-    }
-    sum
-}
-```
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index 8be25b98df0df..d19de081807d2 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -93,14 +93,12 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
     // Check for Unstable Book sections that don't have a corresponding unstable feature
     for feature_name in &unstable_book_lib_features_section_file_names - &unstable_lib_feature_names
     {
-        if !unstable_lang_feature_names.contains(&feature_name) {
-            tidy_error!(
-                bad,
-                "The Unstable Book has a 'library feature' section '{}' which doesn't \
+        tidy_error!(
+            bad,
+            "The Unstable Book has a 'library feature' section '{}' which doesn't \
                          correspond to an unstable library feature",
-                feature_name
-            );
-        }
+            feature_name
+        );
     }
 
     // Check for Unstable Book sections that don't have a corresponding unstable feature.

From 14e4f9f245c615cd379397908abc52c795b65d04 Mon Sep 17 00:00:00 2001
From: mejrs <59372212+mejrs@users.noreply.github.com>
Date: Sun, 30 Mar 2025 22:19:18 +0200
Subject: [PATCH 04/11] Suggest switching underscores for dashes

---
 src/tools/tidy/src/unstable_book.rs | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index d19de081807d2..a2453a6c96057 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -72,6 +72,19 @@ fn collect_unstable_book_lib_features_section_file_names(base_src_path: &Path) -
     collect_unstable_book_section_file_names(&unstable_book_lib_features_path(base_src_path))
 }
 
+/// Would switching underscores for dashes work?
+fn maybe_suggest_dashes(names: &BTreeSet<String>, feature_name: &str, bad: &mut bool) {
+    let with_dashes = feature_name.replace('_', "-");
+    if names.contains(&with_dashes) {
+        tidy_error!(
+            bad,
+            "the file `{}.md` contains underscores; use dashes instead: `{}.md`",
+            feature_name,
+            with_dashes,
+        );
+    }
+}
+
 pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
     let lang_features = features.lang;
     let lib_features = features
@@ -99,6 +112,7 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
                          correspond to an unstable library feature",
             feature_name
         );
+        maybe_suggest_dashes(&unstable_lib_feature_names, &feature_name, bad);
     }
 
     // Check for Unstable Book sections that don't have a corresponding unstable feature.
@@ -110,7 +124,8 @@ pub fn check(path: &Path, features: CollectedFeatures, bad: &mut bool) {
             "The Unstable Book has a 'language feature' section '{}' which doesn't \
                      correspond to an unstable language feature",
             feature_name
-        )
+        );
+        maybe_suggest_dashes(&unstable_lang_feature_names, &feature_name, bad);
     }
 
     // List unstable features that don't have Unstable Book sections.

From 4e99dca8c35b37fcf097e7bd3c2b00abb7a64dfb Mon Sep 17 00:00:00 2001
From: Mara Bos <m-ou.se@m-ou.se>
Date: Mon, 31 Mar 2025 15:37:16 +0200
Subject: [PATCH 05/11] Remove fragile equal-pointers-unequal/*/print3.rs
 tests.

---
 .../equal-pointers-unequal/as-cast/print3.rs  | 23 -----------------
 .../exposed-provenance/print3.rs              | 25 -------------------
 .../strict-provenance/print3.rs               | 25 -------------------
 3 files changed, 73 deletions(-)
 delete mode 100644 tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
 delete mode 100644 tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
 delete mode 100644 tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs

diff --git a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs b/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
deleted file mode 100644
index eda83e999a528..0000000000000
--- a/tests/ui/codegen/equal-pointers-unequal/as-cast/print3.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-//@ known-bug: #107975
-//@ compile-flags: -Copt-level=2
-//@ run-pass
-
-// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
-
-fn main() {
-    let a = {
-        let v = 0;
-        &v as *const _ as usize
-    };
-    let b = {
-        let v = 0;
-        &v as *const _ as usize
-    };
-
-    assert_ne!(a, b);
-    assert_ne!(a, b);
-    let c = a;
-    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
-    println!("{a} {b}");
-    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
-}
diff --git a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
deleted file mode 100644
index c7f46318aaef7..0000000000000
--- a/tests/ui/codegen/equal-pointers-unequal/exposed-provenance/print3.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: #107975
-//@ compile-flags: -Copt-level=2
-//@ run-pass
-
-// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
-
-use std::ptr;
-
-fn main() {
-    let a: usize = {
-        let v = 0;
-        ptr::from_ref(&v).expose_provenance()
-    };
-    let b: usize = {
-        let v = 0;
-        ptr::from_ref(&v).expose_provenance()
-    };
-
-    assert_ne!(a, b);
-    assert_ne!(a, b);
-    let c = a;
-    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
-    println!("{a} {b}");
-    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
-}
diff --git a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs b/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
deleted file mode 100644
index a02ff30918daf..0000000000000
--- a/tests/ui/codegen/equal-pointers-unequal/strict-provenance/print3.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-//@ known-bug: #107975
-//@ compile-flags: -Copt-level=2
-//@ run-pass
-
-// https://github.com/rust-lang/rust/issues/107975#issuecomment-1430704499
-
-use std::ptr;
-
-fn main() {
-    let a: usize = {
-        let v = 0;
-        ptr::from_ref(&v).addr()
-    };
-    let b: usize = {
-        let v = 0;
-        ptr::from_ref(&v).addr()
-    };
-
-    assert_ne!(a, b);
-    assert_ne!(a, b);
-    let c = a;
-    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "false true false");
-    println!("{a} {b}");
-    assert_eq!(format!("{} {} {}", a == b, a == c, b == c), "true true true");
-}

From 3ef1a3f1c5775357c6192584a42bb6469c1f51b8 Mon Sep 17 00:00:00 2001
From: Chris Denton <chris@chrisdenton.dev>
Date: Mon, 31 Mar 2025 16:10:02 +0000
Subject: [PATCH 06/11] Remove ChrisDenton from on vacation

---
 triagebot.toml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/triagebot.toml b/triagebot.toml
index 217da9935383c..47a8c588ad9e5 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1124,7 +1124,6 @@ warn_non_default_branch.enable = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
     "jyn514",
-    "ChrisDenton",
     "saethlin",
 ]
 

From 753968162a423d5a63ca86ef509d4aaf18ac1f9a Mon Sep 17 00:00:00 2001
From: tiif <pekyuan@gmail.com>
Date: Mon, 31 Mar 2025 16:42:01 +0000
Subject: [PATCH 07/11] Fix invalid link

---
 compiler/rustc_middle/src/ty/mod.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index ac98cbc8d6cba..0ffaef82f1c8e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -953,7 +953,7 @@ impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> {
 /// environment. `ParamEnv` is the type that represents this information. See the
 /// [dev guide chapter][param_env_guide] for more information.
 ///
-/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html
+/// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 #[derive(HashStable, TypeVisitable, TypeFoldable)]
 pub struct ParamEnv<'tcx> {
@@ -977,7 +977,7 @@ impl<'tcx> ParamEnv<'tcx> {
     /// to use an empty environment. See the [dev guide section][param_env_guide]
     /// for information on what a `ParamEnv` is and how to acquire one.
     ///
-    /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/param_env/param_env_summary.html
+    /// [param_env_guide]: https://rustc-dev-guide.rust-lang.org/typing_parameter_envs.html
     #[inline]
     pub fn empty() -> Self {
         Self::new(ListWithCachedTypeInfo::empty())

From a6a6d01bbc93da72474983d355e7442abbd162e8 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Wed, 26 Mar 2025 09:47:46 +1100
Subject: [PATCH 08/11] Use `sym::dummy` in one more place.

It makes it clearer that the symbol is unused and doesn't matter.
---
 compiler/rustc_resolve/src/diagnostics.rs | 2 +-
 compiler/rustc_span/src/hygiene.rs        | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 63ea8c4ced13c..f7343b93281f5 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1091,7 +1091,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     ));
                 }
                 Scope::BuiltinAttrs => {
-                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty));
+                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
                     if filter_fn(res) {
                         suggestions.extend(
                             BUILTIN_ATTRIBUTES
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index e7a8dee27f568..9959e98e3dd75 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1440,7 +1440,8 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
                 }
             }
             Entry::Vacant(entry) => {
-                // We are the first thread to start decoding. Mark the current thread as being progress.
+                // We are the first thread to start decoding. Mark the current thread as being
+                // progress.
                 context.local_in_progress.borrow_mut().insert(raw_id);
 
                 // Allocate and store SyntaxContext id *before* calling the decoder function,

From 9fb0defa520c82ccf79af7961ee926dba77b4e96 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Wed, 26 Mar 2025 13:23:13 +1100
Subject: [PATCH 09/11] Tweak `check_doc_keyword`.

To use one `kw::Empty` instead of two. It's a little more direct this
way, and avoids `kw::Empty` being used for both "no string" and "empty
string".
---
 compiler/rustc_passes/src/check_attr.rs | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index ada3151c3b8c1..3019c5c0dae80 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1041,11 +1041,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             s <= kw::Union || s == sym::SelfTy
         }
 
-        let doc_keyword = meta.value_str().unwrap_or(kw::Empty);
-        if doc_keyword == kw::Empty {
-            self.doc_attr_str_error(meta, "keyword");
-            return;
-        }
+        let doc_keyword = match meta.value_str() {
+            Some(value) if value != kw::Empty => value,
+            _ => return self.doc_attr_str_error(meta, "keyword"),
+        };
+
         let item_kind = match self.tcx.hir_node(hir_id) {
             hir::Node::Item(item) => Some(&item.kind),
             _ => None,

From 929749d8018b3a5afde968cff6da11b8460dd52d Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Wed, 26 Mar 2025 13:33:38 +1100
Subject: [PATCH 10/11] Improve `is_doc_keyword`.

This is part of the implementation of `#[doc(keyword = "match")]`
attributes used by `std` to provide documentation for keywords.

`is_doc_keyword` currently does a crude keyword range test that's
intended to catch all keywords but misses `kw::Yeet`. This commit
changes it to use `Symbol` methods, including the new `is_weak` method
(required for `union`). `Symbol` methods are much less prone to falling
out of date if new keywords are added.
---
 compiler/rustc_passes/src/check_attr.rs | 4 ++--
 compiler/rustc_span/src/symbol.rs       | 6 +++++-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 3019c5c0dae80..cfc0369c5989b 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{
     UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
 };
 use rustc_session::parse::feature_err;
-use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, kw, sym};
+use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym};
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
 use rustc_trait_selection::traits::ObligationCtxt;
@@ -1038,7 +1038,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we
             // can remove the `SelfTy` case here, remove `sym::SelfTy`, and update the
             // `#[doc(keyword = "SelfTy")` attribute in `library/std/src/keyword_docs.rs`.
-            s <= kw::Union || s == sym::SelfTy
+            s.is_reserved(|| edition::LATEST_STABLE_EDITION) || s.is_weak() || s == sym::SelfTy
         }
 
         let doc_keyword = match meta.value_str() {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 47dd80c432ead..c6e570e524f59 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -131,7 +131,7 @@ symbols! {
         // tidy-alphabetical-end
 
         // Weak keywords, have special meaning only in specific contexts.
-        // Matching predicates: none
+        // Matching predicates: `is_weak`
         // tidy-alphabetical-start
         Auto:               "auto",
         Builtin:            "builtin",
@@ -2725,6 +2725,10 @@ impl Symbol {
             || self.is_unused_keyword_conditional(edition)
     }
 
+    pub fn is_weak(self) -> bool {
+        self >= kw::Auto && self <= kw::Yeet
+    }
+
     /// A keyword or reserved identifier that can be used as a path segment.
     pub fn is_path_segment_keyword(self) -> bool {
         self == kw::Super

From 27850631638e74bd017d963a35c53e7f81f42e4d Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Thu, 27 Mar 2025 22:56:13 +1100
Subject: [PATCH 11/11] Avoid `kw::Empty` use for `AuxParamsAttr`.

By changing two of the fields to use `Option<Ident>` instead of `Ident`.
As a result, `None` now means "no identifier", which is much clearer
than using an empty identifier.
---
 .../src/significant_drop_tightening.rs        | 30 ++++++++++---------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
index e9db7c9d031a9..76874cc342066 100644
--- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -79,10 +79,11 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
             if apa.counter <= 1 || !apa.has_expensive_expr_after_last_attr {
                 continue;
             }
+            let first_bind_ident = apa.first_bind_ident.unwrap();
             span_lint_and_then(
                 cx,
                 SIGNIFICANT_DROP_TIGHTENING,
-                apa.first_bind_ident.span,
+                first_bind_ident.span,
                 "temporary with significant `Drop` can be early dropped",
                 |diag| {
                     match apa.counter {
@@ -91,13 +92,13 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
                             let indent = " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0));
                             let init_method = snippet(cx, apa.first_method_span, "..");
                             let usage_method = snippet(cx, apa.last_method_span, "..");
-                            let stmt = if apa.last_bind_ident == Ident::empty() {
-                                format!("\n{indent}{init_method}.{usage_method};")
-                            } else {
+                            let stmt = if let Some(last_bind_ident) = apa.last_bind_ident {
                                 format!(
                                     "\n{indent}let {} = {init_method}.{usage_method};",
-                                    snippet(cx, apa.last_bind_ident.span, ".."),
+                                    snippet(cx, last_bind_ident.span, ".."),
                                 )
+                            } else {
+                                format!("\n{indent}{init_method}.{usage_method};")
                             };
 
                             diag.multipart_suggestion_verbose(
@@ -113,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
                                 format!(
                                     "\n{}drop({});",
                                     " ".repeat(indent_of(cx, apa.last_stmt_span).unwrap_or(0)),
-                                    apa.first_bind_ident
+                                    first_bind_ident
                                 ),
                                 Applicability::MaybeIncorrect,
                             );
@@ -124,7 +125,7 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
                         apa.first_block_span,
                         format!(
                             "temporary `{}` is currently being dropped at the end of its contained scope",
-                            apa.first_bind_ident
+                            first_bind_ident
                         ),
                     );
                 },
@@ -283,7 +284,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
                 let mut apa = AuxParamsAttr {
                     first_block_hir_id: self.ap.curr_block_hir_id,
                     first_block_span: self.ap.curr_block_span,
-                    first_bind_ident: ident,
+                    first_bind_ident: Some(ident),
                     first_method_span: {
                         let expr_or_init = expr_or_init(self.cx, expr);
                         if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr_or_init.kind {
@@ -307,7 +308,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
                 match self.ap.curr_stmt.kind {
                     hir::StmtKind::Let(local) => {
                         if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
-                            apa.last_bind_ident = ident;
+                            apa.last_bind_ident = Some(ident);
                         }
                         if let Some(local_init) = local.init
                             && let hir::ExprKind::MethodCall(_, _, _, span) = local_init.kind
@@ -373,7 +374,7 @@ struct AuxParamsAttr {
     first_block_span: Span,
     /// The binding or variable that references the initial construction of the type marked with
     /// `#[has_significant_drop]`.
-    first_bind_ident: Ident,
+    first_bind_ident: Option<Ident>,
     /// Similar to `init_bind_ident` but encompasses the right-hand method call.
     first_method_span: Span,
     /// Similar to `init_bind_ident` but encompasses the whole contained statement.
@@ -381,7 +382,7 @@ struct AuxParamsAttr {
 
     /// The last visited binding or variable span within a block that had any referenced inner type
     /// marked with `#[has_significant_drop]`.
-    last_bind_ident: Ident,
+    last_bind_ident: Option<Ident>,
     /// Similar to `last_bind_span` but encompasses the right-hand method call.
     last_method_span: Span,
     /// Similar to `last_bind_span` but encompasses the whole contained statement.
@@ -395,10 +396,10 @@ impl Default for AuxParamsAttr {
             has_expensive_expr_after_last_attr: false,
             first_block_hir_id: HirId::INVALID,
             first_block_span: DUMMY_SP,
-            first_bind_ident: Ident::empty(),
+            first_bind_ident: None,
             first_method_span: DUMMY_SP,
             first_stmt_span: DUMMY_SP,
-            last_bind_ident: Ident::empty(),
+            last_bind_ident: None,
             last_method_span: DUMMY_SP,
             last_stmt_span: DUMMY_SP,
         }
@@ -413,7 +414,7 @@ fn dummy_stmt_expr<'any>(expr: &'any hir::Expr<'any>) -> hir::Stmt<'any> {
     }
 }
 
-fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_>) -> bool {
+fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Option<Ident>, lcx: &LateContext<'_>) -> bool {
     if let hir::ExprKind::Call(fun, [first_arg]) = expr.kind
         && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
         && let Res::Def(DefKind::Fn, did) = fun_path.res
@@ -422,6 +423,7 @@ fn has_drop(expr: &hir::Expr<'_>, first_bind_ident: &Ident, lcx: &LateContext<'_
         let has_ident = |local_expr: &hir::Expr<'_>| {
             if let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &local_expr.kind
                 && let [first_arg_ps, ..] = arg_path.segments
+                && let Some(first_bind_ident) = first_bind_ident
                 && &first_arg_ps.ident == first_bind_ident
             {
                 true