Skip to content

Port #[should_panic] to the new attribute parsing infrastructure #143808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,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 },

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ impl AttributeKind {
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcObjectLifetimeDefault => No,
ShouldPanic { .. } => No,
SkipDuringMethodDispatch { .. } => No,
SpecializationTrait(..) => No,
Stability { .. } => Yes,
Expand Down
52 changes: 52 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/test_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
},
})
}
}
3 changes: 2 additions & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,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,
Expand Down Expand Up @@ -149,6 +149,7 @@ attribute_parsers!(
Single<RustcLayoutScalarValidRangeEnd>,
Single<RustcLayoutScalarValidRangeStart>,
Single<RustcObjectLifetimeDefaultParser>,
Single<ShouldPanicParser>,
Single<SkipDuringMethodDispatchParser>,
Single<TransparencyParser>,
Single<WithoutArgs<AllowIncoherentImplParser>>,
Expand Down
44 changes: 10 additions & 34 deletions compiler/rustc_builtin_macros/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
use rustc_ast::{self as ast, GenericParamKind, HasNodeId, attr};
use rustc_ast_pretty::pprust;
use rustc_attr_data_structures::AttributeKind;
use rustc_attr_parsing::AttributeParser;
use rustc_errors::{Applicability, Diag, Level};
use rustc_expand::base::*;
use rustc_hir::Attribute;
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Ident, Span, Symbol, sym};
use thin_vec::{ThinVec, thin_vec};
use tracing::debug;
Expand Down Expand Up @@ -478,39 +481,12 @@ 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())
{
ShouldPanic::Yes(reason)
} else {
ShouldPanic::No
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,7 @@ impl AttributeExt for Attribute {
Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span,
Attribute::Parsed(AttributeKind::MayDangle(span)) => *span,
Attribute::Parsed(AttributeKind::Ignore { span, .. }) => *span,
Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span,
a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_parse/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ pub fn check_builtin_meta_item(
| sym::rustc_layout_scalar_valid_range_start
| sym::rustc_layout_scalar_valid_range_end
| sym::no_implicit_prelude
| sym::should_panic
) {
return;
}
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,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)
}
Expand Down Expand Up @@ -334,9 +336,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
[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::automatically_derived, ..] => {
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Impl)
}
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/attributes/check-builtin-attr-ice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,10 @@
struct Foo {
#[should_panic::skip]
//~^ ERROR failed to resolve
//~| ERROR `#[should_panic::skip]` only has an effect on functions
pub field: u8,

#[should_panic::a::b::c]
//~^ ERROR failed to resolve
//~| ERROR `#[should_panic::a::b::c]` only has an effect on functions
pub field2: u8,
}

Expand Down
24 changes: 3 additions & 21 deletions tests/ui/attributes/check-builtin-attr-ice.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,17 @@ LL | #[should_panic::skip]
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic`

error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic`
--> $DIR/check-builtin-attr-ice.rs:50:7
--> $DIR/check-builtin-attr-ice.rs:49:7
|
LL | #[should_panic::a::b::c]
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic`

error[E0433]: failed to resolve: use of unresolved module or unlinked crate `deny`
--> $DIR/check-builtin-attr-ice.rs:59:7
--> $DIR/check-builtin-attr-ice.rs:57:7
|
LL | #[deny::skip]
| ^^^^ use of unresolved module or unlinked crate `deny`

error: `#[should_panic::skip]` only has an effect on functions
--> $DIR/check-builtin-attr-ice.rs:45:5
|
LL | #[should_panic::skip]
| ^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/check-builtin-attr-ice.rs:42:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^

error: `#[should_panic::a::b::c]` only has an effect on functions
--> $DIR/check-builtin-attr-ice.rs:50:5
|
LL | #[should_panic::a::b::c]
| ^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 5 previous errors
error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0433`.
Original file line number Diff line number Diff line change
Expand Up @@ -361,12 +361,6 @@ warning: crate-level attribute should be an inner attribute: add an exclamation
LL | #[type_length_limit="0100"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: `#[should_panic]` only has an effect on functions
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
|
LL | #![should_panic]
| ^^^^^^^^^^^^^^^^

warning: `#[proc_macro_derive]` only has an effect on functions
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
|
Expand Down Expand Up @@ -409,6 +403,12 @@ warning: `#[must_use]` has no effect when applied to a module
LL | #![must_use]
| ^^^^^^^^^^^^

warning: `#[should_panic]` only has an effect on functions
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1
|
LL | #![should_panic]
| ^^^^^^^^^^^^^^^^

warning: attribute should be applied to a function definition
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1
|
Expand Down
26 changes: 13 additions & 13 deletions tests/ui/lint/unused/unused-attr-duplicate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,6 @@ note: attribute also specified here
LL | #[macro_use]
| ^^^^^^^^^^^^

error: unused attribute
--> $DIR/unused-attr-duplicate.rs:55:1
|
LL | #[should_panic(expected = "values don't match")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:54:1
|
LL | #[should_panic]
| ^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

error: unused attribute
--> $DIR/unused-attr-duplicate.rs:70:1
|
Expand Down Expand Up @@ -165,6 +152,19 @@ note: attribute also specified here
LL | #[ignore]
| ^^^^^^^^^

error: unused attribute
--> $DIR/unused-attr-duplicate.rs:55:1
|
LL | #[should_panic(expected = "values don't match")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:54:1
|
LL | #[should_panic]
| ^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

error: unused attribute
--> $DIR/unused-attr-duplicate.rs:60:1
|
Expand Down
13 changes: 8 additions & 5 deletions tests/ui/test-attrs/test-should-panic-attr.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//@ check-pass
//@ compile-flags: --test

#[test]
Expand All @@ -9,28 +8,32 @@ fn test1() {

#[test]
#[should_panic(expected)]
//~^ WARN: argument must be of the form:
//~^ ERROR malformed `should_panic` attribute input
//~| NOTE expected this to be of the form `expected = "..."`
fn test2() {
panic!();
}

#[test]
#[should_panic(expect)]
//~^ WARN: argument must be of the form:
//~^ ERROR malformed `should_panic` attribute input
//~| NOTE the only valid argument here is "expected"
fn test3() {
panic!();
}

#[test]
#[should_panic(expected(foo, bar))]
//~^ WARN: argument must be of the form:
//~^ ERROR malformed `should_panic` attribute input
//~| NOTE expected this to be of the form `expected = "..."`
fn test4() {
panic!();
}

#[test]
#[should_panic(expected = "foo", bar)]
//~^ WARN: argument must be of the form:
//~^ ERROR malformed `should_panic` attribute input
//~| NOTE expected a single argument here
fn test5() {
panic!();
}
Loading
Loading