Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9d329c0

Browse files
committedJun 9, 2024
Add hard error and migration lint for unsafe attrs
1 parent 8fb1930 commit 9d329c0

22 files changed

+461
-50
lines changed
 

‎compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,10 +1145,6 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool {
11451145
})
11461146
}
11471147

1148-
pub fn is_unsafe_attr(name: Symbol) -> bool {
1149-
BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.safety == AttributeSafety::Unsafe)
1150-
}
1151-
11521148
pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
11531149
LazyLock::new(|| {
11541150
let mut map = FxHashMap::default();

‎compiler/rustc_feature/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ pub use accepted::ACCEPTED_FEATURES;
123123
pub use builtin_attrs::AttributeDuplicates;
124124
pub use builtin_attrs::{
125125
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
126-
is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType,
126+
is_valid_for_get_attr, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType,
127127
BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
128128
};
129129
pub use removed::REMOVED_FEATURES;

‎compiler/rustc_lint/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,10 @@ lint_unnameable_test_items = cannot test inner items
821821
lint_unnecessary_qualification = unnecessary qualification
822822
.suggestion = remove the unnecessary path segments
823823
824+
lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
825+
.label = usage of unsafe attribute
826+
lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
827+
824828
lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
825829
826830
lint_untranslatable_diag = diagnostics should be created using translatable messages

‎compiler/rustc_lint/src/context/diagnostics.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,16 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
319319
BuiltinLintDiag::UnusedQualifications { removal_span } => {
320320
lints::UnusedQualifications { removal_span }.decorate_lint(diag);
321321
}
322+
BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
323+
attribute_name_span,
324+
sugg_spans: (left, right),
325+
} => {
326+
lints::UnsafeAttrOutsideUnsafe {
327+
span: attribute_name_span,
328+
suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right },
329+
}
330+
.decorate_lint(diag);
331+
}
322332
BuiltinLintDiag::AssociatedConstElidedLifetime { elided, span: lt_span } => {
323333
let lt_span = if elided { lt_span.shrink_to_hi() } else { lt_span };
324334
let code = if elided { "'static " } else { "'static" };

‎compiler/rustc_lint/src/lints.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2874,3 +2874,24 @@ pub struct RedundantImportVisibility {
28742874
pub import_vis: String,
28752875
pub max_vis: String,
28762876
}
2877+
2878+
#[derive(LintDiagnostic)]
2879+
#[diag(lint_unsafe_attr_outside_unsafe)]
2880+
pub struct UnsafeAttrOutsideUnsafe {
2881+
#[label]
2882+
pub span: Span,
2883+
#[subdiagnostic]
2884+
pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
2885+
}
2886+
2887+
#[derive(Subdiagnostic)]
2888+
#[multipart_suggestion(
2889+
lint_unsafe_attr_outside_unsafe_suggestion,
2890+
applicability = "machine-applicable"
2891+
)]
2892+
pub struct UnsafeAttrOutsideUnsafeSuggestion {
2893+
#[suggestion_part(code = "unsafe(")]
2894+
pub left: Span,
2895+
#[suggestion_part(code = ")")]
2896+
pub right: Span,
2897+
}

‎compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ declare_lint_pass! {
114114
UNNAMEABLE_TYPES,
115115
UNREACHABLE_CODE,
116116
UNREACHABLE_PATTERNS,
117+
UNSAFE_ATTR_OUTSIDE_UNSAFE,
117118
UNSAFE_OP_IN_UNSAFE_FN,
118119
UNSTABLE_NAME_COLLISIONS,
119120
UNSTABLE_SYNTAX_PRE_EXPANSION,
@@ -4841,3 +4842,42 @@ declare_lint! {
48414842
reference: "issue #123743 <https://github.com/rust-lang/rust/issues/123743>",
48424843
};
48434844
}
4845+
4846+
declare_lint! {
4847+
/// The `unsafe_attr_outside_unsafe` lint detects a missing unsafe keyword
4848+
/// on attributes considered unsafe.
4849+
///
4850+
/// ### Example
4851+
///
4852+
/// ```rust
4853+
/// #![feature(unsafe_attributes)]
4854+
/// #![warn(unsafe_attr_outside_unsafe)]
4855+
///
4856+
/// #[no_mangle]
4857+
/// extern "C" fn foo() {}
4858+
///
4859+
/// fn main() {}
4860+
/// ```
4861+
///
4862+
/// {{produces}}
4863+
///
4864+
/// ### Explanation
4865+
///
4866+
/// Some attributes (e.g. no_mangle, export_name, link_section -- see here
4867+
/// for a more complete list)are considered "unsafe" attributes. An unsafe
4868+
/// attribute must only be used inside unsafe(...) in the attribute.
4869+
///
4870+
/// This lint can automatically wrap the attributes in `unsafe(...)` , but this
4871+
/// obviously cannot verify that the preconditions of the `unsafe`
4872+
/// attributes are fulfilled, so that is still up to the user.
4873+
///
4874+
/// The lint is currently "allow" by default, but that might change in the
4875+
/// future.
4876+
pub UNSAFE_ATTR_OUTSIDE_UNSAFE,
4877+
Allow,
4878+
"detects unsafe attributes outside of unsafe",
4879+
@future_incompatible = FutureIncompatibleInfo {
4880+
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
4881+
reference: "issue #123757 <https://github.com/rust-lang/rust/issues/123757>",
4882+
};
4883+
}

‎compiler/rustc_lint_defs/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,10 @@ pub enum BuiltinLintDiag {
691691
/// The span of the unnecessarily-qualified path to remove.
692692
removal_span: Span,
693693
},
694+
UnsafeAttrOutsideUnsafe {
695+
attribute_name_span: Span,
696+
sugg_spans: (Span, Span),
697+
},
694698
AssociatedConstElidedLifetime {
695699
elided: bool,
696700
span: Span,

‎compiler/rustc_parse/messages.ftl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,10 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment
364364
.label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
365365
.sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
366366
367+
parse_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
368+
.suggestion = remove the `unsafe(...)`
369+
.note = extraneous unsafe is not allowed in attributes
370+
367371
parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
368372
.label = the `block` fragment is within this context
369373
.suggestion = wrap this in another block
@@ -864,6 +868,11 @@ parse_unmatched_angle_brackets = {$num_extra_brackets ->
864868
*[other] remove extra angle brackets
865869
}
866870
871+
parse_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
872+
.label = usage of unsafe attribute
873+
parse_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
874+
875+
867876
parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
868877
.label = {parse_unskipped_whitespace}
869878

‎compiler/rustc_parse/src/errors.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2989,3 +2989,34 @@ pub(crate) struct ExprRArrowCall {
29892989
#[suggestion(style = "short", applicability = "machine-applicable", code = ".")]
29902990
pub span: Span,
29912991
}
2992+
2993+
#[derive(Diagnostic)]
2994+
#[diag(parse_invalid_attr_unsafe)]
2995+
#[note]
2996+
pub struct InvalidAttrUnsafe {
2997+
#[primary_span]
2998+
pub span: Span,
2999+
pub name: Path,
3000+
}
3001+
3002+
#[derive(Diagnostic)]
3003+
#[diag(parse_unsafe_attr_outside_unsafe)]
3004+
pub struct UnsafeAttrOutsideUnsafe {
3005+
#[primary_span]
3006+
#[label]
3007+
pub span: Span,
3008+
#[subdiagnostic]
3009+
pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
3010+
}
3011+
3012+
#[derive(Subdiagnostic)]
3013+
#[multipart_suggestion(
3014+
parse_unsafe_attr_outside_unsafe_suggestion,
3015+
applicability = "machine-applicable"
3016+
)]
3017+
pub struct UnsafeAttrOutsideUnsafeSuggestion {
3018+
#[suggestion_part(code = "unsafe(")]
3019+
pub left: Span,
3020+
#[suggestion_part(code = ")")]
3021+
pub right: Span,
3022+
}

‎compiler/rustc_parse/src/validate_attr.rs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,68 @@ use crate::{errors, parse_in};
55
use rustc_ast::token::Delimiter;
66
use rustc_ast::tokenstream::DelimSpan;
77
use rustc_ast::MetaItemKind;
8-
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem};
8+
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety};
99
use rustc_errors::{Applicability, FatalError, PResult};
10-
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
10+
use rustc_feature::{AttributeSafety, AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
1111
use rustc_session::errors::report_lit_error;
12-
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
12+
use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE};
1313
use rustc_session::lint::BuiltinLintDiag;
1414
use rustc_session::parse::ParseSess;
15-
use rustc_span::{sym, Span, Symbol};
15+
use rustc_span::{sym, BytePos, Span, Symbol};
1616

1717
pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
1818
if attr.is_doc_comment() {
1919
return;
2020
}
2121

2222
let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
23+
let attr_item = attr.get_normal_item();
24+
25+
let is_unsafe_attr =
26+
attr_info.map(|attr| attr.safety == AttributeSafety::Unsafe).unwrap_or(false);
27+
28+
if is_unsafe_attr {
29+
if let ast::Safety::Default = attr_item.unsafety {
30+
let path_span = attr_item.path.span;
31+
32+
// If the `attr_item`'s span is not from a macro, then just suggest
33+
// wrapping it in `unsafe(...)`. Otherwise, we suggest putting the
34+
// `unsafe(`, `)` right after and right before the opening and closing
35+
// square bracket respectively.
36+
let diag_span = if attr_item.span().can_be_used_for_suggestions() {
37+
attr_item.span()
38+
} else {
39+
attr.span.with_lo(attr.span.lo() + BytePos(2)).with_hi(attr.span.hi() - BytePos(1))
40+
};
41+
42+
if attr.span.at_least_rust_2024() {
43+
psess.dcx.emit_err(errors::UnsafeAttrOutsideUnsafe {
44+
span: path_span,
45+
suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion {
46+
left: diag_span.shrink_to_lo(),
47+
right: diag_span.shrink_to_hi(),
48+
},
49+
});
50+
} else {
51+
psess.buffer_lint(
52+
UNSAFE_ATTR_OUTSIDE_UNSAFE,
53+
path_span,
54+
ast::CRATE_NODE_ID,
55+
BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
56+
attribute_name_span: path_span,
57+
sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
58+
},
59+
);
60+
}
61+
}
62+
} else {
63+
if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
64+
psess.dcx.emit_err(errors::InvalidAttrUnsafe {
65+
span: unsafe_span,
66+
name: attr_item.path.clone(),
67+
});
68+
}
69+
}
2370

2471
// Check input tokens for built-in and key-value attributes.
2572
match attr_info {
@@ -32,7 +79,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
3279
}
3380
}
3481
}
35-
_ if let AttrArgs::Eq(..) = attr.get_normal_item().args => {
82+
_ if let AttrArgs::Eq(..) = attr_item.args => {
3683
// All key-value attributes are restricted to meta-item syntax.
3784
match parse_meta(psess, attr) {
3885
Ok(_) => {}

‎compiler/rustc_passes/messages.ftl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,10 +384,6 @@ passes_invalid_attr_at_crate_level =
384384
passes_invalid_attr_at_crate_level_item =
385385
the inner attribute doesn't annotate this {$kind}
386386
387-
passes_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
388-
.suggestion = remove the `unsafe(...)`
389-
.note = extraneous unsafe is not allowed in attributes
390-
391387
passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
392388
393389
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments

‎compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
1010
use rustc_data_structures::fx::FxHashMap;
1111
use rustc_errors::StashKey;
1212
use rustc_errors::{Applicability, DiagCtxt, IntoDiagArg, MultiSpan};
13-
use rustc_feature::{
14-
is_unsafe_attr, AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP,
15-
};
13+
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
1614
use rustc_hir::def_id::LocalModDefId;
1715
use rustc_hir::intravisit::{self, Visitor};
1816
use rustc_hir::{self as hir};
@@ -116,8 +114,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
116114
let mut seen = FxHashMap::default();
117115
let attrs = self.tcx.hir().attrs(hir_id);
118116
for attr in attrs {
119-
self.check_unsafe_attr(attr);
120-
121117
match attr.path().as_slice() {
122118
[sym::diagnostic, sym::do_not_recommend] => {
123119
self.check_do_not_recommend(attr.span, hir_id, target)
@@ -312,21 +308,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
312308
true
313309
}
314310

315-
/// Checks if `unsafe()` is applied to an invalid attribute.
316-
fn check_unsafe_attr(&self, attr: &Attribute) {
317-
if !attr.is_doc_comment() {
318-
let attr_item = attr.get_normal_item();
319-
if let ast::Safety::Unsafe(unsafe_span) = attr_item.unsafety {
320-
if !is_unsafe_attr(attr.name_or_empty()) {
321-
self.dcx().emit_err(errors::InvalidAttrUnsafe {
322-
span: unsafe_span,
323-
name: attr_item.path.clone(),
324-
});
325-
}
326-
}
327-
}
328-
}
329-
330311
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
331312
fn check_diagnostic_on_unimplemented(
332313
&self,

‎compiler/rustc_passes/src/errors.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::{
44
};
55

66
use crate::fluent_generated as fluent;
7-
use rustc_ast::{ast, Label};
7+
use rustc_ast::Label;
88
use rustc_errors::{
99
codes::*, Applicability, Diag, DiagCtxt, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
1010
MultiSpan, SubdiagMessageOp, Subdiagnostic,
@@ -863,15 +863,6 @@ pub struct InvalidAttrAtCrateLevel {
863863
pub item: Option<ItemFollowingInnerAttr>,
864864
}
865865

866-
#[derive(Diagnostic)]
867-
#[diag(passes_invalid_attr_unsafe)]
868-
#[note]
869-
pub struct InvalidAttrUnsafe {
870-
#[primary_span]
871-
pub span: Span,
872-
pub name: ast::Path,
873-
}
874-
875866
#[derive(Clone, Copy)]
876867
pub struct ItemFollowingInnerAttr {
877868
pub span: Span,

‎tests/ui/attributes/unsafe/double-unsafe-attributes.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@ help: escape `unsafe` to use it as an identifier
99
LL | #[unsafe(r#unsafe(no_mangle))]
1010
| ++
1111

12-
error: cannot find attribute `r#unsafe` in this scope
13-
--> $DIR/double-unsafe-attributes.rs:3:10
14-
|
15-
LL | #[unsafe(unsafe(no_mangle))]
16-
| ^^^^^^
17-
1812
error: `r#unsafe` is not an unsafe attribute
1913
--> $DIR/double-unsafe-attributes.rs:3:3
2014
|
@@ -23,5 +17,11 @@ LL | #[unsafe(unsafe(no_mangle))]
2317
|
2418
= note: extraneous unsafe is not allowed in attributes
2519

20+
error: cannot find attribute `r#unsafe` in this scope
21+
--> $DIR/double-unsafe-attributes.rs:3:10
22+
|
23+
LL | #[unsafe(unsafe(no_mangle))]
24+
| ^^^^^^
25+
2626
error: aborting due to 3 previous errors
2727

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![deny(rust_2024_compatibility)]
2+
3+
#[no_mangle]
4+
//~^ ERROR: unsafe attribute used without unsafe
5+
//~| WARN this is accepted in the current edition
6+
extern "C" fn foo() {}
7+
8+
fn main() {}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error: unsafe attribute used without unsafe
2+
--> $DIR/in_2024_compatibility.rs:3:3
3+
|
4+
LL | #[no_mangle]
5+
| ^^^^^^^^^ usage of unsafe attribute
6+
|
7+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
8+
= note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
9+
note: the lint level is defined here
10+
--> $DIR/in_2024_compatibility.rs:1:9
11+
|
12+
LL | #![deny(rust_2024_compatibility)]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^
14+
= note: `#[deny(unsafe_attr_outside_unsafe)]` implied by `#[deny(rust_2024_compatibility)]`
15+
help: wrap the attribute in `unsafe(...)`
16+
|
17+
LL | #[unsafe(no_mangle)]
18+
| +++++++ +
19+
20+
error: aborting due to 1 previous error
21+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@ revisions: edition2021 edition2024
2+
//@[edition2021] edition:2021
3+
//@[edition2024] edition:2024
4+
//@[edition2024] compile-flags: -Zunstable-options
5+
//@ check-pass
6+
7+
#![feature(unsafe_attributes)]
8+
9+
#[unsafe(no_mangle)]
10+
extern "C" fn foo() {}
11+
12+
fn main() {}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//@ run-rustfix
2+
#![feature(unsafe_attributes)]
3+
#![deny(unsafe_attr_outside_unsafe)]
4+
5+
macro_rules! tt {
6+
($e:tt) => {
7+
#$e
8+
extern fn foo() {}
9+
}
10+
}
11+
12+
macro_rules! ident {
13+
($e:ident) => {
14+
#[unsafe($e)]
15+
//~^ ERROR: unsafe attribute used without unsafe
16+
//~| WARN this is accepted in the current edition
17+
extern fn bar() {}
18+
}
19+
}
20+
21+
macro_rules! ident2 {
22+
($e:ident, $l:literal) => {
23+
#[unsafe($e = $l)]
24+
//~^ ERROR: unsafe attribute used without unsafe
25+
//~| WARN this is accepted in the current edition
26+
extern fn bars() {}
27+
}
28+
}
29+
30+
macro_rules! meta {
31+
($m:meta) => {
32+
#[$m]
33+
extern fn baz() {}
34+
}
35+
}
36+
37+
macro_rules! meta2 {
38+
($m:meta) => {
39+
#[$m]
40+
extern fn baw() {}
41+
}
42+
}
43+
44+
tt!([unsafe(no_mangle)]);
45+
//~^ ERROR: unsafe attribute used without unsafe
46+
//~| WARN this is accepted in the current edition
47+
ident!(no_mangle);
48+
meta!(unsafe(no_mangle));
49+
//~^ ERROR: unsafe attribute used without unsafe
50+
//~| WARN this is accepted in the current edition
51+
meta2!(unsafe(export_name = "baw"));
52+
//~^ ERROR: unsafe attribute used without unsafe
53+
//~| WARN this is accepted in the current edition
54+
ident2!(export_name, "bars");
55+
56+
#[unsafe(no_mangle)]
57+
//~^ ERROR: unsafe attribute used without unsafe
58+
//~| WARN this is accepted in the current edition
59+
extern "C" fn one() {}
60+
61+
fn main() {}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//@ run-rustfix
2+
#![feature(unsafe_attributes)]
3+
#![deny(unsafe_attr_outside_unsafe)]
4+
5+
macro_rules! tt {
6+
($e:tt) => {
7+
#$e
8+
extern fn foo() {}
9+
}
10+
}
11+
12+
macro_rules! ident {
13+
($e:ident) => {
14+
#[$e]
15+
//~^ ERROR: unsafe attribute used without unsafe
16+
//~| WARN this is accepted in the current edition
17+
extern fn bar() {}
18+
}
19+
}
20+
21+
macro_rules! ident2 {
22+
($e:ident, $l:literal) => {
23+
#[$e = $l]
24+
//~^ ERROR: unsafe attribute used without unsafe
25+
//~| WARN this is accepted in the current edition
26+
extern fn bars() {}
27+
}
28+
}
29+
30+
macro_rules! meta {
31+
($m:meta) => {
32+
#[$m]
33+
extern fn baz() {}
34+
}
35+
}
36+
37+
macro_rules! meta2 {
38+
($m:meta) => {
39+
#[$m]
40+
extern fn baw() {}
41+
}
42+
}
43+
44+
tt!([no_mangle]);
45+
//~^ ERROR: unsafe attribute used without unsafe
46+
//~| WARN this is accepted in the current edition
47+
ident!(no_mangle);
48+
meta!(no_mangle);
49+
//~^ ERROR: unsafe attribute used without unsafe
50+
//~| WARN this is accepted in the current edition
51+
meta2!(export_name = "baw");
52+
//~^ ERROR: unsafe attribute used without unsafe
53+
//~| WARN this is accepted in the current edition
54+
ident2!(export_name, "bars");
55+
56+
#[no_mangle]
57+
//~^ ERROR: unsafe attribute used without unsafe
58+
//~| WARN this is accepted in the current edition
59+
extern "C" fn one() {}
60+
61+
fn main() {}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
error: unsafe attribute used without unsafe
2+
--> $DIR/unsafe-attributes-fix.rs:44:6
3+
|
4+
LL | tt!([no_mangle]);
5+
| ^^^^^^^^^ usage of unsafe attribute
6+
|
7+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
8+
= note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
9+
note: the lint level is defined here
10+
--> $DIR/unsafe-attributes-fix.rs:3:9
11+
|
12+
LL | #![deny(unsafe_attr_outside_unsafe)]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
help: wrap the attribute in `unsafe(...)`
15+
|
16+
LL | tt!([unsafe(no_mangle)]);
17+
| +++++++ +
18+
19+
error: unsafe attribute used without unsafe
20+
--> $DIR/unsafe-attributes-fix.rs:14:11
21+
|
22+
LL | #[$e]
23+
| ^^ usage of unsafe attribute
24+
...
25+
LL | ident!(no_mangle);
26+
| ----------------- in this macro invocation
27+
|
28+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
29+
= note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
30+
= note: this error originates in the macro `ident` (in Nightly builds, run with -Z macro-backtrace for more info)
31+
help: wrap the attribute in `unsafe(...)`
32+
|
33+
LL | #[unsafe($e)]
34+
| +++++++ +
35+
36+
error: unsafe attribute used without unsafe
37+
--> $DIR/unsafe-attributes-fix.rs:48:7
38+
|
39+
LL | meta!(no_mangle);
40+
| ^^^^^^^^^ usage of unsafe attribute
41+
|
42+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
43+
= note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
44+
help: wrap the attribute in `unsafe(...)`
45+
|
46+
LL | meta!(unsafe(no_mangle));
47+
| +++++++ +
48+
49+
error: unsafe attribute used without unsafe
50+
--> $DIR/unsafe-attributes-fix.rs:51:8
51+
|
52+
LL | meta2!(export_name = "baw");
53+
| ^^^^^^^^^^^ usage of unsafe attribute
54+
|
55+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
56+
= note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
57+
help: wrap the attribute in `unsafe(...)`
58+
|
59+
LL | meta2!(unsafe(export_name = "baw"));
60+
| +++++++ +
61+
62+
error: unsafe attribute used without unsafe
63+
--> $DIR/unsafe-attributes-fix.rs:23:11
64+
|
65+
LL | #[$e = $l]
66+
| ^^ usage of unsafe attribute
67+
...
68+
LL | ident2!(export_name, "bars");
69+
| ---------------------------- in this macro invocation
70+
|
71+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
72+
= note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
73+
= note: this error originates in the macro `ident2` (in Nightly builds, run with -Z macro-backtrace for more info)
74+
help: wrap the attribute in `unsafe(...)`
75+
|
76+
LL | #[unsafe($e = $l)]
77+
| +++++++ +
78+
79+
error: unsafe attribute used without unsafe
80+
--> $DIR/unsafe-attributes-fix.rs:56:3
81+
|
82+
LL | #[no_mangle]
83+
| ^^^^^^^^^ usage of unsafe attribute
84+
|
85+
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
86+
= note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
87+
help: wrap the attribute in `unsafe(...)`
88+
|
89+
LL | #[unsafe(no_mangle)]
90+
| +++++++ +
91+
92+
error: aborting due to 6 previous errors
93+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error: unsafe attribute used without unsafe
2+
--> $DIR/unsafe-attributes.rs:9:3
3+
|
4+
LL | #[no_mangle]
5+
| ^^^^^^^^^ usage of unsafe attribute
6+
|
7+
help: wrap the attribute in `unsafe(...)`
8+
|
9+
LL | #[unsafe(no_mangle)]
10+
| +++++++ +
11+
12+
error: aborting due to 1 previous error
13+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@ revisions: edition2021 edition2024
2+
//@[edition2021] edition:2021
3+
//@[edition2021] check-pass
4+
//@[edition2024] edition:2024
5+
//@[edition2024] compile-flags: -Zunstable-options
6+
7+
#![feature(unsafe_attributes)]
8+
9+
#[no_mangle] //[edition2024]~ ERROR: unsafe attribute used without unsafe
10+
extern "C" fn foo() {}
11+
12+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.