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

+38-22
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

+2-2
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

+2-7
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

+2-2
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

+1-1
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

+3-3
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

+3-3
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

+1-1
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

+1-3
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

+1-1
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,

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: unexpected expression: `|x| [b; x]`
1+
error: attribute value must be a literal
22
--> $DIR/issue-90878-2.rs:1:7
33
|
44
LL | #![l=|x|[b;x ]]

tests/ui/malformed/malformed-interpolated.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ macro_rules! check {
1010
check!("0"); // OK
1111
check!(0); // OK
1212
check!(0u8); //~ ERROR suffixed literals are not allowed in attributes
13-
check!(-0); //~ ERROR unexpected expression: `-0`
14-
check!(0 + 0); //~ ERROR unexpected expression: `0 + 0`
13+
check!(-0); //~ ERROR attribute value must be a literal
14+
check!(0 + 0); //~ ERROR attribute value must be a literal
1515

1616
fn main() {}

tests/ui/malformed/malformed-interpolated.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ LL | check!(0u8);
66
|
77
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
88

9-
error: unexpected expression: `-0`
9+
error: attribute value must be a literal
1010
--> $DIR/malformed-interpolated.rs:13:8
1111
|
1212
LL | check!(-0);
1313
| ^^
1414

15-
error: unexpected expression: `0 + 0`
15+
error: attribute value must be a literal
1616
--> $DIR/malformed-interpolated.rs:14:8
1717
|
1818
LL | check!(0 + 0);

tests/ui/parser/bad-lit-suffixes.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ fn main() {
2828
}
2929

3030
#[rustc_dummy = "string"suffix]
31-
//~^ ERROR unexpected expression: `"string"suffix`
31+
//~^ ERROR suffixes on string literals are invalid
3232
fn f() {}
3333

3434
#[must_use = "string"suffix]
35-
//~^ ERROR unexpected expression: `"string"suffix`
35+
//~^ ERROR suffixes on string literals are invalid
36+
//~| ERROR malformed `must_use` attribute input
3637
fn g() {}
3738

3839
#[link(name = "string"suffix)]

tests/ui/parser/bad-lit-suffixes.stderr

+20-7
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,39 @@ error: suffixes on string literals are invalid
1010
LL | "C"suffix
1111
| ^^^^^^^^^ invalid suffix `suffix`
1212

13-
error: unexpected expression: `"string"suffix`
13+
error: suffixes on string literals are invalid
1414
--> $DIR/bad-lit-suffixes.rs:30:17
1515
|
1616
LL | #[rustc_dummy = "string"suffix]
17-
| ^^^^^^^^^^^^^^
17+
| ^^^^^^^^^^^^^^ invalid suffix `suffix`
1818

19-
error: unexpected expression: `"string"suffix`
19+
error: suffixes on string literals are invalid
2020
--> $DIR/bad-lit-suffixes.rs:34:14
2121
|
2222
LL | #[must_use = "string"suffix]
23-
| ^^^^^^^^^^^^^^
23+
| ^^^^^^^^^^^^^^ invalid suffix `suffix`
24+
25+
error: malformed `must_use` attribute input
26+
--> $DIR/bad-lit-suffixes.rs:34:1
27+
|
28+
LL | #[must_use = "string"suffix]
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
|
31+
help: the following are the possible correct uses
32+
|
33+
LL | #[must_use = "reason"]
34+
|
35+
LL | #[must_use]
36+
|
2437

2538
error: suffixes on string literals are invalid
26-
--> $DIR/bad-lit-suffixes.rs:38:15
39+
--> $DIR/bad-lit-suffixes.rs:39:15
2740
|
2841
LL | #[link(name = "string"suffix)]
2942
| ^^^^^^^^^^^^^^ invalid suffix `suffix`
3043

3144
error: invalid suffix `suffix` for number literal
32-
--> $DIR/bad-lit-suffixes.rs:42:41
45+
--> $DIR/bad-lit-suffixes.rs:43:41
3346
|
3447
LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
3548
| ^^^^^^^ invalid suffix `suffix`
@@ -136,5 +149,5 @@ LL | 1.0e10suffix;
136149
|
137150
= help: valid suffixes are `f32` and `f64`
138151

139-
error: aborting due to 20 previous errors
152+
error: aborting due to 21 previous errors
140153

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#![feature(rustc_attrs)]
22

3-
#![rustc_dummy=5z] //~ ERROR unexpected expression: `5z`
3+
#![rustc_dummy=5z] //~ ERROR invalid suffix `z` for number literal
44
fn main() {}
+4-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
error: unexpected expression: `5z`
1+
error: invalid suffix `z` for number literal
22
--> $DIR/issue-104620.rs:3:16
33
|
44
LL | #![rustc_dummy=5z]
5-
| ^^
5+
| ^^ invalid suffix `z`
6+
|
7+
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
68

79
error: aborting due to 1 previous error
810

0 commit comments

Comments
 (0)