diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0fbb288cc968c..04f377b5af177 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -870,7 +870,7 @@ fn validate_generic_param_order( impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - validate_attr::check_attr(&self.session.psess, attr); + validate_attr::check_attr(&self.features, &self.session.psess, attr); } fn visit_ty(&mut self, ty: &'a Ty) { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index c28a09eb57c77..2fe6b269aa3a6 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1796,7 +1796,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let mut span: Option = None; while let Some(attr) = attrs.next() { rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features); - validate_attr::check_attr(&self.cx.sess.psess, attr); + validate_attr::check_attr(features, &self.cx.sess.psess, attr); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; span = Some(current_span); diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 06059555cef86..02ca75cca85ec 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -7,14 +7,16 @@ use rustc_ast::tokenstream::DelimSpan; use rustc_ast::MetaItemKind; use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety}; use rustc_errors::{Applicability, FatalError, PResult}; -use rustc_feature::{AttributeSafety, AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; +use rustc_feature::{ + AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP, +}; use rustc_session::errors::report_lit_error; use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::ParseSess; use rustc_span::{sym, BytePos, Span, Symbol}; -pub fn check_attr(psess: &ParseSess, attr: &Attribute) { +pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) { if attr.is_doc_comment() { return; } @@ -22,50 +24,53 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) { let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name)); let attr_item = attr.get_normal_item(); - let is_unsafe_attr = - attr_info.map(|attr| attr.safety == AttributeSafety::Unsafe).unwrap_or(false); + let is_unsafe_attr = attr_info.is_some_and(|attr| attr.safety == AttributeSafety::Unsafe); - if is_unsafe_attr { - if let ast::Safety::Default = attr_item.unsafety { - let path_span = attr_item.path.span; + if features.unsafe_attributes { + if is_unsafe_attr { + if let ast::Safety::Default = attr_item.unsafety { + let path_span = attr_item.path.span; - // If the `attr_item`'s span is not from a macro, then just suggest - // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the - // `unsafe(`, `)` right after and right before the opening and closing - // square bracket respectively. - let diag_span = if attr_item.span().can_be_used_for_suggestions() { - attr_item.span() - } else { - attr.span.with_lo(attr.span.lo() + BytePos(2)).with_hi(attr.span.hi() - BytePos(1)) - }; + // If the `attr_item`'s span is not from a macro, then just suggest + // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the + // `unsafe(`, `)` right after and right before the opening and closing + // square bracket respectively. + let diag_span = if attr_item.span().can_be_used_for_suggestions() { + attr_item.span() + } else { + attr.span + .with_lo(attr.span.lo() + BytePos(2)) + .with_hi(attr.span.hi() - BytePos(1)) + }; - if attr.span.at_least_rust_2024() { - psess.dcx.emit_err(errors::UnsafeAttrOutsideUnsafe { - span: path_span, - suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { - left: diag_span.shrink_to_lo(), - right: diag_span.shrink_to_hi(), - }, + if attr.span.at_least_rust_2024() { + psess.dcx.emit_err(errors::UnsafeAttrOutsideUnsafe { + span: path_span, + suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion { + left: diag_span.shrink_to_lo(), + right: diag_span.shrink_to_hi(), + }, + }); + } else { + psess.buffer_lint( + UNSAFE_ATTR_OUTSIDE_UNSAFE, + path_span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::UnsafeAttrOutsideUnsafe { + attribute_name_span: path_span, + sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), + }, + ); + } + } + } else { + if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { + psess.dcx.emit_err(errors::InvalidAttrUnsafe { + span: unsafe_span, + name: attr_item.path.clone(), }); - } else { - psess.buffer_lint( - UNSAFE_ATTR_OUTSIDE_UNSAFE, - path_span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::UnsafeAttrOutsideUnsafe { - attribute_name_span: path_span, - sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()), - }, - ); } } - } else { - if let Safety::Unsafe(unsafe_span) = attr_item.unsafety { - psess.dcx.emit_err(errors::InvalidAttrUnsafe { - span: unsafe_span, - name: attr_item.path.clone(), - }); - } } // Check input tokens for built-in and key-value attributes. diff --git a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs index f3b8645abaf89..c6f9115cde750 100644 --- a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs +++ b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs @@ -1,4 +1,5 @@ #![deny(rust_2024_compatibility)] +#![feature(unsafe_attributes)] #[no_mangle] //~^ ERROR: unsafe attribute used without unsafe diff --git a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr index 4629a154ac3ce..f0689d9883c9e 100644 --- a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr @@ -1,5 +1,5 @@ error: unsafe attribute used without unsafe - --> $DIR/in_2024_compatibility.rs:3:3 + --> $DIR/in_2024_compatibility.rs:4:3 | LL | #[no_mangle] | ^^^^^^^^^ usage of unsafe attribute