Skip to content

Commit 50e9839

Browse files
committed
Don't suggest wrapping attr in unsafe if it may come from proc macro
1 parent d5525a7 commit 50e9839

File tree

8 files changed

+110
-13
lines changed

8 files changed

+110
-13
lines changed

compiler/rustc_attr_parsing/src/safety.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,28 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
6262
Some(unsafe_since) => path_span.edition() >= unsafe_since,
6363
};
6464

65+
let mut not_from_proc_macro = true;
66+
if diag_span.from_expansion()
67+
&& let Ok(mut snippet) = self.sess.source_map().span_to_snippet(diag_span)
68+
{
69+
snippet.retain(|c| !c.is_whitespace());
70+
if snippet.contains("!(") || snippet.starts_with("#[") && snippet.ends_with("]")
71+
{
72+
not_from_proc_macro = false;
73+
}
74+
}
75+
6576
if emit_error {
6677
self.stage.emit_err(
6778
self.sess,
6879
crate::session_diagnostics::UnsafeAttrOutsideUnsafe {
6980
span: path_span,
70-
suggestion:
81+
suggestion: not_from_proc_macro.then(|| {
7182
crate::session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion {
7283
left: diag_span.shrink_to_lo(),
7384
right: diag_span.shrink_to_hi(),
74-
},
85+
}
86+
}),
7587
},
7688
);
7789
} else {
@@ -81,7 +93,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
8193
span: path_span,
8294
kind: AttributeLintKind::UnsafeAttrOutsideUnsafe {
8395
attribute_name_span: path_span,
84-
sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
96+
sugg_spans: not_from_proc_macro
97+
.then(|| (diag_span.shrink_to_lo(), diag_span.shrink_to_hi())),
8598
},
8699
})
87100
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafe {
758758
#[label]
759759
pub span: Span,
760760
#[subdiagnostic]
761-
pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
761+
pub suggestion: Option<UnsafeAttrOutsideUnsafeSuggestion>,
762762
}
763763

764764
#[derive(Subdiagnostic)]

compiler/rustc_lint/src/early/diagnostics.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -353,14 +353,14 @@ pub fn decorate_attribute_lint(
353353
}
354354
.decorate_lint(diag)
355355
}
356-
&AttributeLintKind::UnsafeAttrOutsideUnsafe {
357-
attribute_name_span,
358-
sugg_spans: (left, right),
359-
} => lints::UnsafeAttrOutsideUnsafeLint {
360-
span: attribute_name_span,
361-
suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right },
356+
&AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => {
357+
lints::UnsafeAttrOutsideUnsafeLint {
358+
span: attribute_name_span,
359+
suggestion: sugg_spans
360+
.map(|(left, right)| lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }),
361+
}
362+
.decorate_lint(diag)
362363
}
363-
.decorate_lint(diag),
364364
&AttributeLintKind::UnexpectedCfgName(name, value) => {
365365
check_cfg::unexpected_cfg_name(sess, tcx, name, value).decorate_lint(diag)
366366
}

compiler/rustc_lint/src/lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3177,7 +3177,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafeLint {
31773177
#[label]
31783178
pub span: Span,
31793179
#[subdiagnostic]
3180-
pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
3180+
pub suggestion: Option<UnsafeAttrOutsideUnsafeSuggestion>,
31813181
}
31823182

31833183
#[derive(Subdiagnostic)]

compiler/rustc_lint_defs/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ pub enum AttributeLintKind {
729729
},
730730
UnsafeAttrOutsideUnsafe {
731731
attribute_name_span: Span,
732-
sugg_spans: (Span, Span),
732+
sugg_spans: Option<(Span, Span)>,
733733
},
734734
UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>),
735735
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ edition: 2024
2+
3+
extern crate proc_macro;
4+
5+
use proc_macro::TokenStream;
6+
7+
#[proc_macro]
8+
pub fn missing_unsafe(_input: TokenStream) -> TokenStream {
9+
"#[no_mangle] pub fn abc() {}".parse().unwrap()
10+
}
11+
12+
#[proc_macro_attribute]
13+
pub fn attr_missing_unsafe(_attr: TokenStream, _input: TokenStream) -> TokenStream {
14+
"#[no_mangle] pub fn bar() {}".parse().unwrap()
15+
}
16+
17+
#[proc_macro_derive(AttrMissingUnsafe)]
18+
pub fn derive_attr_missing_unsafe(_input: TokenStream) -> TokenStream {
19+
"#[no_mangle] pub fn baz() {}".parse().unwrap()
20+
}
21+
22+
#[proc_macro]
23+
pub fn macro_rules_missing_unsafe(_input: TokenStream) -> TokenStream {
24+
"macro_rules! make_fn {
25+
() => { #[no_mangle] pub fn foo() { } };
26+
}"
27+
.parse()
28+
.unwrap()
29+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Test for unsafe attributes generated by a proc-macro.
2+
3+
//@ proc-macro: unsafe-attributes-pm-in-2024.rs
4+
//@ ignore-backends: gcc
5+
6+
unsafe_attributes_pm_in_2024::missing_unsafe!(); //~ ERROR unsafe attribute used without unsafe
7+
8+
#[unsafe_attributes_pm_in_2024::attr_missing_unsafe] //~ ERROR unsafe attribute used without unsafe
9+
pub fn bar() {}
10+
11+
#[derive(unsafe_attributes_pm_in_2024::AttrMissingUnsafe)] //~ ERROR unsafe attribute used without unsafe
12+
struct Baz;
13+
14+
unsafe_attributes_pm_in_2024::macro_rules_missing_unsafe!(); //~ ERROR unsafe attribute used without unsafe
15+
16+
make_fn!();
17+
18+
fn main() {}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error: unsafe attribute used without unsafe
2+
--> $DIR/unsafe-attributes-from-pm-in-2024.rs:6:1
3+
|
4+
LL | unsafe_attributes_pm_in_2024::missing_unsafe!();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute
6+
|
7+
= 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)
8+
9+
error: unsafe attribute used without unsafe
10+
--> $DIR/unsafe-attributes-from-pm-in-2024.rs:8:1
11+
|
12+
LL | #[unsafe_attributes_pm_in_2024::attr_missing_unsafe]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute
14+
|
15+
= 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)
16+
17+
error: unsafe attribute used without unsafe
18+
--> $DIR/unsafe-attributes-from-pm-in-2024.rs:11:10
19+
|
20+
LL | #[derive(unsafe_attributes_pm_in_2024::AttrMissingUnsafe)]
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute
22+
|
23+
= 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)
24+
25+
error: unsafe attribute used without unsafe
26+
--> $DIR/unsafe-attributes-from-pm-in-2024.rs:14:1
27+
|
28+
LL | unsafe_attributes_pm_in_2024::macro_rules_missing_unsafe!();
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ usage of unsafe attribute
30+
LL |
31+
LL | make_fn!();
32+
| ---------- in this macro invocation
33+
|
34+
= note: this error originates in the macro `make_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
35+
36+
error: aborting due to 4 previous errors
37+

0 commit comments

Comments
 (0)