Error on unsafe on non-unsafe attribute
This commit is contained in:
parent
48851d9adb
commit
230b58febf
@ -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();
|
||||
|
@ -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};
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
6
tests/ui/attributes/unsafe/unsafe-safe-attribute.rs
Normal file
6
tests/ui/attributes/unsafe/unsafe-safe-attribute.rs
Normal file
@ -0,0 +1,6 @@
|
||||
#![feature(unsafe_attributes)]
|
||||
|
||||
#[unsafe(repr(C))] //~ ERROR: is not an unsafe attribute
|
||||
struct Foo {}
|
||||
|
||||
fn main() {}
|
10
tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr
Normal file
10
tests/ui/attributes/unsafe/unsafe-safe-attribute.stderr
Normal 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
|
||||
|
@ -0,0 +1,8 @@
|
||||
#![feature(unsafe_attributes)]
|
||||
|
||||
#[unsafe(diagnostic::on_unimplemented( //~ ERROR: is not an unsafe attribute
|
||||
message = "testing",
|
||||
))]
|
||||
trait Foo {}
|
||||
|
||||
fn main() {}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user