From 50e9839d4849d932810ebba52a664d39baed5253 Mon Sep 17 00:00:00 2001 From: mu001999 Date: Tue, 9 Dec 2025 00:31:56 +0800 Subject: [PATCH] Don't suggest wrapping attr in unsafe if it may come from proc macro --- compiler/rustc_attr_parsing/src/safety.rs | 19 ++++++++-- .../src/session_diagnostics.rs | 2 +- compiler/rustc_lint/src/early/diagnostics.rs | 14 +++---- compiler/rustc_lint/src/lints.rs | 2 +- compiler/rustc_lint_defs/src/lib.rs | 2 +- .../auxiliary/unsafe-attributes-pm-in-2024.rs | 29 +++++++++++++++ .../unsafe-attributes-from-pm-in-2024.rs | 18 +++++++++ .../unsafe-attributes-from-pm-in-2024.stderr | 37 +++++++++++++++++++ 8 files changed, 110 insertions(+), 13 deletions(-) create mode 100644 tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm-in-2024.rs create mode 100644 tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.rs create mode 100644 tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.stderr diff --git a/compiler/rustc_attr_parsing/src/safety.rs b/compiler/rustc_attr_parsing/src/safety.rs index 52baf2136173d..817785108a1ed 100644 --- a/compiler/rustc_attr_parsing/src/safety.rs +++ b/compiler/rustc_attr_parsing/src/safety.rs @@ -62,16 +62,28 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { Some(unsafe_since) => path_span.edition() >= unsafe_since, }; + let mut not_from_proc_macro = true; + if diag_span.from_expansion() + && let Ok(mut snippet) = self.sess.source_map().span_to_snippet(diag_span) + { + snippet.retain(|c| !c.is_whitespace()); + if snippet.contains("!(") || snippet.starts_with("#[") && snippet.ends_with("]") + { + not_from_proc_macro = false; + } + } + if emit_error { self.stage.emit_err( self.sess, crate::session_diagnostics::UnsafeAttrOutsideUnsafe { span: path_span, - suggestion: + suggestion: not_from_proc_macro.then(|| { crate::session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion { left: diag_span.shrink_to_lo(), right: diag_span.shrink_to_hi(), - }, + } + }), }, ); } else { @@ -81,7 +93,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { span: path_span, kind: AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span: path_span, - sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), + sugg_spans: not_from_proc_macro + .then(|| (diag_span.shrink_to_lo(), diag_span.shrink_to_hi())), }, }) } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index c4f6f9c6a38cb..cf3f3760d9629 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -758,7 +758,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafe { #[label] pub span: Span, #[subdiagnostic] - pub suggestion: UnsafeAttrOutsideUnsafeSuggestion, + pub suggestion: Option, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 589594a3ec5e6..c44e0ba67daac 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -353,14 +353,14 @@ pub fn decorate_attribute_lint( } .decorate_lint(diag) } - &AttributeLintKind::UnsafeAttrOutsideUnsafe { - attribute_name_span, - sugg_spans: (left, right), - } => lints::UnsafeAttrOutsideUnsafeLint { - span: attribute_name_span, - suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }, + &AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => { + lints::UnsafeAttrOutsideUnsafeLint { + span: attribute_name_span, + suggestion: sugg_spans + .map(|(left, right)| lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }), + } + .decorate_lint(diag) } - .decorate_lint(diag), &AttributeLintKind::UnexpectedCfgName(name, value) => { check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag) } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 1bec316ce45a7..20262c9c6bcf6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3177,7 +3177,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafeLint { #[label] pub span: Span, #[subdiagnostic] - pub suggestion: UnsafeAttrOutsideUnsafeSuggestion, + pub suggestion: Option, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 376310838cc74..bb153afecc4c6 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -729,7 +729,7 @@ pub enum AttributeLintKind { }, UnsafeAttrOutsideUnsafe { attribute_name_span: Span, - sugg_spans: (Span, Span), + sugg_spans: Option<(Span, Span)>, }, UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), diff --git a/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm-in-2024.rs b/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm-in-2024.rs new file mode 100644 index 0000000000000..5f44223df90cf --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/auxiliary/unsafe-attributes-pm-in-2024.rs @@ -0,0 +1,29 @@ +//@ edition: 2024 + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn missing_unsafe(_input: TokenStream) -> TokenStream { + "#[no_mangle] pub fn abc() {}".parse().unwrap() +} + +#[proc_macro_attribute] +pub fn attr_missing_unsafe(_attr: TokenStream, _input: TokenStream) -> TokenStream { + "#[no_mangle] pub fn bar() {}".parse().unwrap() +} + +#[proc_macro_derive(AttrMissingUnsafe)] +pub fn derive_attr_missing_unsafe(_input: TokenStream) -> TokenStream { + "#[no_mangle] pub fn baz() {}".parse().unwrap() +} + +#[proc_macro] +pub fn macro_rules_missing_unsafe(_input: TokenStream) -> TokenStream { + "macro_rules! make_fn { + () => { #[no_mangle] pub fn foo() { } }; + }" + .parse() + .unwrap() +} diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.rs new file mode 100644 index 0000000000000..dca05cc27f6e1 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.rs @@ -0,0 +1,18 @@ +// Test for unsafe attributes generated by a proc-macro. + +//@ proc-macro: unsafe-attributes-pm-in-2024.rs +//@ ignore-backends: gcc + +unsafe_attributes_pm_in_2024::missing_unsafe!(); //~ ERROR unsafe attribute used without unsafe + +#[unsafe_attributes_pm_in_2024::attr_missing_unsafe] //~ ERROR unsafe attribute used without unsafe +pub fn bar() {} + +#[derive(unsafe_attributes_pm_in_2024::AttrMissingUnsafe)] //~ ERROR unsafe attribute used without unsafe +struct Baz; + +unsafe_attributes_pm_in_2024::macro_rules_missing_unsafe!(); //~ ERROR unsafe attribute used without unsafe + +make_fn!(); + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.stderr new file mode 100644 index 0000000000000..fa36b148bf3de --- /dev/null +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.stderr @@ -0,0 +1,37 @@ +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-from-pm-in-2024.rs:6:1 + | +LL | unsafe_attributes_pm_in_2024::missing_unsafe!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute + | + = note: this error originates in the macro `unsafe_attributes_pm_in_2024::missing_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-from-pm-in-2024.rs:8:1 + | +LL | #[unsafe_attributes_pm_in_2024::attr_missing_unsafe] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute + | + = note: this error originates in the attribute macro `unsafe_attributes_pm_in_2024::attr_missing_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-from-pm-in-2024.rs:11:10 + | +LL | #[derive(unsafe_attributes_pm_in_2024::AttrMissingUnsafe)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute + | + = note: this error originates in the derive macro `unsafe_attributes_pm_in_2024::AttrMissingUnsafe` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-from-pm-in-2024.rs:14:1 + | +LL | unsafe_attributes_pm_in_2024::macro_rules_missing_unsafe!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute +LL | +LL | make_fn!(); + | ---------- in this macro invocation + | + = note: this error originates in the macro `make_fn` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors +