Skip to content

Commit 226edf6

Browse files
committed
Improve an error involving attribute values.
Attribute values must be literals. The error you get when that doesn't hold is pretty bad, e.g.: ``` unexpected expression: 1 + 1 ``` You also get the same error if the attribute value is a literal, but an invalid literal, e.g.: ``` unexpected expression: "foo"suffix ``` This commit does two things. - Changes the error message to "attribute value must be a literal", which gives a better idea of what the problem is and how to fix it. It also no longer prints the invalid expression, because the carets below highlight it anyway. - Separates the "not a literal" case from the "invalid literal" case. Which means invalid literals now get the specific error at the literal level, rather than at the attribute level.
1 parent 5701093 commit 226edf6

17 files changed

+87
-62
lines changed

compiler/rustc_parse/src/validate_attr.rs

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use rustc_ast::token::Delimiter;
66
use rustc_ast::tokenstream::DelimSpan;
77
use rustc_ast::MetaItemKind;
88
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem};
9-
use rustc_ast_pretty::pprust;
109
use rustc_errors::{Applicability, FatalError, PResult};
1110
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
11+
use rustc_session::errors::report_lit_error;
1212
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
1313
use rustc_session::parse::ParseSess;
1414
use rustc_span::{sym, Span, Symbol};
@@ -51,28 +51,44 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
5151
MetaItemKind::List(nmis)
5252
}
5353
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => {
54-
if let ast::ExprKind::Lit(token_lit) = expr.kind
55-
&& let Ok(lit) = ast::MetaItemLit::from_token_lit(token_lit, expr.span)
56-
{
57-
if token_lit.suffix.is_some() {
58-
let mut err = sess.span_diagnostic.struct_span_err(
59-
expr.span,
60-
"suffixed literals are not allowed in attributes",
61-
);
62-
err.help(
63-
"instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
64-
use an unsuffixed version (`1`, `1.0`, etc.)",
65-
);
66-
return Err(err);
67-
} else {
68-
MetaItemKind::NameValue(lit)
69-
}
54+
if let ast::ExprKind::Lit(token_lit) = expr.kind {
55+
let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
56+
let res = match res {
57+
Ok(lit) => {
58+
if token_lit.suffix.is_some() {
59+
let mut err = sess.span_diagnostic.struct_span_err(
60+
expr.span,
61+
"suffixed literals are not allowed in attributes",
62+
);
63+
err.help(
64+
"instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
65+
use an unsuffixed version (`1`, `1.0`, etc.)",
66+
);
67+
return Err(err);
68+
} else {
69+
MetaItemKind::NameValue(lit)
70+
}
71+
}
72+
Err(err) => {
73+
report_lit_error(sess, err, token_lit, expr.span);
74+
let lit = ast::MetaItemLit {
75+
symbol: token_lit.symbol,
76+
suffix: token_lit.suffix,
77+
kind: ast::LitKind::Err,
78+
span: expr.span,
79+
};
80+
MetaItemKind::NameValue(lit)
81+
}
82+
};
83+
res
7084
} else {
71-
// The non-error case can happen with e.g. `#[foo = 1+1]`. The error case can
72-
// happen with e.g. `#[foo = include_str!("nonexistent-file.rs")]`; in that
73-
// case we delay the error because an earlier error will have already been
74-
// reported.
75-
let msg = format!("unexpected expression: `{}`", pprust::expr_to_string(expr));
85+
// Example cases:
86+
// - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
87+
// - `#[foo = include_str!("nonexistent-file.rs")]`:
88+
// results in `ast::ExprKind::Err`. In that case we delay
89+
// the error because an earlier error will have already
90+
// been reported.
91+
let msg = format!("attribute value must be a literal");
7692
let mut err = sess.span_diagnostic.struct_span_err(expr.span, msg);
7793
if let ast::ExprKind::Err = expr.kind {
7894
err.downgrade_to_delayed_bug();

tests/ui/attributes/issue-90873.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#![u=||{static d=||1;}]
2-
//~^ unexpected expression
2+
//~^ attribute value must be a literal
33
//~| cannot find attribute `u` in this scope
44
//~| missing type for `static` item
55

66
#![a={impl std::ops::Neg for i8 {}}]
7-
//~^ ERROR unexpected expression
7+
//~^ ERROR attribute value must be a literal
88
//~| ERROR cannot find attribute `a` in this scope
99
//~| ERROR `main` function not found in crate `issue_90873`

tests/ui/attributes/issue-90873.stderr

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
error: unexpected expression: `||
2-
{
3-
static d: _ = || 1;
4-
}`
1+
error: attribute value must be a literal
52
--> $DIR/issue-90873.rs:1:6
63
|
74
LL | #![u=||{static d=||1;}]
85
| ^^^^^^^^^^^^^^^^^
96

10-
error: unexpected expression: `{
11-
impl std::ops::Neg for i8 {}
12-
}`
7+
error: attribute value must be a literal
138
--> $DIR/issue-90873.rs:6:6
149
|
1510
LL | #![a={impl std::ops::Neg for i8 {}}]

tests/ui/attributes/key-value-expansion-on-mac.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ macro_rules! bar {
77

88
// FIXME?: `bar` here expands before `stringify` has a chance to expand.
99
// `#[rustc_dummy = ...]` is validated and dropped during expansion of `bar`,
10-
// the "unexpected expression" errors comes from the validation.
11-
#[rustc_dummy = stringify!(b)] //~ ERROR unexpected expression: `stringify!(b)`
10+
// the "attribute value must be a literal" error comes from the validation.
11+
#[rustc_dummy = stringify!(b)] //~ ERROR attribute value must be a literal
1212
bar!();
1313

1414
fn main() {}

tests/ui/attributes/key-value-expansion-on-mac.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: unexpected expression: `stringify!(b)`
1+
error: attribute value must be a literal
22
--> $DIR/key-value-expansion-on-mac.rs:11:17
33
|
44
LL | #[rustc_dummy = stringify!(b)]

tests/ui/attributes/key-value-expansion.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ macro_rules! bug {
1818

1919
// Any expressions containing macro call `X` that's more complex than `X` itself.
2020
// Parentheses will work.
21-
bug!((column!())); //~ ERROR unexpected expression: `(7u32)`
21+
bug!((column!())); //~ ERROR attribute value must be a literal
2222

2323
// Original test case.
2424

2525
macro_rules! bug {
2626
() => {
27-
bug!("bug" + stringify!(found)); //~ ERROR unexpected expression: `"bug" + "found"`
27+
bug!("bug" + stringify!(found)); //~ ERROR attribute value must be a literal
2828
};
2929
($test:expr) => {
3030
#[doc = $test]
@@ -46,7 +46,7 @@ macro_rules! doc_comment {
4646
macro_rules! some_macro {
4747
($t1: ty) => {
4848
doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}
49-
//~^ ERROR unexpected expression: `{
49+
//~^ ERROR attribute value must be a literal
5050
};
5151
}
5252

tests/ui/attributes/key-value-expansion.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: unexpected expression: `(7u32)`
1+
error: attribute value must be a literal
22
--> $DIR/key-value-expansion.rs:21:6
33
|
44
LL | bug!((column!()));
55
| ^^^^^^^^^^^
66

7-
error: unexpected expression: `"bug" + "found"`
7+
error: attribute value must be a literal
88
--> $DIR/key-value-expansion.rs:27:14
99
|
1010
LL | bug!("bug" + stringify!(found));
@@ -15,7 +15,7 @@ LL | bug!();
1515
|
1616
= note: this error originates in the macro `bug` (in Nightly builds, run with -Z macro-backtrace for more info)
1717

18-
error: unexpected expression: `{ let res = ::alloc::fmt::format(format_args!("{0}", "u8")); res }.as_str()`
18+
error: attribute value must be a literal
1919
--> $DIR/key-value-expansion.rs:48:23
2020
|
2121
LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}

tests/ui/attributes/unused-item-in-attr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[w = { extern crate alloc; }]
2-
//~^ ERROR unexpected expression: `{
2+
//~^ ERROR attribute value must be a literal
33
//~| ERROR cannot find attribute `w` in this scope
44
fn f() {}
55

tests/ui/attributes/unused-item-in-attr.stderr

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
error: unexpected expression: `{
2-
extern crate alloc;
3-
}`
1+
error: attribute value must be a literal
42
--> $DIR/unused-item-in-attr.rs:1:7
53
|
64
LL | #[w = { extern crate alloc; }]

tests/ui/consts/issue-90878-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![l=|x|[b;x ]] //~ ERROR unexpected expression: `|x| [b; x]`
1+
#![l=|x|[b;x ]] //~ ERROR attribute value must be a literal
22
//~^ ERROR cannot find attribute `l` in this scope
33

44
// notice the space at the start,

0 commit comments

Comments
 (0)