Error on unsafe on non-unsafe attribute

This commit is contained in:
carbotaniuman 2024-05-15 18:52:08 -05:00
parent 48851d9adb
commit 230b58febf
9 changed files with 75 additions and 4 deletions

View file

@ -1146,6 +1146,10 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool {
})
}
pub fn is_unsafe_attr(name: Symbol) -> bool {
BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.safety == AttributeSafety::Unsafe)
}
pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
LazyLock::new(|| {
let mut map = FxHashMap::default();

View file

@ -123,8 +123,8 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
pub use builtin_attrs::AttributeDuplicates;
pub use builtin_attrs::{
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute,
GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType,
BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
};
pub use removed::REMOVED_FEATURES;
pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_FEATURES};

View file

@ -384,6 +384,10 @@ passes_invalid_attr_at_crate_level =
passes_invalid_attr_at_crate_level_item =
the inner attribute doesn't annotate this {$kind}
passes_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
.suggestion = remove the `unsafe(...)`
.note = extraneous unsafe is not allowed in attributes
passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments

View file

@ -10,7 +10,9 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::StashKey;
use rustc_errors::{Applicability, DiagCtxt, IntoDiagArg, MultiSpan};
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_feature::{
is_unsafe_attr, AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP,
};
use rustc_hir::def_id::LocalModDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir};
@ -114,6 +116,8 @@ fn check_attributes(
let mut seen = FxHashMap::default();
let attrs = self.tcx.hir().attrs(hir_id);
for attr in attrs {
self.check_unsafe_attr(attr);
match attr.path().as_slice() {
[sym::diagnostic, sym::do_not_recommend] => {
self.check_do_not_recommend(attr.span, hir_id, target)
@ -308,6 +312,22 @@ fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target)
true
}
/// Checks if `unsafe()` is applied to an invalid attribute.
fn check_unsafe_attr(&self, attr: &Attribute) {
if !attr.is_doc_comment() {
let attr_item = attr.get_normal_item();
if let ast::Unsafe::Yes(unsafe_span) = attr_item.unsafety {
if !is_unsafe_attr(attr.name_or_empty()) {
self.dcx().emit_err(errors::InvalidAttrUnsafe {
span: unsafe_span,
name: attr_item.path.clone(),
});
}
}
}
}
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
fn check_diagnostic_on_unimplemented(
&self,

View file

@ -4,7 +4,7 @@
};
use crate::fluent_generated as fluent;
use rustc_ast::Label;
use rustc_ast::{ast, Label};
use rustc_errors::{
codes::*, Applicability, Diag, DiagCtxt, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
MultiSpan, SubdiagMessageOp, Subdiagnostic,
@ -863,6 +863,15 @@ pub struct InvalidAttrAtCrateLevel {
pub item: Option<ItemFollowingInnerAttr>,
}
#[derive(Diagnostic)]
#[diag(passes_invalid_attr_unsafe)]
#[note]
pub struct InvalidAttrUnsafe {
#[primary_span]
pub span: Span,
pub name: ast::Path,
}
#[derive(Clone, Copy)]
pub struct ItemFollowingInnerAttr {
pub span: Span,

View file

@ -0,0 +1,6 @@
#![feature(unsafe_attributes)]
#[unsafe(repr(C))] //~ ERROR: is not an unsafe attribute
struct Foo {}
fn main() {}

View file

@ -0,0 +1,10 @@
error: `repr` is not an unsafe attribute
--> $DIR/unsafe-safe-attribute.rs:3:3
|
LL | #[unsafe(repr(C))]
| ^^^^^^
|
= note: extraneous unsafe is not allowed in attributes
error: aborting due to 1 previous error

View file

@ -0,0 +1,8 @@
#![feature(unsafe_attributes)]
#[unsafe(diagnostic::on_unimplemented( //~ ERROR: is not an unsafe attribute
message = "testing",
))]
trait Foo {}
fn main() {}

View file

@ -0,0 +1,10 @@
error: `diagnostic::on_unimplemented` is not an unsafe attribute
--> $DIR/unsafe-safe-attribute_diagnostic.rs:3:3
|
LL | #[unsafe(diagnostic::on_unimplemented(
| ^^^^^^
|
= note: extraneous unsafe is not allowed in attributes
error: aborting due to 1 previous error