From 72076c6b54478159b848552237b1e09e2c39bbce Mon Sep 17 00:00:00 2001 From: Skgland Date: Wed, 26 Nov 2025 21:38:51 +0100 Subject: [PATCH 01/16] move and rename proc_macro::tracked_{env::var,path::path} --- compiler/rustc_fluent_macro/src/fluent.rs | 3 +++ compiler/rustc_fluent_macro/src/lib.rs | 3 ++- compiler/rustc_macros/src/current_version.rs | 4 ++++ compiler/rustc_macros/src/symbols.rs | 8 ++++++- library/proc_macro/src/lib.rs | 22 ++++++++++---------- tests/ui/proc-macro/auxiliary/env.rs | 6 +++--- 6 files changed, 30 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs index e383d085bb3d3..46d11d0469a43 100644 --- a/compiler/rustc_fluent_macro/src/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -8,6 +8,9 @@ use fluent_syntax::ast::{ Attribute, Entry, Expression, Identifier, InlineExpression, Message, Pattern, PatternElement, }; use fluent_syntax::parser::ParserError; +#[cfg(not(bootstrap))] +use proc_macro::tracked::path; +#[cfg(bootstrap)] use proc_macro::tracked_path::path; use proc_macro::{Diagnostic, Level, Span}; use proc_macro2::TokenStream; diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index c2f49de31c237..e9ddeb3b971e3 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -1,7 +1,8 @@ // tidy-alphabetical-start #![allow(rustc::default_hash_types)] +#![cfg_attr(bootstrap, feature(track_path))] +#![cfg_attr(not(bootstrap), feature(proc_macro_tracked_path))] #![feature(proc_macro_diagnostic)] -#![feature(track_path)] // tidy-alphabetical-end use proc_macro::TokenStream; diff --git a/compiler/rustc_macros/src/current_version.rs b/compiler/rustc_macros/src/current_version.rs index 42ca60a6d8ab8..6912d68421cbc 100644 --- a/compiler/rustc_macros/src/current_version.rs +++ b/compiler/rustc_macros/src/current_version.rs @@ -22,7 +22,11 @@ struct RustcVersion { impl RustcVersion { fn parse_cfg_release(env_var: &str) -> Result> { + #[cfg(not(bootstrap))] + let value = proc_macro::tracked::env_var(env_var)?; + #[cfg(bootstrap)] let value = proc_macro::tracked_env::var(env_var)?; + Self::parse_str(&value) .ok_or_else(|| format!("failed to parse rustc version: {:?}", value).into()) } diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs index 78a4d47ca3346..7437dddf58c56 100644 --- a/compiler/rustc_macros/src/symbols.rs +++ b/compiler/rustc_macros/src/symbols.rs @@ -259,7 +259,13 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { break; } - let value = match proc_macro::tracked_env::var(env_var.value()) { + #[cfg(bootstrap)] + let tracked_env = proc_macro::tracked_env::var(env_var.value()); + + #[cfg(not(bootstrap))] + let tracked_env = proc_macro::tracked::env_var(env_var.value()); + + let value = match tracked_env { Ok(value) => value, Err(err) => { errors.list.push(syn::Error::new_spanned(expr, err)); diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 4efdfcad924b5..ee224ceb6045f 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1594,9 +1594,14 @@ impl fmt::Debug for Literal { } } -/// Tracked access to environment variables. -#[unstable(feature = "proc_macro_tracked_env", issue = "99515")] -pub mod tracked_env { +#[unstable( + feature = "proc_macro_tracked_path", + issue = "99515", + implied_by = "proc_macro_tracked_env" +)] +/// Functionality for adding environment state to the build dependency info. +pub mod tracked { + use std::env::{self, VarError}; use std::ffi::OsStr; @@ -1606,23 +1611,18 @@ pub mod tracked_env { /// Besides the dependency tracking this function should be equivalent to `env::var` from the /// standard library, except that the argument must be UTF-8. #[unstable(feature = "proc_macro_tracked_env", issue = "99515")] - pub fn var + AsRef>(key: K) -> Result { + pub fn env_var + AsRef>(key: K) -> Result { let key: &str = key.as_ref(); let value = crate::bridge::client::FreeFunctions::injected_env_var(key) .map_or_else(|| env::var(key), Ok); crate::bridge::client::FreeFunctions::track_env_var(key, value.as_deref().ok()); value } -} - -/// Tracked access to additional files. -#[unstable(feature = "track_path", issue = "99515")] -pub mod tracked_path { - /// Track a file explicitly. + /// Track a file or directory explicitly. /// /// Commonly used for tracking asset preprocessing. - #[unstable(feature = "track_path", issue = "99515")] + #[unstable(feature = "proc_macro_tracked_path", issue = "99515")] pub fn path>(path: P) { let path: &str = path.as_ref(); crate::bridge::client::FreeFunctions::track_path(path); diff --git a/tests/ui/proc-macro/auxiliary/env.rs b/tests/ui/proc-macro/auxiliary/env.rs index d01e3b42d4ce3..f0f0328e131e6 100644 --- a/tests/ui/proc-macro/auxiliary/env.rs +++ b/tests/ui/proc-macro/auxiliary/env.rs @@ -3,11 +3,11 @@ extern crate proc_macro; use proc_macro::TokenStream; -use proc_macro::tracked_env::var; +use proc_macro::tracked::env_var; #[proc_macro] pub fn generate_const(input: TokenStream) -> TokenStream { - let the_const = match var("THE_CONST") { + let the_const = match env_var("THE_CONST") { Ok(x) if x == "12" => { "const THE_CONST: u32 = 12;" } @@ -15,7 +15,7 @@ pub fn generate_const(input: TokenStream) -> TokenStream { "const THE_CONST: u32 = 0;" } }; - let another = if var("ANOTHER").is_ok() { + let another = if env_var("ANOTHER").is_ok() { "const ANOTHER: u32 = 1;" } else { "const ANOTHER: u32 = 2;" From 8d8d7021c6006481728775ac4db170af05cf161d Mon Sep 17 00:00:00 2001 From: Skgland Date: Wed, 26 Nov 2025 21:43:44 +0100 Subject: [PATCH 02/16] change proc_macro::tracked::path to take an AsRef instead of an AsRef --- library/proc_macro/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index ee224ceb6045f..cb9e53780b041 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1604,6 +1604,7 @@ pub mod tracked { use std::env::{self, VarError}; use std::ffi::OsStr; + use std::path::Path; /// Retrieve an environment variable and add it to build dependency info. /// The build system executing the compiler will know that the variable was accessed during @@ -1623,8 +1624,8 @@ pub mod tracked { /// /// Commonly used for tracking asset preprocessing. #[unstable(feature = "proc_macro_tracked_path", issue = "99515")] - pub fn path>(path: P) { - let path: &str = path.as_ref(); + pub fn path>(path: P) { + let path: &str = path.as_ref().to_str().unwrap(); crate::bridge::client::FreeFunctions::track_path(path); } } From f4296bce97007d68ab4236f5293f50bf06a3664e Mon Sep 17 00:00:00 2001 From: Skgland Date: Thu, 27 Nov 2025 22:02:47 +0100 Subject: [PATCH 03/16] fix tests --- tests/run-make/env-dep-info/macro_def.rs | 4 ++-- tests/run-make/track-path-dep-info/macro_def.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/run-make/env-dep-info/macro_def.rs b/tests/run-make/env-dep-info/macro_def.rs index e328eae48326d..17d27ebfba3c8 100644 --- a/tests/run-make/env-dep-info/macro_def.rs +++ b/tests/run-make/env-dep-info/macro_def.rs @@ -6,7 +6,7 @@ use proc_macro::*; #[proc_macro] pub fn access_env_vars(_: TokenStream) -> TokenStream { - let _ = tracked_env::var("EXISTING_PROC_MACRO_ENV"); - let _ = tracked_env::var("NONEXISTENT_PROC_MACEO_ENV"); + let _ = tracked::env_var("EXISTING_PROC_MACRO_ENV"); + let _ = tracked::env_var("NONEXISTENT_PROC_MACEO_ENV"); TokenStream::new() } diff --git a/tests/run-make/track-path-dep-info/macro_def.rs b/tests/run-make/track-path-dep-info/macro_def.rs index 8777ce21f8b82..032594d905d09 100644 --- a/tests/run-make/track-path-dep-info/macro_def.rs +++ b/tests/run-make/track-path-dep-info/macro_def.rs @@ -1,4 +1,4 @@ -#![feature(track_path)] +#![feature(proc_macro_track_path)] #![crate_type = "proc-macro"] extern crate proc_macro; @@ -6,6 +6,6 @@ use proc_macro::*; #[proc_macro] pub fn access_tracked_paths(_: TokenStream) -> TokenStream { - tracked_path::path("emojis.txt"); + tracked::path("emojis.txt"); TokenStream::new() } From 3f67246af50fe6f67d5c56b02efaeb01a0d48f0e Mon Sep 17 00:00:00 2001 From: Skgland Date: Fri, 28 Nov 2025 20:47:03 +0100 Subject: [PATCH 04/16] fix tests/run-make/track-path-dep-info attempt 2 --- tests/run-make/track-path-dep-info/macro_def.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run-make/track-path-dep-info/macro_def.rs b/tests/run-make/track-path-dep-info/macro_def.rs index 032594d905d09..b7271cac2344b 100644 --- a/tests/run-make/track-path-dep-info/macro_def.rs +++ b/tests/run-make/track-path-dep-info/macro_def.rs @@ -1,4 +1,4 @@ -#![feature(proc_macro_track_path)] +#![feature(proc_macro_tracked_path)] #![crate_type = "proc-macro"] extern crate proc_macro; From 0030e8ab1864d53d98de1e90ab3cf999b62ddcf1 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 4 Aug 2025 21:55:18 -0400 Subject: [PATCH 05/16] compiler-builtins: Change gating for outline atomic symbols Build outline atomic symbols on all targets that have `outline-atomics` enabled, rather than only on Linux. Since this is no longer OS-specific, also rename the module. --- .../src/{aarch64_linux.rs => aarch64_outline_atomics.rs} | 8 ++++---- library/compiler-builtins/compiler-builtins/src/lib.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) rename library/compiler-builtins/compiler-builtins/src/{aarch64_linux.rs => aarch64_outline_atomics.rs} (97%) diff --git a/library/compiler-builtins/compiler-builtins/src/aarch64_linux.rs b/library/compiler-builtins/compiler-builtins/src/aarch64_outline_atomics.rs similarity index 97% rename from library/compiler-builtins/compiler-builtins/src/aarch64_linux.rs rename to library/compiler-builtins/compiler-builtins/src/aarch64_outline_atomics.rs index 01d7fb4732918..df0cf76502223 100644 --- a/library/compiler-builtins/compiler-builtins/src/aarch64_linux.rs +++ b/library/compiler-builtins/compiler-builtins/src/aarch64_outline_atomics.rs @@ -196,7 +196,7 @@ macro_rules! compare_and_swap { "cbnz w17, 0b", "1:", "ret", - have_lse = sym crate::aarch64_linux::HAVE_LSE_ATOMICS, + have_lse = sym crate::aarch64_outline_atomics::HAVE_LSE_ATOMICS, } } } @@ -228,7 +228,7 @@ macro_rules! compare_and_swap_i128 { "cbnz w15, 0b", "1:", "ret", - have_lse = sym crate::aarch64_linux::HAVE_LSE_ATOMICS, + have_lse = sym crate::aarch64_outline_atomics::HAVE_LSE_ATOMICS, } } } @@ -256,7 +256,7 @@ macro_rules! swap { concat!(stxr!($ordering, $bytes), " w17, ", reg!($bytes, 16), ", [x1]"), "cbnz w17, 0b", "ret", - have_lse = sym crate::aarch64_linux::HAVE_LSE_ATOMICS, + have_lse = sym crate::aarch64_outline_atomics::HAVE_LSE_ATOMICS, } } } @@ -286,7 +286,7 @@ macro_rules! fetch_op { concat!(stxr!($ordering, $bytes), " w15, ", reg!($bytes, 17), ", [x1]"), "cbnz w15, 0b", "ret", - have_lse = sym crate::aarch64_linux::HAVE_LSE_ATOMICS, + have_lse = sym crate::aarch64_outline_atomics::HAVE_LSE_ATOMICS, } } } diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index a9dd6e531c5d3..c993209699be4 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -55,8 +55,8 @@ pub mod arm; #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))] pub mod aarch64; -#[cfg(all(target_arch = "aarch64", target_os = "linux"))] -pub mod aarch64_linux; +#[cfg(all(target_arch = "aarch64", target_feature = "outline-atomics"))] +pub mod aarch64_outline_atomics; #[cfg(all( kernel_user_helpers, From 2105a2579b22a45fcaa8f4037dffc084c7cd0764 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 4 Aug 2025 21:55:18 -0400 Subject: [PATCH 06/16] Make the `RUST_LSE_INIT` constructor cross-platform Change the gating and link sections to enable this for any platforms that enable `outline-atomics`, rather than only Linux. Additionally, no longer run this if LSE is available, since in this case the outline versions will never be called. --- library/std/src/sys/configure_builtins.rs | 46 ++++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/configure_builtins.rs b/library/std/src/sys/configure_builtins.rs index 9d776b778dcbe..f569ec0f51298 100644 --- a/library/std/src/sys/configure_builtins.rs +++ b/library/std/src/sys/configure_builtins.rs @@ -1,13 +1,49 @@ -/// Hook into .init_array to enable LSE atomic operations at startup, if -/// supported. -#[cfg(all(target_arch = "aarch64", target_os = "linux", not(feature = "compiler-builtins-c")))] +/// Enable LSE atomic operations at startup, if supported. +/// +/// Linker sections are based on what [`ctor`] does, with priorities to run slightly before user +/// code: +/// +/// - Apple uses the section `__mod_init_func`, `mod_init_funcs` is needed to set +/// `S_MOD_INIT_FUNC_POINTERS`. There doesn't seem to be a way to indicate priorities. +/// - Windows uses `.CRT$XCT`, which is run before user constructors (these should use `.CRT$XCU`). +/// - ELF uses `.init_array` with a priority of 90, which runs before our `ARGV_INIT_ARRAY` +/// initializer (priority 99). Both are within the 0-100 implementation-reserved range, per docs +/// for the [`prio-ctor-dtor`] warning, and this matches compiler-rt's `CONSTRUCTOR_PRIORITY`. +/// +/// To save startup time, the initializer is only run if outline atomic routines from +/// compiler-builtins may be used. If LSE is known to be available then the calls are never +/// emitted, and if we build the C intrinsics then it has its own initializer using the symbol +/// `__aarch64_have_lse_atomics`. +/// +/// Initialization is done in a global constructor to so we get the same behavior regardless of +/// whether Rust's `init` is used, or if we are in a `dylib` or `no_main` situation (as opposed +/// to doing it as part of pre-main startup). This also matches C implementations. +/// +/// Ideally `core` would have something similar, but detecting the CPU features requires the +/// auxiliary vector from the OS. We do the initialization in `std` rather than as part of +/// `compiler-builtins` because a builtins->std dependency isn't possible, and inlining parts of +/// `std-detect` would be much messier. +/// +/// [`ctor`]: https://github.com/mmastrac/rust-ctor/blob/63382b833ddcbfb8b064f4e86bfa1ed4026ff356/shared/src/macros/mod.rs#L522-L534 +/// [`prio-ctor-dtor`]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html +#[cfg(all( + target_arch = "aarch64", + target_feature = "outline-atomics", + not(target_feature = "lse"), + not(feature = "compiler-builtins-c"), +))] #[used] -#[unsafe(link_section = ".init_array.90")] +#[cfg_attr(target_vendor = "apple", unsafe(link_section = "__DATA,__mod_init_func,mod_init_funcs"))] +#[cfg_attr(target_os = "windows", unsafe(link_section = ".CRT$XCT"))] +#[cfg_attr( + not(any(target_vendor = "apple", target_os = "windows")), + unsafe(link_section = ".init_array.90") +)] static RUST_LSE_INIT: extern "C" fn() = { extern "C" fn init_lse() { use crate::arch; - // This is provided by compiler-builtins::aarch64_linux. + // This is provided by compiler-builtins::aarch64_outline_atomics. unsafe extern "C" { fn __rust_enable_lse(); } From 1ed1b6e2674e0884479042ae1b6aac431f1c217c Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 5 Sep 2025 15:20:59 -0400 Subject: [PATCH 07/16] Enable `outline-atomics` by default on AArch64 Windows platforms Windows has a similar flag `/forceInterlockedFunctions`, which uses names such as `_InterlockedAdd64_rel`. --- .../rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs | 2 +- .../rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs index ce17280b153d6..db3cf83ddc999 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, Cc, FramePointer, LinkerFlavor, Lld, Target, TargetMetad pub(crate) fn target() -> Target { let mut base = base::windows_gnullvm::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon".into(); + base.features = "+v8a,+neon,+outline-atomics".into(); base.linker = Some("aarch64-w64-mingw32-clang".into()); base.add_pre_link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &["-m", "arm64pe"]); diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs index 0d06bec21f4a4..e9f7f51a7a35b 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs @@ -3,7 +3,7 @@ use crate::spec::{Arch, FramePointer, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { let mut base = base::windows_msvc::opts(); base.max_atomic_width = Some(128); - base.features = "+v8a,+neon".into(); + base.features = "+v8a,+neon,+outline-atomics".into(); // Microsoft recommends enabling frame pointers on Arm64 Windows. // From https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#integer-registers From c45590397843909a1f36d4fd9d89cfc1e7551652 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 5 Sep 2025 15:23:00 -0400 Subject: [PATCH 08/16] Enable `outline-atomics` by default on AArch64 Android Per LLVM commit c5e7e649d537 ("[AArch64][Clang][Linux] Enable out-of-line atomics by default.") [1], Clang enables these on Android. Thus, do the same in Rust. [1]: https://github.com/llvm/llvm-project/commit/c5e7e649d537067de --- compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs index 3b158c13521ea..d1810b6fa4860 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs @@ -21,7 +21,7 @@ pub(crate) fn target() -> Target { max_atomic_width: Some(128), // As documented in https://developer.android.com/ndk/guides/cpu-features.html // the neon (ASIMD) and FP must exist on all android aarch64 targets. - features: "+v8a,+neon".into(), + features: "+v8a,+neon,+outline-atomics".into(), // the AAPCS64 expects use of non-leaf frame pointers per // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not From 21525f862d621bbeb9a131f3631111c402e1a447 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 5 Sep 2025 15:34:47 -0400 Subject: [PATCH 09/16] Enable `outline-atomics` by default on AArch64 Fuchsia Clang has done this by default since LLVM commit 1a963d3278c2 ("[Driver] Make -moutline-atomics default for aarch64-fuchsia targets"), [1], so do the same here. [1]: https://github.com/llvm/llvm-project/commit/1a963d3278c2daab7e12125371442cd129c09954 --- .../rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index 6489e2bda8091..8a07f98075a89 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs @@ -5,7 +5,7 @@ use crate::spec::{ pub(crate) fn target() -> Target { let mut base = base::fuchsia::opts(); base.cpu = "generic".into(); - base.features = "+v8a,+crc,+aes,+sha2,+neon".into(); + base.features = "+v8a,+crc,+aes,+sha2,+neon,+outline-atomics".into(); base.max_atomic_width = Some(128); base.stack_probes = StackProbeType::Inline; base.supported_sanitizers = SanitizerSet::ADDRESS From 66c150c1fa29d15e1c5c06dfe708c8443faf42c3 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 5 Sep 2025 15:34:57 -0400 Subject: [PATCH 10/16] Enable `outline-atomics` by default on AArch64 OpenBSD Clang has recently started doing this, as of LLVM commit 5d774ec8d183 ("[Driver] Enable outline atomics for OpenBSD/aarch64") [1]. Thus, do the same here. [1]: https://github.com/llvm/llvm-project/commit/5d774ec8d183cbbb243c57f50d891822211d3ec2 --- .../rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs index e5e40cb38b911..14a2f007f1e8c 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: Arch::AArch64, options: TargetOptions { - features: "+v8a".into(), + features: "+v8a,+outline-atomics".into(), max_atomic_width: Some(128), stack_probes: StackProbeType::Inline, ..base::openbsd::opts() From 01e2cf8f44b0d99c019f292140cfc58b9bc67501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 15 Sep 2025 02:28:43 -0700 Subject: [PATCH 11/16] Handle macro invocation in attribute during parse ``` error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` --> $DIR/macro-in-attribute.rs:4:21 | LL | #[deprecated(note = concat!("a", "b"))] | ^^^^^^^^^^^^^^^^^ macros are not allowed here ``` --- compiler/rustc_attr_parsing/messages.ftl | 1 + compiler/rustc_attr_parsing/src/parser.rs | 40 ++++++++++++++----- .../src/session_diagnostics.rs | 2 + .../rustc_parse/src/parser/diagnostics.rs | 2 +- tests/ui/parser/macro/macro-in-attribute.rs | 9 +++++ .../ui/parser/macro/macro-in-attribute.stderr | 8 ++++ 6 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 tests/ui/parser/macro/macro-in-attribute.rs create mode 100644 tests/ui/parser/macro/macro-in-attribute.stderr diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 0d53ed9d97a54..5cb34f96d1302 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -87,6 +87,7 @@ attr_parsing_invalid_link_modifier = attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr} .remove_neg_sugg = negative numbers are not literals, try removing the `-` sign .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal + .label = macros are not allowed here attr_parsing_invalid_predicate = invalid predicate `{$predicate}` diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 7474471f2fe0f..23f0e4fa0330c 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; use rustc_parse::exp; -use rustc_parse::parser::{Parser, PathStyle, token_descr}; +use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr}; use rustc_session::errors::{create_lit_error, report_lit_error}; use rustc_session::parse::ParseSess; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym}; @@ -488,6 +488,7 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { descr: token_descr(&self.parser.token), quote_ident_sugg: None, remove_neg_sugg: None, + macro_call: None, }; // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and @@ -496,20 +497,37 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { if self.parser.prev_token == token::Eq && let token::Ident(..) = self.parser.token.kind { - let before = self.parser.token.span.shrink_to_lo(); - while let token::Ident(..) = self.parser.token.kind { - self.parser.bump(); + if self.parser.look_ahead(1, |t| matches!(t.kind, token::TokenKind::Bang)) { + let snapshot = self.parser.create_snapshot_for_diagnostic(); + let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false); + match stmt { + Ok(Some(stmt)) => { + // The user tried to write something like + // `#[deprecated(note = concat!("a", "b"))]`. + err.descr = format!("macro {}", err.descr); + err.macro_call = Some(stmt.span); + err.span = stmt.span; + } + Ok(None) => {} + Err(err) => { + err.cancel(); + self.parser.restore_snapshot(snapshot); + } + } + } else { + let before = self.parser.token.span.shrink_to_lo(); + while let token::Ident(..) = self.parser.token.kind { + self.parser.bump(); + } + err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { + before, + after: self.parser.prev_token.span.shrink_to_hi(), + }); } - err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { - before, - after: self.parser.prev_token.span.shrink_to_hi(), - }); } if self.parser.token == token::Minus - && self - .parser - .look_ahead(1, |t| matches!(t.kind, rustc_ast::token::TokenKind::Literal { .. })) + && self.parser.look_ahead(1, |t| matches!(t.kind, token::TokenKind::Literal { .. })) { err.remove_neg_sugg = Some(InvalidMetaItemRemoveNegSugg { negative_sign: self.parser.token.span }); diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index c4f6f9c6a38cb..95eca25fd362b 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -804,6 +804,8 @@ pub(crate) struct InvalidMetaItem { pub quote_ident_sugg: Option, #[subdiagnostic] pub remove_neg_sugg: Option, + #[label] + pub macro_call: Option, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index d4667a09af6d9..4f6860fead8d0 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -284,7 +284,7 @@ impl<'a> Parser<'a> { } /// Replace `self` with `snapshot.parser`. - pub(super) fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) { + pub fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) { *self = snapshot.parser; } diff --git a/tests/ui/parser/macro/macro-in-attribute.rs b/tests/ui/parser/macro/macro-in-attribute.rs new file mode 100644 index 0000000000000..57808c6fd27da --- /dev/null +++ b/tests/ui/parser/macro/macro-in-attribute.rs @@ -0,0 +1,9 @@ +// Test for #146325. +// Ensure that when we encounter a macro invocation in an attribute, we don't suggest nonsense. + +#[deprecated(note = concat!("a", "b"))] +struct X; +//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` +//~| NOTE: macros are not allowed here + +fn main() {} diff --git a/tests/ui/parser/macro/macro-in-attribute.stderr b/tests/ui/parser/macro/macro-in-attribute.stderr new file mode 100644 index 0000000000000..e0ae51365a85c --- /dev/null +++ b/tests/ui/parser/macro/macro-in-attribute.stderr @@ -0,0 +1,8 @@ +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` + --> $DIR/macro-in-attribute.rs:4:21 + | +LL | #[deprecated(note = concat!("a", "b"))] + | ^^^^^^^^^^^^^^^^^ macros are not allowed here + +error: aborting due to 1 previous error + From 0b0e826c0fc09eb54487658ab782e816d92619d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 28 Sep 2025 20:52:57 +0000 Subject: [PATCH 12/16] Rework attribute recovery logic --- compiler/rustc_ast/src/ast.rs | 13 +++ compiler/rustc_attr_parsing/messages.ftl | 2 +- compiler/rustc_attr_parsing/src/parser.rs | 80 ++++++++++--------- .../src/session_diagnostics.rs | 2 +- tests/ui/attributes/malformed-fn-align.rs | 2 +- tests/ui/attributes/malformed-fn-align.stderr | 4 +- ...-66340-deprecated-attr-non-meta-grammar.rs | 2 +- ...40-deprecated-attr-non-meta-grammar.stderr | 4 +- tests/ui/parser/attribute/attr-bad-meta-4.rs | 2 +- .../parser/attribute/attr-bad-meta-4.stderr | 4 +- .../parser/attribute/attr-unquoted-ident.rs | 19 +++-- .../attribute/attr-unquoted-ident.stderr | 25 ++++-- tests/ui/parser/macro/expr-in-attribute.rs | 9 +++ .../ui/parser/macro/expr-in-attribute.stderr | 8 ++ tests/ui/parser/macro/macro-in-attribute.rs | 2 +- .../ui/parser/macro/macro-in-attribute.stderr | 2 +- 16 files changed, 116 insertions(+), 64 deletions(-) create mode 100644 tests/ui/parser/macro/expr-in-attribute.rs create mode 100644 tests/ui/parser/macro/expr-in-attribute.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index db7cace49ae8f..b696ebeba992c 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1259,6 +1259,19 @@ pub enum StmtKind { MacCall(Box), } +impl StmtKind { + pub fn descr(&self) -> &'static str { + match self { + StmtKind::Let(_) => "local", + StmtKind::Item(_) => "item", + StmtKind::Expr(_) => "expression", + StmtKind::Semi(_) => "statement", + StmtKind::Empty => "semicolon", + StmtKind::MacCall(_) => "macro", + } + } +} + #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct MacCallStmt { pub mac: Box, diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 5cb34f96d1302..02ddf8ac0023d 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -87,7 +87,7 @@ attr_parsing_invalid_link_modifier = attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr} .remove_neg_sugg = negative numbers are not literals, try removing the `-` sign .quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal - .label = macros are not allowed here + .label = {$descr}s are not allowed here attr_parsing_invalid_predicate = invalid predicate `{$predicate}` diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 23f0e4fa0330c..819e5630561d0 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -8,7 +8,7 @@ use std::fmt::{Debug, Display}; use rustc_ast::token::{self, Delimiter, MetaVarKind}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path}; +use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path, StmtKind, UnOp}; use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; @@ -488,51 +488,55 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { descr: token_descr(&self.parser.token), quote_ident_sugg: None, remove_neg_sugg: None, - macro_call: None, + label: None, }; + if let token::OpenInvisible(_) = self.parser.token.kind { + // Do not attempt to suggest anything when encountered as part of a macro expansion. + return self.parser.dcx().create_err(err); + } + // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and // don't `uninterpolate` the token to avoid suggesting anything butchered or questionable // when macro metavariables are involved. - if self.parser.prev_token == token::Eq - && let token::Ident(..) = self.parser.token.kind - { - if self.parser.look_ahead(1, |t| matches!(t.kind, token::TokenKind::Bang)) { - let snapshot = self.parser.create_snapshot_for_diagnostic(); - let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false); - match stmt { - Ok(Some(stmt)) => { - // The user tried to write something like - // `#[deprecated(note = concat!("a", "b"))]`. - err.descr = format!("macro {}", err.descr); - err.macro_call = Some(stmt.span); - err.span = stmt.span; - } - Ok(None) => {} - Err(err) => { - err.cancel(); - self.parser.restore_snapshot(snapshot); + let snapshot = self.parser.create_snapshot_for_diagnostic(); + let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false); + match stmt { + Ok(Some(stmt)) => { + // The user tried to write something like + // `#[deprecated(note = concat!("a", "b"))]`. + err.descr = stmt.kind.descr().to_string(); + err.label = Some(stmt.span); + err.span = stmt.span; + if let StmtKind::Expr(expr) = &stmt.kind + && let ExprKind::Unary(UnOp::Neg, val) = &expr.kind + && let ExprKind::Lit(_) = val.kind + { + err.remove_neg_sugg = Some(InvalidMetaItemRemoveNegSugg { + negative_sign: expr.span.until(val.span), + }); + } else if let StmtKind::Expr(expr) = &stmt.kind + && let ExprKind::Path(None, Path { segments, .. }) = &expr.kind + && segments.len() == 1 + { + while let token::Ident(..) | token::Literal(_) | token::Dot = + self.parser.token.kind + { + // We've got a word, so we try to consume the rest of a potential sentence. + // We include `.` to correctly handle things like `A sentence here.`. + self.parser.bump(); } + err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { + before: expr.span.shrink_to_lo(), + after: self.parser.prev_token.span.shrink_to_hi(), + }); } - } else { - let before = self.parser.token.span.shrink_to_lo(); - while let token::Ident(..) = self.parser.token.kind { - self.parser.bump(); - } - err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg { - before, - after: self.parser.prev_token.span.shrink_to_hi(), - }); } - } - - if self.parser.token == token::Minus - && self.parser.look_ahead(1, |t| matches!(t.kind, token::TokenKind::Literal { .. })) - { - err.remove_neg_sugg = - Some(InvalidMetaItemRemoveNegSugg { negative_sign: self.parser.token.span }); - self.parser.bump(); - self.parser.bump(); + Ok(None) => {} + Err(e) => { + e.cancel(); + self.parser.restore_snapshot(snapshot); + } } self.parser.dcx().create_err(err) diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 95eca25fd362b..2b3108a8d3ed9 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -805,7 +805,7 @@ pub(crate) struct InvalidMetaItem { #[subdiagnostic] pub remove_neg_sugg: Option, #[label] - pub macro_call: Option, + pub label: Option, } #[derive(Subdiagnostic)] diff --git a/tests/ui/attributes/malformed-fn-align.rs b/tests/ui/attributes/malformed-fn-align.rs index c76eda65a75b0..219218f034793 100644 --- a/tests/ui/attributes/malformed-fn-align.rs +++ b/tests/ui/attributes/malformed-fn-align.rs @@ -26,7 +26,7 @@ fn f3() {} #[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on functions fn f4() {} -#[rustc_align(-1)] //~ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +#[rustc_align(-1)] //~ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn f5() {} #[rustc_align(3)] //~ ERROR invalid alignment value: not a power of two diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index 33f789b626952..b419df8ea2d18 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -37,11 +37,11 @@ error[E0589]: invalid alignment value: not a power of two LL | #[rustc_align(0)] | ^ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/malformed-fn-align.rs:29:15 | LL | #[rustc_align(-1)] - | ^ + | ^^ expressions are not allowed here | help: negative numbers are not literals, try removing the `-` sign | diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs index 378d0a3e72358..cdf2b76a1cccc 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs @@ -7,5 +7,5 @@ fn main() { } #[deprecated(note = test)] -//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `test` +//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn foo() {} diff --git a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr index cd985ab5a1824..379c7f5812240 100644 --- a/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr +++ b/tests/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -1,8 +1,8 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `test` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21 | LL | #[deprecated(note = test)] - | ^^^^ + | ^^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.rs b/tests/ui/parser/attribute/attr-bad-meta-4.rs index 606b41e89a5f5..bfd2958ad5659 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.rs +++ b/tests/ui/parser/attribute/attr-bad-meta-4.rs @@ -9,7 +9,7 @@ macro_rules! mac { mac!(an(arbitrary token stream)); #[cfg(feature = -1)] -//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +//~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found fn handler() {} fn main() {} diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr index 1d939942fb9a9..8f4edca226d3b 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr @@ -1,8 +1,8 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `-` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/attr-bad-meta-4.rs:11:17 | LL | #[cfg(feature = -1)] - | ^ + | ^^ expressions are not allowed here | help: negative numbers are not literals, try removing the `-` sign | diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.rs b/tests/ui/parser/attribute/attr-unquoted-ident.rs index 8a0c65b783a74..152448bf8a0f9 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.rs +++ b/tests/ui/parser/attribute/attr-unquoted-ident.rs @@ -4,14 +4,21 @@ fn main() { #[cfg(key=foo)] - //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - //~| HELP surround the identifier with quotation marks to make it into a string literal + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here println!(); #[cfg(key="bar")] println!(); #[cfg(key=foo bar baz)] - //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - //~| HELP surround the identifier with quotation marks to make it into a string literal + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here + println!(); + #[cfg(key=foo 1 bar 2.0 baz.)] + //~^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found + //~| HELP: surround the identifier with quotation marks to make it into a string literal + //~| NOTE: expressions are not allowed here println!(); } @@ -19,7 +26,7 @@ fn main() { macro_rules! make { ($name:ident) => { #[doc(alias = $name)] pub struct S; } - //~^ ERROR expected unsuffixed literal, found identifier `nickname` + //~^ ERROR: expected unsuffixed literal, found identifier `nickname` } -make!(nickname); //~ NOTE in this expansion +make!(nickname); //~ NOTE: in this expansion diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr index 8a2785280adc3..f1af60dec9bbb 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.stderr +++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr @@ -1,27 +1,38 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/attr-unquoted-ident.rs:6:15 | LL | #[cfg(key=foo)] - | ^^^ + | ^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | LL | #[cfg(key="foo")] | + + -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `foo` - --> $DIR/attr-unquoted-ident.rs:12:15 +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/attr-unquoted-ident.rs:13:15 | LL | #[cfg(key=foo bar baz)] - | ^^^ + | ^^^ expressions are not allowed here | help: surround the identifier with quotation marks to make it into a string literal | LL | #[cfg(key="foo bar baz")] | + + +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/attr-unquoted-ident.rs:18:15 + | +LL | #[cfg(key=foo 1 bar 2.0 baz.)] + | ^^^ expressions are not allowed here + | +help: surround the identifier with quotation marks to make it into a string literal + | +LL | #[cfg(key="foo 1 bar 2.0 baz.")] + | + + + error: expected unsuffixed literal, found identifier `nickname` - --> $DIR/attr-unquoted-ident.rs:21:38 + --> $DIR/attr-unquoted-ident.rs:28:38 | LL | ($name:ident) => { #[doc(alias = $name)] pub struct S; } | ^^^^^ @@ -31,5 +42,5 @@ LL | make!(nickname); | = note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/parser/macro/expr-in-attribute.rs b/tests/ui/parser/macro/expr-in-attribute.rs new file mode 100644 index 0000000000000..8c8934493361b --- /dev/null +++ b/tests/ui/parser/macro/expr-in-attribute.rs @@ -0,0 +1,9 @@ +// Test for #146325. +// Ensure that when we encounter an expr invocation in an attribute, we don't suggest nonsense. + +#[deprecated(note = a!=b)] +struct X; +//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression +//~| NOTE: expressions are not allowed here + +fn main() {} diff --git a/tests/ui/parser/macro/expr-in-attribute.stderr b/tests/ui/parser/macro/expr-in-attribute.stderr new file mode 100644 index 0000000000000..08d6f12d1e641 --- /dev/null +++ b/tests/ui/parser/macro/expr-in-attribute.stderr @@ -0,0 +1,8 @@ +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression + --> $DIR/expr-in-attribute.rs:4:21 + | +LL | #[deprecated(note = a!=b)] + | ^^^^ expressions are not allowed here + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/macro/macro-in-attribute.rs b/tests/ui/parser/macro/macro-in-attribute.rs index 57808c6fd27da..efb7de9f01c4f 100644 --- a/tests/ui/parser/macro/macro-in-attribute.rs +++ b/tests/ui/parser/macro/macro-in-attribute.rs @@ -3,7 +3,7 @@ #[deprecated(note = concat!("a", "b"))] struct X; -//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` +//~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found //~| NOTE: macros are not allowed here fn main() {} diff --git a/tests/ui/parser/macro/macro-in-attribute.stderr b/tests/ui/parser/macro/macro-in-attribute.stderr index e0ae51365a85c..08fb664407574 100644 --- a/tests/ui/parser/macro/macro-in-attribute.stderr +++ b/tests/ui/parser/macro/macro-in-attribute.stderr @@ -1,4 +1,4 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro `concat` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro --> $DIR/macro-in-attribute.rs:4:21 | LL | #[deprecated(note = concat!("a", "b"))] From c1500f986f2a814378714b5a7939f4d43350c121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 3 Nov 2025 19:21:31 +0000 Subject: [PATCH 13/16] review comment --- compiler/rustc_ast/src/ast.rs | 2 +- tests/ui/parser/macro/macro-in-attribute.rs | 2 +- tests/ui/parser/macro/macro-in-attribute.stderr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index b696ebeba992c..78da2fa9163ca 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1267,7 +1267,7 @@ impl StmtKind { StmtKind::Expr(_) => "expression", StmtKind::Semi(_) => "statement", StmtKind::Empty => "semicolon", - StmtKind::MacCall(_) => "macro", + StmtKind::MacCall(_) => "macro call", } } } diff --git a/tests/ui/parser/macro/macro-in-attribute.rs b/tests/ui/parser/macro/macro-in-attribute.rs index efb7de9f01c4f..7a4b3b22baa91 100644 --- a/tests/ui/parser/macro/macro-in-attribute.rs +++ b/tests/ui/parser/macro/macro-in-attribute.rs @@ -4,6 +4,6 @@ #[deprecated(note = concat!("a", "b"))] struct X; //~^^ ERROR: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found -//~| NOTE: macros are not allowed here +//~| NOTE: macro calls are not allowed here fn main() {} diff --git a/tests/ui/parser/macro/macro-in-attribute.stderr b/tests/ui/parser/macro/macro-in-attribute.stderr index 08fb664407574..d057c93ede073 100644 --- a/tests/ui/parser/macro/macro-in-attribute.stderr +++ b/tests/ui/parser/macro/macro-in-attribute.stderr @@ -1,8 +1,8 @@ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found macro call --> $DIR/macro-in-attribute.rs:4:21 | LL | #[deprecated(note = concat!("a", "b"))] - | ^^^^^^^^^^^^^^^^^ macros are not allowed here + | ^^^^^^^^^^^^^^^^^ macro calls are not allowed here error: aborting due to 1 previous error From 761cb57aef119745ed8eab68f03508a1e5950d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 9 Dec 2025 01:20:58 +0000 Subject: [PATCH 14/16] fix test --- tests/ui/macros/cfg_select.rs | 2 +- tests/ui/macros/cfg_select.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 2a627cc05b93b..586e4037d7c1f 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -68,7 +68,7 @@ cfg_select! { cfg_select! { () => {} - //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `(` + //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression } cfg_select! { diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 3a5d2b0a1e1ee..a14e243346610 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -27,11 +27,11 @@ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `=>` LL | => {} | ^^ -error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `(` +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/cfg_select.rs:70:5 | LL | () => {} - | ^ + | ^^ expressions are not allowed here error[E0539]: malformed `cfg_select` macro input --> $DIR/cfg_select.rs:75:5 From 75df299225d56977ebacca0400c4fcaa3b316726 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 9 Dec 2025 11:30:03 +0100 Subject: [PATCH 15/16] Mirror `ubuntu:24.04` on ghcr --- .github/workflows/ghcr.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml index a89867efe666b..ddb3b2ce0dd58 100644 --- a/.github/workflows/ghcr.yml +++ b/.github/workflows/ghcr.yml @@ -55,6 +55,8 @@ jobs: images=( # Mirrored because used by the tidy job, which doesn't cache Docker images "ubuntu:22.04" + # Mirrored because used by x86-64-gnu-miri + "ubuntu:24.04" # Mirrored because used by all linux CI jobs, including tidy "moby/buildkit:buildx-stable-1" # Mirrored because used when CI is running inside a Docker container From 2a2da782d32f25d69b66880b5dca640e2be8fe3e Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Thu, 4 Dec 2025 21:53:11 +0000 Subject: [PATCH 16/16] add check for uninhabited types along side never --- compiler/rustc_mir_build/src/builder/mod.rs | 21 ++++++++++++++++++- .../uninhabited-unreachable-warning-149571.rs | 10 +++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/ui/uninhabited/uninhabited-unreachable-warning-149571.rs diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 206eb9126f54b..14a24265a8f4b 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -839,6 +839,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.infcx.typing_env(self.param_env), ); + // check if the function's return type is inhabited + // this was added here because of this regression + // https://github.com/rust-lang/rust/issues/149571 + let output_is_inhabited = + if matches!(self.tcx.def_kind(self.def_id), DefKind::Fn | DefKind::AssocFn) { + self.tcx + .fn_sig(self.def_id) + .instantiate_identity() + .skip_binder() + .output() + .is_inhabited_from( + self.tcx, + self.parent_module, + self.infcx.typing_env(self.param_env), + ) + } else { + true + }; + if !ty_is_inhabited { // Unreachable code warnings are already emitted during type checking. // However, during type checking, full type information is being @@ -849,7 +868,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // uninhabited types (e.g. empty enums). The check above is used so // that we do not emit the same warning twice if the uninhabited type // is indeed `!`. - if !ty.is_never() { + if !ty.is_never() && output_is_inhabited { lints.push((target_bb, ty, term.source_info.span)); } diff --git a/tests/ui/uninhabited/uninhabited-unreachable-warning-149571.rs b/tests/ui/uninhabited/uninhabited-unreachable-warning-149571.rs new file mode 100644 index 0000000000000..a389562d649e3 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-unreachable-warning-149571.rs @@ -0,0 +1,10 @@ +#![deny(unreachable_code)] +//@ run-pass + +use std::convert::Infallible; + +pub fn foo(f: impl FnOnce() -> Infallible) -> Infallible { + f() +} + +fn main() {}