From 0404952bcfbb8e12cbb5064cb24140f86f0e8461 Mon Sep 17 00:00:00 2001 From: Sasha Pourcelot Date: Sun, 3 Aug 2025 11:54:07 +0200 Subject: [PATCH] Port `#[allow_internal_unsafe]` to the new attribute system --- .../src/attributes/macro_attrs.rs | 8 +++ compiler/rustc_attr_parsing/src/context.rs | 5 +- compiler/rustc_expand/src/base.rs | 5 +- .../rustc_hir/src/attrs/data_structures.rs | 3 ++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_lint/src/builtin.rs | 13 ++++- compiler/rustc_passes/messages.ftl | 2 +- compiler/rustc_passes/src/check_attr.rs | 49 ++++++++++++++++--- compiler/rustc_passes/src/errors.rs | 4 +- tests/ui/attributes/malformed-attrs.stderr | 15 +++--- 10 files changed, 82 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 886f7a889d303..0779248e1a95e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -113,3 +113,11 @@ impl AttributeParser for MacroUseParser { Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state }) } } + +pub(crate) struct AllowInternalUnsafeParser; + +impl NoArgsAttributeParser for AllowInternalUnsafeParser { + const PATH: &[Symbol] = &[sym::allow_internal_unsafe]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; + const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 767d19bd23406..9e98c52d87b53 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -33,7 +33,9 @@ use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, }; use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; -use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser}; +use crate::attributes::macro_attrs::{ + AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser, +}; use crate::attributes::must_use::MustUseParser; use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; use crate::attributes::non_exhaustive::NonExhaustiveParser; @@ -177,6 +179,7 @@ attribute_parsers!( Single, Single, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 1a9832b2fe26a..163fe34c19401 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -905,10 +905,7 @@ impl SyntaxExtension { find_attr!(attrs, AttributeKind::AllowInternalUnstable(i, _) => i) .map(|i| i.as_slice()) .unwrap_or_default(); - // FIXME(jdonszelman): allow_internal_unsafe isn't yet new-style - // let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe); - let allow_internal_unsafe = - ast::attr::find_by_name(attrs, sym::allow_internal_unsafe).is_some(); + let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe(_)); let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export) .and_then(|macro_export| macro_export.meta_item_list()) diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 80f5e6177f758..34c71ff02ac86 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -249,6 +249,9 @@ pub enum AttributeKind { /// Represents `#[rustc_allow_incoherent_impl]`. AllowIncoherentImpl(Span), + /// Represents `#[allow_internal_unsafe]`. + AllowInternalUnsafe(Span), + /// Represents `#[allow_internal_unstable]`. AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index bbdecb2986e00..c61842961bd04 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -16,6 +16,7 @@ impl AttributeKind { Align { .. } => No, AllowConstFnUnstable(..) => No, AllowIncoherentImpl(..) => No, + AllowInternalUnsafe(..) => Yes, AllowInternalUnstable(..) => Yes, AsPtr(..) => Yes, AutomaticallyDerived(..) => Yes, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c893b7233755d..51b1019104652 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -14,6 +14,7 @@ //! [`crate::late_lint_methods!`] invocation in `lib.rs`. use std::fmt::Write; +use std::slice; use ast::token::TokenKind; use rustc_abi::BackendRepr; @@ -21,6 +22,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; +use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, LintDiagnostic}; use rustc_feature::GateIssue; use rustc_hir as hir; @@ -249,7 +251,16 @@ impl UnsafeCode { impl EarlyLintPass for UnsafeCode { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { - if attr.has_name(sym::allow_internal_unsafe) { + if AttributeParser::parse_limited( + cx.builder.sess(), + slice::from_ref(attr), + sym::allow_internal_unsafe, + attr.span, + DUMMY_NODE_ID, + Some(cx.builder.features()), + ) + .is_some() + { self.report_unsafe(cx, attr.span, BuiltinUnsafe::AllowInternalUnsafe); } } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 6a28fe2617edf..4a1f01cc5c857 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -29,7 +29,7 @@ passes_allow_incoherent_impl = `rustc_allow_incoherent_impl` attribute should be applied to impl items .label = the only currently supported targets are inherent methods -passes_allow_internal_unstable = +passes_macro_only_attribute = attribute should be applied to a macro .label = not a macro diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ede74bdc0df62..94d8389540d1b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -207,6 +207,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => { self.check_const_continue(hir_id, *attr_span, target) } + Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span)) => { + self.check_allow_internal_unsafe(hir_id, *attr_span, span, target, attrs) + } Attribute::Parsed(AttributeKind::AllowInternalUnstable(_, first_span)) => { self.check_allow_internal_unstable(hir_id, *first_span, span, target, attrs) } @@ -415,7 +418,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // internal | sym::prelude_import | sym::panic_handler - | sym::allow_internal_unsafe | sym::lang | sym::needs_allocator | sym::default_lib_allocator @@ -2214,7 +2216,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. /// (Allows proc_macro functions) - // FIXME(jdonszelmann): if possible, move to attr parsing fn check_allow_internal_unstable( &self, hir_id: HirId, @@ -2222,6 +2223,42 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: Span, target: Target, attrs: &[Attribute], + ) { + self.check_macro_only_attr( + hir_id, + attr_span, + span, + target, + attrs, + "allow_internal_unstable", + ) + } + + /// Outputs an error for `#[allow_internal_unsafe]` which can only be applied to macros. + /// (Allows proc_macro functions) + fn check_allow_internal_unsafe( + &self, + hir_id: HirId, + attr_span: Span, + span: Span, + target: Target, + attrs: &[Attribute], + ) { + self.check_macro_only_attr(hir_id, attr_span, span, target, attrs, "allow_internal_unsafe") + } + + /// Outputs an error for attributes that can only be applied to macros, such as + /// `#[allow_internal_unsafe]` and `#[allow_internal_unstable]`. + /// (Allows proc_macro functions) + // FIXME(jdonszelmann): if possible, move to attr parsing + fn check_macro_only_attr( + &self, + hir_id: HirId, + attr_span: Span, + span: Span, + target: Target, + attrs: &[Attribute], + attr_name: &str, ) { match target { Target::Fn => { @@ -2240,18 +2277,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm => { - self.inline_attr_str_error_without_macro_def( - hir_id, - attr_span, - "allow_internal_unstable", - ); + self.inline_attr_str_error_without_macro_def(hir_id, attr_span, attr_name); return; } // otherwise continue out of the match _ => {} } - self.tcx.dcx().emit_err(errors::AllowInternalUnstable { attr_span, span }); + self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span }); } /// Checks if the items on the `#[debugger_visualizer]` attribute are valid. diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c6ab6b0d60179..10b30fbe8c94e 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -643,8 +643,8 @@ pub(crate) struct UsedStatic { } #[derive(Diagnostic)] -#[diag(passes_allow_internal_unstable)] -pub(crate) struct AllowInternalUnstable { +#[diag(passes_macro_only_attribute)] +pub(crate) struct MacroOnlyAttribute { #[primary_span] pub attr_span: Span, #[label] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 814a1e5f69192..be58ddbbf069b 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -151,12 +151,6 @@ LL - #[macro_export = 18] LL + #[macro_export] | -error: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:217:1 - | -LL | #[allow_internal_unsafe = 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[allow_internal_unsafe]` - error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/malformed-attrs.rs:100:1 | @@ -567,6 +561,15 @@ error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and ` LL | #[macro_use = 1] | ^^^^^^^^^^^^^^^^ +error[E0565]: malformed `allow_internal_unsafe` attribute input + --> $DIR/malformed-attrs.rs:217:1 + | +LL | #[allow_internal_unsafe = 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^---^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[allow_internal_unsafe]` + error[E0565]: malformed `type_const` attribute input --> $DIR/malformed-attrs.rs:144:5 |