Skip to content

Commit 230b58f

Browse files
committed
Error on unsafe on non-unsafe attribute
1 parent 48851d9 commit 230b58f

File tree

9 files changed

+75
-4
lines changed

9 files changed

+75
-4
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

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

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

compiler/rustc_feature/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ 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_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute,
127-
GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
126+
is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType,
127+
BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
128128
};
129129
pub use removed::REMOVED_FEATURES;
130130
pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_FEATURES};

compiler/rustc_passes/messages.ftl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,10 @@ 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+
387391
passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
388392
389393
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: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ 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::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
13+
use rustc_feature::{
14+
is_unsafe_attr, AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP,
15+
};
1416
use rustc_hir::def_id::LocalModDefId;
1517
use rustc_hir::intravisit::{self, Visitor};
1618
use rustc_hir::{self as hir};
@@ -114,6 +116,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
114116
let mut seen = FxHashMap::default();
115117
let attrs = self.tcx.hir().attrs(hir_id);
116118
for attr in attrs {
119+
self.check_unsafe_attr(attr);
120+
117121
match attr.path().as_slice() {
118122
[sym::diagnostic, sym::do_not_recommend] => {
119123
self.check_do_not_recommend(attr.span, hir_id, target)
@@ -308,6 +312,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
308312
true
309313
}
310314

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

compiler/rustc_passes/src/errors.rs

Lines changed: 10 additions & 1 deletion
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::Label;
7+
use rustc_ast::{ast, Label};
88
use rustc_errors::{
99
codes::*, Applicability, Diag, DiagCtxt, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
1010
MultiSpan, SubdiagMessageOp, Subdiagnostic,
@@ -863,6 +863,15 @@ 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+
866875
#[derive(Clone, Copy)]
867876
pub struct ItemFollowingInnerAttr {
868877
pub span: Span,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(unsafe_attributes)]
2+
3+
#[unsafe(repr(C))] //~ ERROR: is not an unsafe attribute
4+
struct Foo {}
5+
6+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: `repr` is not an unsafe attribute
2+
--> $DIR/unsafe-safe-attribute.rs:3:3
3+
|
4+
LL | #[unsafe(repr(C))]
5+
| ^^^^^^
6+
|
7+
= note: extraneous unsafe is not allowed in attributes
8+
9+
error: aborting due to 1 previous error
10+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(unsafe_attributes)]
2+
3+
#[unsafe(diagnostic::on_unimplemented( //~ ERROR: is not an unsafe attribute
4+
message = "testing",
5+
))]
6+
trait Foo {}
7+
8+
fn main() {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: `diagnostic::on_unimplemented` is not an unsafe attribute
2+
--> $DIR/unsafe-safe-attribute_diagnostic.rs:3:3
3+
|
4+
LL | #[unsafe(diagnostic::on_unimplemented(
5+
| ^^^^^^
6+
|
7+
= note: extraneous unsafe is not allowed in attributes
8+
9+
error: aborting due to 1 previous error
10+

0 commit comments

Comments
 (0)