Skip to content

Commit 7d1090b

Browse files
committed
Don't suggest wrapping attr in unsafe if it may come from proc macro
1 parent fbab541 commit 7d1090b

File tree

8 files changed

+111
-13
lines changed

8 files changed

+111
-13
lines changed

compiler/rustc_attr_parsing/src/safety.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::ops::Not;
2+
13
use rustc_ast::Safety;
24
use rustc_feature::{AttributeSafety, BUILTIN_ATTRIBUTE_MAP};
35
use rustc_hir::AttrPath;
@@ -62,16 +64,26 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
6264
Some(unsafe_since) => path_span.edition() >= unsafe_since,
6365
};
6466

67+
let may_from_proc_macro = if diag_span.from_expansion()
68+
&& let Ok(mut snippet) = self.sess.source_map().span_to_snippet(diag_span)
69+
{
70+
snippet.retain(|c| !c.is_whitespace());
71+
snippet.ends_with("!()") || snippet.starts_with("#[") && snippet.ends_with("]")
72+
} else {
73+
false
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: may_from_proc_macro.not().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,9 @@ 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: may_from_proc_macro
97+
.not()
98+
.then(|| (diag_span.shrink_to_lo(), diag_span.shrink_to_hi())),
8599
},
86100
})
87101
}

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
@@ -356,13 +356,13 @@ pub fn decorate_attribute_lint(
356356
}
357357
.decorate_lint(diag)
358358
}
359-
&AttributeLintKind::UnsafeAttrOutsideUnsafe {
360-
attribute_name_span,
361-
sugg_spans: (left, right),
362-
} => lints::UnsafeAttrOutsideUnsafeLint {
363-
span: attribute_name_span,
364-
suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right },
359+
&AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => {
360+
lints::UnsafeAttrOutsideUnsafeLint {
361+
span: attribute_name_span,
362+
suggestion: sugg_spans
363+
.map(|(left, right)| lints::UnsafeAttrOutsideUnsafeSuggestion { left, right }),
364+
}
365+
.decorate_lint(diag)
365366
}
366-
.decorate_lint(diag),
367367
}
368368
}

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
@@ -730,7 +730,7 @@ pub enum AttributeLintKind {
730730
},
731731
UnsafeAttrOutsideUnsafe {
732732
attribute_name_span: Span,
733-
sugg_spans: (Span, Span),
733+
sugg_spans: Option<(Span, Span)>,
734734
},
735735
}
736736

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)