mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +00:00
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>> =
|
pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
|
||||||
LazyLock::new(|| {
|
LazyLock::new(|| {
|
||||||
let mut map = FxHashMap::default();
|
let mut map = FxHashMap::default();
|
||||||
|
@ -123,8 +123,8 @@ pub use accepted::ACCEPTED_FEATURES;
|
|||||||
pub use builtin_attrs::AttributeDuplicates;
|
pub use builtin_attrs::AttributeDuplicates;
|
||||||
pub use builtin_attrs::{
|
pub use builtin_attrs::{
|
||||||
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
|
deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
|
||||||
is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute,
|
is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType,
|
||||||
GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
|
BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
|
||||||
};
|
};
|
||||||
pub use removed::REMOVED_FEATURES;
|
pub use removed::REMOVED_FEATURES;
|
||||||
pub use unstable::{Features, INCOMPATIBLE_FEATURES, UNSTABLE_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 =
|
passes_invalid_attr_at_crate_level_item =
|
||||||
the inner attribute doesn't annotate this {$kind}
|
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 = `{$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
|
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
|
||||||
|
@ -10,7 +10,9 @@ use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
|
|||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::StashKey;
|
use rustc_errors::StashKey;
|
||||||
use rustc_errors::{Applicability, DiagCtxt, IntoDiagArg, MultiSpan};
|
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::def_id::LocalModDefId;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{self as hir};
|
use rustc_hir::{self as hir};
|
||||||
@ -114,6 +116,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
let mut seen = FxHashMap::default();
|
let mut seen = FxHashMap::default();
|
||||||
let attrs = self.tcx.hir().attrs(hir_id);
|
let attrs = self.tcx.hir().attrs(hir_id);
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
|
self.check_unsafe_attr(attr);
|
||||||
|
|
||||||
match attr.path().as_slice() {
|
match attr.path().as_slice() {
|
||||||
[sym::diagnostic, sym::do_not_recommend] => {
|
[sym::diagnostic, sym::do_not_recommend] => {
|
||||||
self.check_do_not_recommend(attr.span, hir_id, target)
|
self.check_do_not_recommend(attr.span, hir_id, target)
|
||||||
@ -308,6 +312,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
true
|
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
|
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
|
||||||
fn check_diagnostic_on_unimplemented(
|
fn check_diagnostic_on_unimplemented(
|
||||||
&self,
|
&self,
|
||||||
|
@ -4,7 +4,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::fluent_generated as fluent;
|
use crate::fluent_generated as fluent;
|
||||||
use rustc_ast::Label;
|
use rustc_ast::{ast, Label};
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
codes::*, Applicability, Diag, DiagCtxt, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
|
codes::*, Applicability, Diag, DiagCtxt, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
|
||||||
MultiSpan, SubdiagMessageOp, Subdiagnostic,
|
MultiSpan, SubdiagMessageOp, Subdiagnostic,
|
||||||
@ -863,6 +863,15 @@ pub struct InvalidAttrAtCrateLevel {
|
|||||||
pub item: Option<ItemFollowingInnerAttr>,
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct ItemFollowingInnerAttr {
|
pub struct ItemFollowingInnerAttr {
|
||||||
pub span: Span,
|
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