diff options
| author | Jonathan Brouwer <jonathantbrouwer@gmail.com> | 2025-07-11 18:36:28 +0200 |
|---|---|---|
| committer | Jonathan Brouwer <jonathantbrouwer@gmail.com> | 2025-08-06 21:37:51 +0200 |
| commit | f7ad4065fe41f8bcf74c4f6a7c2c1793e08e71f0 (patch) | |
| tree | 41f0dcfa9ca1cc71e4adacd5a59b7aee7e5c5192 | |
| parent | 8fb40f798a23adf608182ce5f4eb151fdc8e0da5 (diff) | |
| download | rust-f7ad4065fe41f8bcf74c4f6a7c2c1793e08e71f0.tar.gz rust-f7ad4065fe41f8bcf74c4f6a7c2c1793e08e71f0.zip | |
Port `#[should_panic]` to the new attribute parsing infrastructure
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
| -rw-r--r-- | compiler/rustc_attr_parsing/src/attributes/test_attrs.rs | 52 | ||||
| -rw-r--r-- | compiler/rustc_attr_parsing/src/context.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/test.rs | 51 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/attrs/data_structures.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/attrs/encode_cross_crate.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 5 |
7 files changed, 78 insertions, 38 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index a90ed830cd1..77b494328c7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -44,3 +44,55 @@ impl<S: Stage> SingleAttributeParser<S> for IgnoreParser { }) } } + +pub(crate) struct ShouldPanicParser; + +impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser { + const PATH: &[Symbol] = &[sym::should_panic]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = + template!(Word, List: r#"expected = "reason""#, NameValueStr: "reason"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { + Some(AttributeKind::ShouldPanic { + span: cx.attr_span, + reason: match args { + ArgParser::NoArgs => None, + ArgParser::NameValue(name_value) => { + let Some(str_value) = name_value.value_as_str() else { + cx.expected_string_literal( + name_value.value_span, + Some(name_value.value_as_lit()), + ); + return None; + }; + Some(str_value) + } + ArgParser::List(list) => { + let Some(single) = list.single() else { + cx.expected_single_argument(list.span); + return None; + }; + let Some(single) = single.meta_item() else { + cx.expected_name_value(single.span(), Some(sym::expected)); + return None; + }; + if !single.path().word_is(sym::expected) { + cx.expected_specific_argument_strings(list.span, vec!["expected"]); + return None; + } + let Some(nv) = single.args().name_value() else { + cx.expected_name_value(single.span(), Some(sym::expected)); + return None; + }; + let Some(expected) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + Some(expected) + } + }, + }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index c6599f20c2d..f43cc8fd450 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -49,7 +49,7 @@ use crate::attributes::semantics::MayDangleParser; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, }; -use crate::attributes::test_attrs::IgnoreParser; +use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser}; use crate::attributes::traits::{ AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser, DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser, @@ -173,6 +173,7 @@ attribute_parsers!( Single<RustcLayoutScalarValidRangeEnd>, Single<RustcLayoutScalarValidRangeStart>, Single<RustcObjectLifetimeDefaultParser>, + Single<ShouldPanicParser>, Single<SkipDuringMethodDispatchParser>, Single<TransparencyParser>, Single<WithoutArgs<AllowIncoherentImplParser>>, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index ba3d8368b2a..7b57c02b197 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -5,10 +5,13 @@ use std::assert_matches::assert_matches; use std::iter; use rustc_ast::ptr::P; -use rustc_ast::{self as ast, GenericParamKind, attr, join_path_idents}; +use rustc_ast::{self as ast, GenericParamKind, HasNodeId, attr, join_path_idents}; use rustc_ast_pretty::pprust; +use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, Diag, Level}; use rustc_expand::base::*; +use rustc_hir::Attribute; +use rustc_hir::attrs::AttributeKind; use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; use tracing::debug; @@ -473,39 +476,19 @@ fn should_ignore_message(i: &ast::Item) -> Option<Symbol> { } fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { - match attr::find_by_name(&i.attrs, sym::should_panic) { - Some(attr) => { - match attr.meta_item_list() { - // Handle #[should_panic(expected = "foo")] - Some(list) => { - let msg = list - .iter() - .find(|mi| mi.has_name(sym::expected)) - .and_then(|mi| mi.meta_item()) - .and_then(|mi| mi.value_str()); - if list.len() != 1 || msg.is_none() { - cx.dcx() - .struct_span_warn( - attr.span, - "argument must be of the form: \ - `expected = \"error message\"`", - ) - .with_note( - "errors in this attribute were erroneously \ - allowed and will become a hard error in a \ - future release", - ) - .emit(); - ShouldPanic::Yes(None) - } else { - ShouldPanic::Yes(msg) - } - } - // Handle #[should_panic] and #[should_panic = "expected"] - None => ShouldPanic::Yes(attr.value_str()), - } - } - None => ShouldPanic::No, + if let Some(Attribute::Parsed(AttributeKind::ShouldPanic { reason, .. })) = + AttributeParser::parse_limited( + cx.sess, + &i.attrs, + sym::should_panic, + i.span, + i.node_id(), + None, + ) + { + ShouldPanic::Yes(reason) + } else { + ShouldPanic::No } } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 80618422b56..c531d72b53c 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -433,6 +433,9 @@ pub enum AttributeKind { /// Represents `#[rustc_object_lifetime_default]`. RustcObjectLifetimeDefault, + /// Represents `#[should_panic]` + ShouldPanic { reason: Option<Symbol>, span: Span }, + /// Represents `#[rustc_skip_during_method_dispatch]`. SkipDuringMethodDispatch { array: bool, boxed_slice: bool, 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 9644a597a31..a1a381bda0f 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -69,6 +69,7 @@ impl AttributeKind { RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, RustcObjectLifetimeDefault => No, + ShouldPanic { .. } => No, SkipDuringMethodDispatch { .. } => No, SpecializationTrait(..) => No, Stability { .. } => Yes, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c30c830f9af..34db6f92d92 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1308,6 +1308,7 @@ impl AttributeExt for Attribute { Attribute::Parsed(AttributeKind::MacroUse { span, .. }) => *span, Attribute::Parsed(AttributeKind::MayDangle(span)) => *span, Attribute::Parsed(AttributeKind::Ignore { span, .. }) => *span, + Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span, Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span, a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"), } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2663d5fe99c..33db97dde2c 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -315,6 +315,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => { self.check_used(*attr_span, target, span); } + Attribute::Parsed(AttributeKind::ShouldPanic { span: attr_span, .. }) => self + .check_generic_attr(hir_id, sym::should_panic, *attr_span, target, Target::Fn), &Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => { self.check_pass_by_value(attr_span, span, target) } @@ -384,9 +386,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::link, ..] => self.check_link(hir_id, attr, span, target), [sym::path, ..] => self.check_generic_attr_unparsed(hir_id, attr, target, Target::Mod), [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target), - [sym::should_panic, ..] => { - self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn) - } [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } |
