Skip to content

Commit 5c6055c

Browse files
Port #[should_panic] to the new attribute parsing infrastructure
Signed-off-by: Jonathan Brouwer <[email protected]>
1 parent a9fb610 commit 5c6055c

File tree

8 files changed

+79
-38
lines changed

8 files changed

+79
-38
lines changed

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,9 @@ pub enum AttributeKind {
389389
/// Represents `#[rustc_object_lifetime_default]`.
390390
RustcObjectLifetimeDefault,
391391

392+
/// Represents `#[should_panic]`
393+
ShouldPanic { reason: Option<Symbol>, span: Span },
394+
392395
/// Represents `#[rustc_skip_during_method_dispatch]`.
393396
SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
394397

compiler/rustc_attr_data_structures/src/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl AttributeKind {
6262
RustcLayoutScalarValidRangeEnd(..) => Yes,
6363
RustcLayoutScalarValidRangeStart(..) => Yes,
6464
RustcObjectLifetimeDefault => No,
65+
ShouldPanic { .. } => No,
6566
SkipDuringMethodDispatch { .. } => No,
6667
SpecializationTrait(..) => No,
6768
Stability { .. } => Yes,

compiler/rustc_attr_parsing/src/attributes/test_attrs.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,55 @@ impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
4444
})
4545
}
4646
}
47+
48+
pub(crate) struct ShouldPanicParser;
49+
50+
impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser {
51+
const PATH: &[Symbol] = &[sym::should_panic];
52+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
53+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
54+
const TEMPLATE: AttributeTemplate =
55+
template!(Word, List: r#"expected = "reason""#, NameValueStr: "reason");
56+
57+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
58+
Some(AttributeKind::ShouldPanic {
59+
span: cx.attr_span,
60+
reason: match args {
61+
ArgParser::NoArgs => None,
62+
ArgParser::NameValue(name_value) => {
63+
let Some(str_value) = name_value.value_as_str() else {
64+
cx.expected_string_literal(
65+
name_value.value_span,
66+
Some(name_value.value_as_lit()),
67+
);
68+
return None;
69+
};
70+
Some(str_value)
71+
}
72+
ArgParser::List(list) => {
73+
let Some(single) = list.single() else {
74+
cx.expected_single_argument(list.span);
75+
return None;
76+
};
77+
let Some(single) = single.meta_item() else {
78+
cx.expected_name_value(single.span(), Some(sym::expected));
79+
return None;
80+
};
81+
if !single.path().word_is(sym::expected) {
82+
cx.expected_specific_argument_strings(list.span, vec!["expected"]);
83+
return None;
84+
}
85+
let Some(nv) = single.args().name_value() else {
86+
cx.expected_name_value(single.span(), Some(sym::expected));
87+
return None;
88+
};
89+
let Some(expected) = nv.value_as_str() else {
90+
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
91+
return None;
92+
};
93+
Some(expected)
94+
}
95+
},
96+
})
97+
}
98+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use crate::attributes::semantics::MayDangleParser;
4343
use crate::attributes::stability::{
4444
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
4545
};
46-
use crate::attributes::test_attrs::IgnoreParser;
46+
use crate::attributes::test_attrs::{IgnoreParser, ShouldPanicParser};
4747
use crate::attributes::traits::{
4848
AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
4949
DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
@@ -151,6 +151,7 @@ attribute_parsers!(
151151
Single<RustcLayoutScalarValidRangeEnd>,
152152
Single<RustcLayoutScalarValidRangeStart>,
153153
Single<RustcObjectLifetimeDefaultParser>,
154+
Single<ShouldPanicParser>,
154155
Single<SkipDuringMethodDispatchParser>,
155156
Single<TransparencyParser>,
156157
Single<WithoutArgs<AllowIncoherentImplParser>>,

compiler/rustc_builtin_macros/src/test.rs

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ use std::assert_matches::assert_matches;
55
use std::iter;
66

77
use rustc_ast::ptr::P;
8-
use rustc_ast::{self as ast, GenericParamKind, attr};
8+
use rustc_ast::{self as ast, GenericParamKind, HasNodeId, attr};
99
use rustc_ast_pretty::pprust;
10+
use rustc_attr_data_structures::AttributeKind;
11+
use rustc_attr_parsing::AttributeParser;
1012
use rustc_errors::{Applicability, Diag, Level};
1113
use rustc_expand::base::*;
14+
use rustc_hir::Attribute;
1215
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Ident, Span, Symbol, sym};
1316
use thin_vec::{ThinVec, thin_vec};
1417
use tracing::debug;
@@ -478,39 +481,19 @@ fn should_ignore_message(i: &ast::Item) -> Option<Symbol> {
478481
}
479482

480483
fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
481-
match attr::find_by_name(&i.attrs, sym::should_panic) {
482-
Some(attr) => {
483-
match attr.meta_item_list() {
484-
// Handle #[should_panic(expected = "foo")]
485-
Some(list) => {
486-
let msg = list
487-
.iter()
488-
.find(|mi| mi.has_name(sym::expected))
489-
.and_then(|mi| mi.meta_item())
490-
.and_then(|mi| mi.value_str());
491-
if list.len() != 1 || msg.is_none() {
492-
cx.dcx()
493-
.struct_span_warn(
494-
attr.span,
495-
"argument must be of the form: \
496-
`expected = \"error message\"`",
497-
)
498-
.with_note(
499-
"errors in this attribute were erroneously \
500-
allowed and will become a hard error in a \
501-
future release",
502-
)
503-
.emit();
504-
ShouldPanic::Yes(None)
505-
} else {
506-
ShouldPanic::Yes(msg)
507-
}
508-
}
509-
// Handle #[should_panic] and #[should_panic = "expected"]
510-
None => ShouldPanic::Yes(attr.value_str()),
511-
}
512-
}
513-
None => ShouldPanic::No,
484+
if let Some(Attribute::Parsed(AttributeKind::ShouldPanic { reason, .. })) =
485+
AttributeParser::parse_limited(
486+
cx.sess,
487+
&i.attrs,
488+
sym::should_panic,
489+
i.span,
490+
i.node_id(),
491+
None,
492+
)
493+
{
494+
ShouldPanic::Yes(reason)
495+
} else {
496+
ShouldPanic::No
514497
}
515498
}
516499

compiler/rustc_hir/src/hir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,7 @@ impl AttributeExt for Attribute {
13041304
Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span,
13051305
Attribute::Parsed(AttributeKind::MayDangle(span)) => *span,
13061306
Attribute::Parsed(AttributeKind::Ignore { span, .. }) => *span,
1307+
Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span,
13071308
Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span,
13081309
a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
13091310
}

compiler/rustc_parse/src/validate_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ pub fn check_builtin_meta_item(
307307
| sym::path
308308
| sym::ignore
309309
| sym::must_use
310+
| sym::should_panic
310311
| sym::track_caller
311312
| sym::link_name
312313
| sym::link_ordinal

compiler/rustc_passes/src/check_attr.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
278278
Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => {
279279
self.check_used(*attr_span, target, span);
280280
}
281+
Attribute::Parsed(AttributeKind::ShouldPanic { span: attr_span, .. }) => self
282+
.check_generic_attr(hir_id, sym::should_panic, *attr_span, target, Target::Fn),
281283
&Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => {
282284
self.check_pass_by_value(attr_span, span, target)
283285
}
@@ -348,9 +350,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
348350
}
349351
[sym::path, ..] => self.check_generic_attr_unparsed(hir_id, attr, target, Target::Mod),
350352
[sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
351-
[sym::should_panic, ..] => {
352-
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn)
353-
}
354353
[sym::proc_macro, ..] => {
355354
self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
356355
}

0 commit comments

Comments
 (0)