From b82f09a48d45dd8cbb8a313d26a94858766f0001 Mon Sep 17 00:00:00 2001 From: Sanidhya Singh Date: Wed, 3 Jun 2026 12:09:35 +0530 Subject: [PATCH 1/7] Document error conditions for Command::{spawn, output, status} These methods return `io::Result` but did not document why they can fail or, importantly, that a child terminated by a signal is reported through its `ExitStatus` rather than as an `Err`. Add `# Errors` sections describing the common reasons spawning a child can fail (program not found, missing permission, resource exhaustion) and clarifying that a running child which exits unsuccessfully or is killed by a signal is not an error: those methods still return `Ok` and the outcome is reflected in the resulting `ExitStatus`. --- library/std/src/process.rs | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 0b8db439a6370..990cb0eb8c7e4 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1070,6 +1070,26 @@ impl Command { /// /// By default, stdin, stdout and stderr are inherited from the parent. /// + /// # Errors + /// + /// This method returns an [`io::Error`] if the child process could not be + /// spawned. Common reasons include: + /// + /// * the program could not be found (for example, it does not exist, or, + /// when given a bare name, it is not present in the `PATH`); + /// * the current process does not have permission to execute the program + /// (for example, the file is not marked executable, or execution is + /// denied by a security policy such as `seccomp`); + /// * the operating system could not create the new process because of + /// resource exhaustion (for example, a limit on the number of processes + /// was reached). + /// + /// An error is only returned for failures that occur while the child is + /// being spawned. Once the child has started successfully, anything that + /// happens to it afterwards — including being terminated by a signal — is + /// reported through its [`ExitStatus`] rather than as an error from the + /// spawning method. + /// /// # Examples /// /// ```no_run @@ -1092,6 +1112,20 @@ impl Command { /// attempt by the child process to read from the stdin stream will result /// in the stream immediately closing. /// + /// # Errors + /// + /// Like [`spawn`], this method returns an [`io::Error`] if the child + /// process could not be spawned; see [`spawn`] for the common reasons. It + /// may also return an error if reading the child's output or waiting on the + /// child fails. + /// + /// Note that this method does **not** return an error if the child runs and + /// then exits unsuccessfully, or is terminated by a signal. In those cases + /// it still returns [`Ok`], and the outcome is reflected in the + /// [`ExitStatus`] stored in the returned [`Output`]. + /// + /// [`spawn`]: Command::spawn + /// /// # Examples /// /// ```should_panic @@ -1119,6 +1153,19 @@ impl Command { /// /// By default, stdin, stdout and stderr are inherited from the parent. /// + /// # Errors + /// + /// Like [`spawn`], this method returns an [`io::Error`] if the child + /// process could not be spawned; see [`spawn`] for the common reasons. It + /// may also return an error if waiting on the child fails. + /// + /// Note that this method does **not** return an error if the child runs and + /// then exits unsuccessfully, or is terminated by a signal. In those cases + /// it still returns [`Ok`], and the outcome is reflected in the returned + /// [`ExitStatus`]. + /// + /// [`spawn`]: Command::spawn + /// /// # Examples /// /// ```should_panic From bdb15892919043d7171c3f7619640007f7eac635 Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Sat, 30 May 2026 09:31:44 +0800 Subject: [PATCH 2/7] fix armv7a-none-eabihf tier doc --- src/doc/rustc/src/platform-support/arm-none-eabi.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 5d22cef92d220..4a6c4783f6d7b 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -12,7 +12,7 @@ their own document. ### Tier 2 Target List - Arm A-Profile Architectures - - [`armv7a-none-eabi`](armv7a-none-eabi.md) + - [`armv7a-none-eabi` and `armv7a-none-eabihf`](armv7a-none-eabi.md) - [`thumbv7a-none-eabi` and `thumbv7a-none-eabihf`](armv7a-none-eabi.md) - Arm R-Profile Architectures - [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md) @@ -32,7 +32,7 @@ their own document. ### Tier 3 Target List - Arm A-Profile Architectures - - [`armv7a-none-eabihf`](armv7a-none-eabi.md) + - None - Arm R-Profile Architectures - None - Arm M-Profile Architectures From 316f09f6b8012237022922e3566a39bdd6bdd64c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 4 Jun 2026 09:46:09 +0200 Subject: [PATCH 3/7] std tests: avoid duplicating thread-local machinery --- library/std/src/lib.rs | 1 + library/std/src/thread/mod.rs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 09d81f11e0a45..9f5200dab80df 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -383,6 +383,7 @@ #![feature(str_internals)] #![feature(sync_unsafe_cell)] #![feature(temporary_niche_types)] +#![feature(thread_local_internals)] #![feature(ub_checks)] #![feature(uint_carryless_mul)] #![feature(used_with_arg)] diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 00aeb70e6e076..6e052a34069fe 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -199,6 +199,7 @@ pub use id::ThreadId; pub use join_handle::JoinHandle; pub(crate) use lifecycle::ThreadInit; #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(test))] // we use the realstd types instead, see below pub use local::{AccessError, LocalKey}; #[stable(feature = "scoped_threads", since = "1.63.0")] pub use scoped::{Scope, ScopedJoinHandle, scope}; @@ -210,10 +211,18 @@ pub use thread::Thread; // Implementation details used by the thread_local!{} macro. #[doc(hidden)] #[unstable(feature = "thread_local_internals", issue = "none")] +#[cfg(not(test))] // we use the realstd types instead, see below pub mod local_impl { pub use super::local::thread_local_process_attrs; pub use crate::sys::thread_local::*; } +// Under cfg(test), avoid having two instances of the thread-local machinery. +// Things too easily get mixed up and then we end up with memory leaks because we're not calling +// all the right dtors. +#[cfg(test)] +pub use realstd::thread::local_impl; +#[cfg(test)] +pub use realstd::thread::{AccessError, LocalKey}; /// A specialized [`Result`] type for threads. /// From 3bdd720f57ae5a1e60f36ddc3bad5b99d9db8dc8 Mon Sep 17 00:00:00 2001 From: Kjetil Kjeka Date: Thu, 4 Jun 2026 10:27:46 +0200 Subject: [PATCH 4/7] NVPTX: Add @kulst to the target maintainers --- src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md index 02510d9f3dee2..5c74e7b95d9ab 100644 --- a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md +++ b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md @@ -8,6 +8,7 @@ platform. ## Target maintainers [@kjetilkjeka](https://github.com/kjetilkjeka) +[@kulst](https://github.com/kulst) ## Requirements From 7ed4c9df4a7598b0fb4d0cf4a2216406ef985ae9 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 4 Jun 2026 21:39:52 +0200 Subject: [PATCH 5/7] Make distinction between crate-level attributes that are warned vs errored --- .../src/attributes/crate_level.rs | 60 ++++++++++++------- .../src/attributes/link_attrs.rs | 6 +- .../src/attributes/rustc_dump.rs | 6 +- .../src/attributes/rustc_internal.rs | 3 +- .../src/attributes/stability.rs | 3 +- .../src/attributes/test_attrs.rs | 6 +- compiler/rustc_attr_parsing/src/errors.rs | 1 + .../rustc_attr_parsing/src/target_checking.rs | 35 ++++++----- 8 files changed, 77 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index d6d9b761a1e76..4ae66c1f56fc9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -13,7 +13,8 @@ impl SingleAttributeParser for CrateNameParser { const PATH: &[Symbol] = &[sym::crate_name]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -31,7 +32,8 @@ impl CombineAttributeParser for CrateTypeParser { const PATH: &[Symbol] = &[sym::crate_type]; type Item = CrateType; const CONVERT: ConvertFn = |items, _| AttributeKind::CrateType(items); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html"); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -74,7 +76,8 @@ impl SingleAttributeParser for RecursionLimitParser { const PATH: &[Symbol] = &[sym::recursion_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -89,7 +92,8 @@ pub(crate) struct MoveSizeLimitParser; impl SingleAttributeParser for MoveSizeLimitParser { const PATH: &[Symbol] = &[sym::move_size_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(large_assignments); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -105,7 +109,8 @@ impl SingleAttributeParser for TypeLengthLimitParser { const PATH: &[Symbol] = &[sym::type_length_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -120,7 +125,8 @@ pub(crate) struct PatternComplexityLimitParser; impl SingleAttributeParser for PatternComplexityLimitParser { const PATH: &[Symbol] = &[sym::pattern_complexity_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!( rustc_attrs, "the `#[pattern_complexity_limit]` attribute is used for rustc unit tests" @@ -137,7 +143,8 @@ pub(crate) struct NoCoreParser; impl NoArgsAttributeParser for NoCoreParser { const PATH: &[Symbol] = &[sym::no_core]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(no_core); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoCore; } @@ -147,7 +154,8 @@ pub(crate) struct NoStdParser; impl NoArgsAttributeParser for NoStdParser { const PATH: &[Symbol] = &[sym::no_std]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoStd; } @@ -157,7 +165,8 @@ pub(crate) struct NoMainParser; impl NoArgsAttributeParser for NoMainParser { const PATH: &[Symbol] = &[sym::no_main]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain; } @@ -166,7 +175,8 @@ pub(crate) struct RustcCoherenceIsCoreParser; impl NoArgsAttributeParser for RustcCoherenceIsCoreParser { const PATH: &[Symbol] = &[sym::rustc_coherence_is_core]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoherenceIsCore; } @@ -176,7 +186,8 @@ pub(crate) struct WindowsSubsystemParser; impl SingleAttributeParser for WindowsSubsystemParser { const PATH: &[Symbol] = &[sym::windows_subsystem]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -203,7 +214,8 @@ pub(crate) struct PanicRuntimeParser; impl NoArgsAttributeParser for PanicRuntimeParser { const PATH: &[Symbol] = &[sym::panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime; } @@ -212,7 +224,8 @@ pub(crate) struct NeedsPanicRuntimeParser; impl NoArgsAttributeParser for NeedsPanicRuntimeParser { const PATH: &[Symbol] = &[sym::needs_panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(needs_panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; } @@ -221,7 +234,8 @@ pub(crate) struct ProfilerRuntimeParser; impl NoArgsAttributeParser for ProfilerRuntimeParser { const PATH: &[Symbol] = &[sym::profiler_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(profiler_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; } @@ -231,7 +245,8 @@ pub(crate) struct NoBuiltinsParser; impl NoArgsAttributeParser for NoBuiltinsParser { const PATH: &[Symbol] = &[sym::no_builtins]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; } @@ -240,7 +255,8 @@ pub(crate) struct RustcPreserveUbChecksParser; impl NoArgsAttributeParser for RustcPreserveUbChecksParser { const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; } @@ -249,7 +265,8 @@ pub(crate) struct RustcNoImplicitBoundsParser; impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; } @@ -258,7 +275,8 @@ pub(crate) struct DefaultLibAllocatorParser; impl NoArgsAttributeParser for DefaultLibAllocatorParser { const PATH: &[Symbol] = &[sym::default_lib_allocator]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator; } @@ -269,7 +287,8 @@ impl CombineAttributeParser for FeatureParser { const PATH: &[Symbol] = &[sym::feature]; type Item = Ident; const CONVERT: ConvertFn = AttributeKind::Feature; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["feature1, feature2, ..."]); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -314,7 +333,8 @@ impl CombineAttributeParser for RegisterToolParser { const PATH: &[Symbol] = &[sym::register_tool]; type Item = Ident; const CONVERT: ConvertFn = |tools, _span| AttributeKind::RegisterTool(tools); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]); const STABILITY: AttributeStability = unstable!(register_tool); diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index bc500ddd48acf..0fb63a8cb5722 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -688,7 +688,8 @@ pub(crate) struct NeedsAllocatorParser; impl NoArgsAttributeParser for NeedsAllocatorParser { const PATH: &[Symbol] = &[sym::needs_allocator]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; } @@ -697,7 +698,8 @@ pub(crate) struct CompilerBuiltinsParser; impl NoArgsAttributeParser for CompilerBuiltinsParser { const PATH: &[Symbol] = &[sym::compiler_builtins]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(compiler_builtins); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CompilerBuiltins; } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index a80a46e90ac0c..7d4c93b5b7020 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -49,7 +49,8 @@ pub(crate) struct RustcDumpHiddenTypeOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpHiddenTypeOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_hidden_type_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpHiddenTypeOfOpaques; } @@ -242,7 +243,8 @@ pub(crate) struct RustcDumpVariancesOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpVariancesOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques; } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 6e1060ea05ae9..95397c7118552 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -370,7 +370,8 @@ pub(crate) struct RustcNeverTypeOptionsParser; impl SingleAttributeParser for RustcNeverTypeOptionsParser { const PATH: &[Symbol] = &[sym::rustc_never_type_options]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[ r#"fallback = "unit", "never", "no""#, r#"diverging_block_default = "unit", "never""#, diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index b38bb6d535770..3d3a5e7f1816b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -460,7 +460,8 @@ pub(crate) struct UnstableRemovedParser; impl CombineAttributeParser for UnstableRemovedParser { type Item = UnstableRemovedFeature; const PATH: &[Symbol] = &[sym::unstable_removed]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[r#"feature = "name", reason = "...", link = "...", since = "version""#]); const STABILITY: AttributeStability = unstable!(staged_api); diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 00e113f171715..70a2aac26aee5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -83,7 +83,8 @@ pub(crate) struct ReexportTestHarnessMainParser; impl SingleAttributeParser for ReexportTestHarnessMainParser { const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); @@ -174,7 +175,8 @@ pub(crate) struct TestRunnerParser; impl SingleAttributeParser for TestRunnerParser { const PATH: &[Symbol] = &[sym::test_runner]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["path"]); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index 5f898295d5afa..0a03e82754f00 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -148,6 +148,7 @@ pub(crate) struct InvalidAttrStyle { pub crate_root_path: String, #[help("the crate root is at `{$crate_root_path}`")] pub show_crate_root_help: bool, + pub span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 483a3d6a1329b..87b0eb9504e0e 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -114,7 +114,11 @@ impl<'sess> AttributeParser<'sess> { // For crate-level attributes we emit a specific set of lints to warn // people about accidentally not using them on the crate. if let &AllowedTargets::AllowList(&[Allow(Target::Crate)]) = allowed_targets { - Self::check_crate_level(cx); + Self::check_crate_level(cx, false); + return; + } + if let &AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]) = allowed_targets { + Self::check_crate_level(cx, true); return; } @@ -181,7 +185,7 @@ impl<'sess> AttributeParser<'sess> { } } - pub(crate) fn check_crate_level(cx: &mut AcceptContext<'_, 'sess>) { + pub(crate) fn check_crate_level(cx: &mut AcceptContext<'_, 'sess>, warn: bool) { if cx.target == Target::Crate { return; } @@ -205,19 +209,20 @@ impl<'sess> AttributeParser<'sess> { }) .unwrap_or_default(); - let target = cx.target; - cx.emit_lint( - rustc_session::lint::builtin::UNUSED_ATTRIBUTES, - crate::errors::InvalidAttrStyle { - name, - is_used_as_inner, - target_span: (!is_used_as_inner).then_some(target_span), - target: target.name(), - crate_root_path, - show_crate_root_help, - }, - attr_span, - ); + let diag = crate::errors::InvalidAttrStyle { + name, + is_used_as_inner, + target_span: (!is_used_as_inner).then_some(target_span), + target: cx.target.name(), + crate_root_path, + show_crate_root_help, + span: attr_span, + }; + if warn { + cx.emit_lint(rustc_session::lint::builtin::UNUSED_ATTRIBUTES, diag, attr_span); + } else { + cx.emit_err(diag); + } } // FIXME: Fix "Cannot determine resolution" error and remove built-in macros From 73c631d5ae6a753f70a88612b61daa7ff8ff2fdb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 4 Jun 2026 21:52:07 +0200 Subject: [PATCH 6/7] Make all unstable crate-level attributes on incorrect targets an error --- .../src/attributes/crate_level.rs | 33 +++++++------------ .../src/attributes/link_attrs.rs | 6 ++-- .../src/attributes/rustc_dump.rs | 6 ++-- .../src/attributes/rustc_internal.rs | 3 +- .../src/attributes/stability.rs | 3 +- .../src/attributes/test_attrs.rs | 6 ++-- compiler/rustc_attr_parsing/src/errors.rs | 1 + tests/ui/attributes/attr-on-mac-call.rs | 2 +- tests/ui/attributes/attr-on-mac-call.stderr | 26 +++++++-------- tests/ui/attributes/malformed-no-std.stderr | 24 +++++++------- tests/ui/attributes/register-tool-target.rs | 3 +- .../ui/attributes/register-tool-target.stderr | 9 +++-- 12 files changed, 51 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 4ae66c1f56fc9..502b2740d21be 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -92,8 +92,7 @@ pub(crate) struct MoveSizeLimitParser; impl SingleAttributeParser for MoveSizeLimitParser { const PATH: &[Symbol] = &[sym::move_size_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(large_assignments); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -125,8 +124,7 @@ pub(crate) struct PatternComplexityLimitParser; impl SingleAttributeParser for PatternComplexityLimitParser { const PATH: &[Symbol] = &[sym::pattern_complexity_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!( rustc_attrs, "the `#[pattern_complexity_limit]` attribute is used for rustc unit tests" @@ -143,8 +141,7 @@ pub(crate) struct NoCoreParser; impl NoArgsAttributeParser for NoCoreParser { const PATH: &[Symbol] = &[sym::no_core]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(no_core); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoCore; } @@ -175,8 +172,7 @@ pub(crate) struct RustcCoherenceIsCoreParser; impl NoArgsAttributeParser for RustcCoherenceIsCoreParser { const PATH: &[Symbol] = &[sym::rustc_coherence_is_core]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoherenceIsCore; } @@ -214,8 +210,7 @@ pub(crate) struct PanicRuntimeParser; impl NoArgsAttributeParser for PanicRuntimeParser { const PATH: &[Symbol] = &[sym::panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime; } @@ -224,8 +219,7 @@ pub(crate) struct NeedsPanicRuntimeParser; impl NoArgsAttributeParser for NeedsPanicRuntimeParser { const PATH: &[Symbol] = &[sym::needs_panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(needs_panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; } @@ -234,8 +228,7 @@ pub(crate) struct ProfilerRuntimeParser; impl NoArgsAttributeParser for ProfilerRuntimeParser { const PATH: &[Symbol] = &[sym::profiler_runtime]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(profiler_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; } @@ -255,8 +248,7 @@ pub(crate) struct RustcPreserveUbChecksParser; impl NoArgsAttributeParser for RustcPreserveUbChecksParser { const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; } @@ -265,8 +257,7 @@ pub(crate) struct RustcNoImplicitBoundsParser; impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; } @@ -275,8 +266,7 @@ pub(crate) struct DefaultLibAllocatorParser; impl NoArgsAttributeParser for DefaultLibAllocatorParser { const PATH: &[Symbol] = &[sym::default_lib_allocator]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator; } @@ -333,8 +323,7 @@ impl CombineAttributeParser for RegisterToolParser { const PATH: &[Symbol] = &[sym::register_tool]; type Item = Ident; const CONVERT: ConvertFn = |tools, _span| AttributeKind::RegisterTool(tools); - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]); const STABILITY: AttributeStability = unstable!(register_tool); diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 0fb63a8cb5722..bc500ddd48acf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -688,8 +688,7 @@ pub(crate) struct NeedsAllocatorParser; impl NoArgsAttributeParser for NeedsAllocatorParser { const PATH: &[Symbol] = &[sym::needs_allocator]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; } @@ -698,8 +697,7 @@ pub(crate) struct CompilerBuiltinsParser; impl NoArgsAttributeParser for CompilerBuiltinsParser { const PATH: &[Symbol] = &[sym::compiler_builtins]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(compiler_builtins); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CompilerBuiltins; } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index 7d4c93b5b7020..a80a46e90ac0c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -49,8 +49,7 @@ pub(crate) struct RustcDumpHiddenTypeOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpHiddenTypeOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_hidden_type_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpHiddenTypeOfOpaques; } @@ -243,8 +242,7 @@ pub(crate) struct RustcDumpVariancesOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpVariancesOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques; } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 95397c7118552..6e1060ea05ae9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -370,8 +370,7 @@ pub(crate) struct RustcNeverTypeOptionsParser; impl SingleAttributeParser for RustcNeverTypeOptionsParser { const PATH: &[Symbol] = &[sym::rustc_never_type_options]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[ r#"fallback = "unit", "never", "no""#, r#"diverging_block_default = "unit", "never""#, diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 3d3a5e7f1816b..b38bb6d535770 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -460,8 +460,7 @@ pub(crate) struct UnstableRemovedParser; impl CombineAttributeParser for UnstableRemovedParser { type Item = UnstableRemovedFeature; const PATH: &[Symbol] = &[sym::unstable_removed]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[r#"feature = "name", reason = "...", link = "...", since = "version""#]); const STABILITY: AttributeStability = unstable!(staged_api); diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 70a2aac26aee5..00e113f171715 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -83,8 +83,7 @@ pub(crate) struct ReexportTestHarnessMainParser; impl SingleAttributeParser for ReexportTestHarnessMainParser { const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); @@ -175,8 +174,7 @@ pub(crate) struct TestRunnerParser; impl SingleAttributeParser for TestRunnerParser { const PATH: &[Symbol] = &[sym::test_runner]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["path"]); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index 0a03e82754f00..ae5dc7b0d4dc2 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -148,6 +148,7 @@ pub(crate) struct InvalidAttrStyle { pub crate_root_path: String, #[help("the crate root is at `{$crate_root_path}`")] pub show_crate_root_help: bool, + #[primary_span] pub span: Span, } diff --git a/tests/ui/attributes/attr-on-mac-call.rs b/tests/ui/attributes/attr-on-mac-call.rs index 2875ff0c74e6d..1fdc2a6ed3562 100644 --- a/tests/ui/attributes/attr-on-mac-call.rs +++ b/tests/ui/attributes/attr-on-mac-call.rs @@ -108,6 +108,6 @@ fn main() { //~| WARN previously accepted unreachable!(); #[register_tool(xyz)] - //~^ WARN crate-level attribute should be an inner attribute + //~^ ERROR crate-level attribute should be an inner attribute unreachable!(); } diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr index 8d19137da4457..9c042b301241a 100644 --- a/tests/ui/attributes/attr-on-mac-call.stderr +++ b/tests/ui/attributes/attr-on-mac-call.stderr @@ -6,6 +6,18 @@ LL | #[sanitize(address = "off")] | = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![register_tool]` + --> $DIR/attr-on-mac-call.rs:110:5 + | +LL | #[register_tool(xyz)] + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this macro call + --> $DIR/attr-on-mac-call.rs:112:5 + | +LL | unreachable!(); + | ^^^^^^^^^^^^^^ + warning: `#[export_name]` attribute cannot be used on macro calls --> $DIR/attr-on-mac-call.rs:8:5 | @@ -289,17 +301,5 @@ LL | #[repr(simd)] = help: `#[repr(simd)]` can only be applied to structs = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![register_tool]` - --> $DIR/attr-on-mac-call.rs:110:5 - | -LL | #[register_tool(xyz)] - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: this attribute does not have an `!`, which means it is applied to this macro call - --> $DIR/attr-on-mac-call.rs:112:5 - | -LL | unreachable!(); - | ^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error; 32 warnings emitted +error: aborting due to 2 previous errors; 31 warnings emitted diff --git a/tests/ui/attributes/malformed-no-std.stderr b/tests/ui/attributes/malformed-no-std.stderr index 07963e6256648..a965b7e235b36 100644 --- a/tests/ui/attributes/malformed-no-std.stderr +++ b/tests/ui/attributes/malformed-no-std.stderr @@ -106,6 +106,18 @@ note: attribute also specified here LL | #![no_core = "foo"] | ^^^^^^^^^^^^^^^^^^^ +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_core]` + --> $DIR/malformed-no-std.rs:23:1 + | +LL | #[no_core] + | ^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this extern crate + --> $DIR/malformed-no-std.rs:26:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ + error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` --> $DIR/malformed-no-std.rs:21:1 | @@ -123,18 +135,6 @@ note: the lint level is defined here LL | #[deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_core]` - --> $DIR/malformed-no-std.rs:23:1 - | -LL | #[no_core] - | ^^^^^^^^^^ - | -note: this attribute does not have an `!`, which means it is applied to this extern crate - --> $DIR/malformed-no-std.rs:26:1 - | -LL | extern crate core; - | ^^^^^^^^^^^^^^^^^^ - warning: unused attribute --> $DIR/malformed-no-std.rs:5:1 | diff --git a/tests/ui/attributes/register-tool-target.rs b/tests/ui/attributes/register-tool-target.rs index a92b946c95f2d..8498e7fa0f15c 100644 --- a/tests/ui/attributes/register-tool-target.rs +++ b/tests/ui/attributes/register-tool-target.rs @@ -1,8 +1,7 @@ -//@ check-pass #![feature(register_tool)] #[register_tool(no_valid_target)] -//~^ WARN crate-level attribute should be an inner attribute +//~^ ERROR crate-level attribute should be an inner attribute fn main() { } diff --git a/tests/ui/attributes/register-tool-target.stderr b/tests/ui/attributes/register-tool-target.stderr index 4808ee49ee6a4..bf865c29c9965 100644 --- a/tests/ui/attributes/register-tool-target.stderr +++ b/tests/ui/attributes/register-tool-target.stderr @@ -1,17 +1,16 @@ -warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![register_tool]` - --> $DIR/register-tool-target.rs:4:1 +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![register_tool]` + --> $DIR/register-tool-target.rs:3:1 | LL | #[register_tool(no_valid_target)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/register-tool-target.rs:6:1 + --> $DIR/register-tool-target.rs:5:1 | LL | / fn main() { LL | | LL | | } | |_^ - = note: requested on the command line with `-W unused-attributes` -warning: 1 warning emitted +error: aborting due to 1 previous error From 00b8189a187f353752039b72c10edd0ce2e038f9 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Thu, 4 Jun 2026 21:42:10 +0000 Subject: [PATCH 7/7] Suppress --- .../nice_region_error/named_anon_conflict.rs | 21 ++++++++++++++++- .../infer/nice_region_error/util.rs | 11 ++++++++- compiler/rustc_trait_selection/src/errors.rs | 14 +++++++++-- ...t-ref-aliases-pointee-lifetime-distinct.rs | 10 ++++++++ ...f-aliases-pointee-lifetime-distinct.stderr | 14 +++++++++++ .../e0621-mut-ref-aliases-pointee-lifetime.rs | 23 +++++++++++++++++++ ...21-mut-ref-aliases-pointee-lifetime.stderr | 19 +++++++++++++++ 7 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs index 73a04d78519c8..ad8cc5d279af1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs @@ -2,6 +2,7 @@ //! where one region is named and the other is anonymous. use rustc_errors::Diag; +use rustc_middle::ty; use tracing::debug; use crate::error_reporting::infer::nice_region_error::NiceRegionError; @@ -72,7 +73,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { return None; } + let orig_ty = anon_param_info.orig_param_ty; + // Don't suggest naming the outer lifetime when it already appears in the pointee + // (e.g. `&'a mut Buffer<'a>`); point at borrow splitting instead. + let suggestion_would_alias_lifetime = + if let ty::Ref(_, orig_inner_ty, ty::Mutability::Mut) = orig_ty.kind() { + self.tcx().any_free_region_meets(orig_inner_ty, |r| r == named) + } else { + false + }; + let named = named.to_string(); + let new_ty_span = if suggestion_would_alias_lifetime { None } else { Some(new_ty_span) }; let err = match param.pat.simple_ident() { Some(simple_ident) => ExplicitLifetimeRequired::WithIdent { span, @@ -80,8 +92,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { named, new_ty_span, new_ty, + link_nomicon: suggestion_would_alias_lifetime, + }, + None => ExplicitLifetimeRequired::WithParamType { + span, + named, + new_ty_span, + new_ty, + link_nomicon: suggestion_would_alias_lifetime, }, - None => ExplicitLifetimeRequired::WithParamType { span, named, new_ty_span, new_ty }, }; Some(self.tcx().sess.dcx().create_err(err)) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 3ec97ce76ef07..50eeb3a243266 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -16,6 +16,8 @@ pub struct AnonymousParamInfo<'tcx> { pub param: &'tcx hir::Param<'tcx>, /// The type corresponding to the anonymous region parameter. pub param_ty: Ty<'tcx>, + /// The original type before region replacement. + pub orig_param_ty: Ty<'tcx>, /// The `ty::LateParamRegionKind` corresponding to the anonymous region. pub kind: ty::LateParamRegionKind, /// The `Span` of the parameter type. @@ -94,7 +96,14 @@ pub fn find_param_with_region<'tcx>( let ty_hir_id = fn_decl.inputs[index].hir_id; let param_ty_span = tcx.hir_span(ty_hir_id); let is_first = index == 0; - AnonymousParamInfo { param, param_ty: new_param_ty, param_ty_span, kind, is_first } + AnonymousParamInfo { + param, + param_ty: new_param_ty, + orig_param_ty: ty, + param_ty_span, + kind, + is_first, + } }) }) } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 5a926dc46c707..662480587fdd2 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -868,8 +868,13 @@ pub(crate) enum ExplicitLifetimeRequired<'a> { applicability = "unspecified", style = "verbose" )] - new_ty_span: Span, + new_ty_span: Option, new_ty: Ty<'a>, + #[help( + "see \ + for more information about lifetime errors related to mutable references" + )] + link_nomicon: bool, }, #[diag("explicit lifetime required in parameter type", code = E0621)] WithParamType { @@ -883,8 +888,13 @@ pub(crate) enum ExplicitLifetimeRequired<'a> { applicability = "unspecified", style = "verbose" )] - new_ty_span: Span, + new_ty_span: Option, new_ty: Ty<'a>, + #[help( + "see \ + for more information about lifetime errors related to mutable references" + )] + link_nomicon: bool, }, } diff --git a/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs new file mode 100644 index 0000000000000..a6995df36567c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs @@ -0,0 +1,10 @@ +// Regression test for #156682 +// When the suggested type would NOT alias the outer reference's lifetime with one +// already used inside the pointee, the normal suggestion should still apply. + +pub fn push<'a>(x: &mut Vec<&'a u8>, y: &u8) { + x.push(y); + //~^ ERROR explicit lifetime required in the type of `y` +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.stderr b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.stderr new file mode 100644 index 0000000000000..fdc087aa4d979 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.stderr @@ -0,0 +1,14 @@ +error[E0621]: explicit lifetime required in the type of `y` + --> $DIR/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs:6:5 + | +LL | x.push(y); + | ^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `y` + | +LL | pub fn push<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { + | ++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.rs b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.rs new file mode 100644 index 0000000000000..5b78d566bf98c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.rs @@ -0,0 +1,23 @@ +// Regression test for #156682 +// E0621 should not suggest `&'a mut Buffer<'a>`, which would alias the outer +// reference's lifetime with one already used inside the pointee. + +pub struct Buffer<'a> { + buf: &'a mut [u8], +} + +pub fn foo<'a>(buffer: &mut Buffer<'a>) { + buffer.buf = &mut buffer.buf[..]; + //~^ ERROR explicit lifetime required in the type of `buffer` +} + +pub struct Wrapper<'a> { + inner: Buffer<'a>, +} + +pub fn baz<'a>(wrapper: &mut Wrapper<'a>) { + wrapper.inner.buf = &mut wrapper.inner.buf[..]; + //~^ ERROR explicit lifetime required in the type of `wrapper` +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.stderr b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.stderr new file mode 100644 index 0000000000000..488c96061a3e9 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.stderr @@ -0,0 +1,19 @@ +error[E0621]: explicit lifetime required in the type of `buffer` + --> $DIR/e0621-mut-ref-aliases-pointee-lifetime.rs:10:5 + | +LL | buffer.buf = &mut buffer.buf[..]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | + = help: see for more information about lifetime errors related to mutable references + +error[E0621]: explicit lifetime required in the type of `wrapper` + --> $DIR/e0621-mut-ref-aliases-pointee-lifetime.rs:19:5 + | +LL | wrapper.inner.buf = &mut wrapper.inner.buf[..]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | + = help: see for more information about lifetime errors related to mutable references + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0621`.