Skip to content

Commit ca8d53a

Browse files
committed
fix bug in proc macro derive diagnostics
1 parent f3fd3ef commit ca8d53a

File tree

5 files changed

+102
-38
lines changed

5 files changed

+102
-38
lines changed

compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,15 @@ fn parse_derive_like<S: Stage>(
9292
return None;
9393
};
9494

95+
// updated if we see `attributes(...)` to keep track of the last
96+
// argument we did accept for the final diagnostic
97+
let mut last = trait_ident.span;
98+
9599
// Parse optional attributes
96100
let mut attributes = ThinVec::new();
97101
if let Some(attrs) = items.next() {
102+
last = attrs.span();
103+
98104
let Some(attr_list) = attrs.meta_item() else {
99105
cx.expected_list(attrs.span());
100106
return None;
@@ -132,7 +138,7 @@ fn parse_derive_like<S: Stage>(
132138

133139
// If anything else is specified, we should reject it
134140
if let Some(next) = items.next() {
135-
cx.expected_no_args(next.span());
141+
cx.expected_end_of_list(last, next.span());
136142
}
137143

138144
Some((Some(trait_ident.name), attributes))

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,21 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
507507
})
508508
}
509509

510+
/// Expected the end of an argument list.
511+
///
512+
/// Note: only useful when arguments in an attribute are ordered and we've seen the last one we expected.
513+
/// Most attributes shouldn't care about their argument order.
514+
pub(crate) fn expected_end_of_list(&self, last_item_span: Span, span: Span) -> ErrorGuaranteed {
515+
self.emit_err(AttributeParseError {
516+
span,
517+
attr_span: self.attr_span,
518+
template: self.template.clone(),
519+
attribute: self.attr_path.clone(),
520+
reason: AttributeParseErrorReason::ExpectedEnd { last: last_item_span },
521+
attr_style: self.attr_style,
522+
})
523+
}
524+
510525
pub(crate) fn expected_single_argument(&self, span: Span) -> ErrorGuaranteed {
511526
self.emit_err(AttributeParseError {
512527
span,

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,9 @@ pub(crate) enum AttributeParseErrorReason<'a> {
577577
list: bool,
578578
},
579579
ExpectedIdentifier,
580+
ExpectedEnd {
581+
last: Span,
582+
},
580583
}
581584

582585
pub(crate) struct AttributeParseError<'a> {
@@ -716,6 +719,10 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
716719
AttributeParseErrorReason::ExpectedIdentifier => {
717720
diag.span_label(self.span, "expected a valid identifier here");
718721
}
722+
AttributeParseErrorReason::ExpectedEnd { last } => {
723+
diag.span_label(last, "expected no more arguments after this");
724+
diag.span_label(self.span, "remove this argument");
725+
}
719726
}
720727

721728
if let Some(link) = self.template.docs {

tests/ui/proc-macro/attribute.rs

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,97 +10,132 @@ use proc_macro::*;
1010
//~^ ERROR malformed `proc_macro_derive` attribute
1111
//~| NOTE expected this to be a list
1212
//~| NOTE for more information, visit
13-
pub fn foo1(input: TokenStream) -> TokenStream { input }
13+
pub fn foo1(input: TokenStream) -> TokenStream {
14+
input
15+
}
1416

1517
#[proc_macro_derive = ""]
1618
//~^ ERROR malformed `proc_macro_derive` attribute
1719
//~| NOTE expected this to be a list
1820
//~| NOTE for more information, visit
19-
pub fn foo2(input: TokenStream) -> TokenStream { input }
21+
pub fn foo2(input: TokenStream) -> TokenStream {
22+
input
23+
}
2024

2125
#[proc_macro_derive(d3, a, b)]
2226
//~^ ERROR malformed `proc_macro_derive` attribute
2327
//~| NOTE the only valid argument here is `attributes`
2428
//~| NOTE for more information, visit
25-
pub fn foo3(input: TokenStream) -> TokenStream { input }
29+
pub fn foo3(input: TokenStream) -> TokenStream {
30+
input
31+
}
2632

2733
#[proc_macro_derive(d4, attributes(a), b)]
2834
//~^ ERROR malformed `proc_macro_derive` attribute
29-
//~| NOTE didn't expect any arguments here
35+
//~| NOTE expected no more arguments after this
36+
//~| NOTE remove this argument
3037
//~| NOTE for more information, visit
31-
pub fn foo4(input: TokenStream) -> TokenStream { input }
38+
pub fn foo4(input: TokenStream) -> TokenStream {
39+
input
40+
}
3241

3342
#[proc_macro_derive("a")]
3443
//~^ ERROR malformed `proc_macro_derive` attribute
3544
//~| NOTE didn't expect a literal here
3645
//~| NOTE for more information, visit
37-
pub fn foo5(input: TokenStream) -> TokenStream { input }
46+
pub fn foo5(input: TokenStream) -> TokenStream {
47+
input
48+
}
3849

3950
#[proc_macro_derive(d6 = "")]
4051
//~^ ERROR malformed `proc_macro_derive` attribute
4152
//~| NOTE didn't expect any arguments here
4253
//~| NOTE for more information, visit
43-
pub fn foo6(input: TokenStream) -> TokenStream { input }
54+
pub fn foo6(input: TokenStream) -> TokenStream {
55+
input
56+
}
4457

4558
#[proc_macro_derive(m::d7)]
4659
//~^ ERROR malformed `proc_macro_derive` attribute
4760
//~| NOTE expected a valid identifier here
4861
//~| NOTE for more information, visit
49-
pub fn foo7(input: TokenStream) -> TokenStream { input }
62+
pub fn foo7(input: TokenStream) -> TokenStream {
63+
input
64+
}
5065

5166
#[proc_macro_derive(d8(a))]
5267
//~^ ERROR malformed `proc_macro_derive` attribute
5368
//~| NOTE didn't expect any arguments here
5469
//~| NOTE for more information, visit
55-
pub fn foo8(input: TokenStream) -> TokenStream { input }
70+
pub fn foo8(input: TokenStream) -> TokenStream {
71+
input
72+
}
5673

5774
#[proc_macro_derive(self)]
5875
//~^ ERROR malformed `proc_macro_derive` attribute
5976
//~| NOTE expected a valid identifier here
6077
//~| NOTE for more information, visit
61-
pub fn foo9(input: TokenStream) -> TokenStream { input }
78+
pub fn foo9(input: TokenStream) -> TokenStream {
79+
input
80+
}
6281

6382
#[proc_macro_derive(PartialEq)] // OK
64-
pub fn foo10(input: TokenStream) -> TokenStream { input }
83+
pub fn foo10(input: TokenStream) -> TokenStream {
84+
input
85+
}
6586

6687
#[proc_macro_derive(d11, a)]
6788
//~^ ERROR malformed `proc_macro_derive` attribute
6889
//~| NOTE the only valid argument here is `attributes`
6990
//~| NOTE for more information, visit
70-
pub fn foo11(input: TokenStream) -> TokenStream { input }
91+
pub fn foo11(input: TokenStream) -> TokenStream {
92+
input
93+
}
7194

7295
#[proc_macro_derive(d12, attributes)]
7396
//~^ ERROR malformed `proc_macro_derive` attribute
7497
//~| NOTE expected this to be a list
7598
//~| NOTE for more information, visit
76-
pub fn foo12(input: TokenStream) -> TokenStream { input }
99+
pub fn foo12(input: TokenStream) -> TokenStream {
100+
input
101+
}
77102

78103
#[proc_macro_derive(d13, attributes("a"))]
79104
//~^ ERROR malformed `proc_macro_derive` attribute
80105
//~| NOTE expected a valid identifier here
81106
//~| NOTE for more information, visit
82-
pub fn foo13(input: TokenStream) -> TokenStream { input }
107+
pub fn foo13(input: TokenStream) -> TokenStream {
108+
input
109+
}
83110

84111
#[proc_macro_derive(d14, attributes(a = ""))]
85112
//~^ ERROR malformed `proc_macro_derive` attribute
86113
//~| NOTE didn't expect any arguments here
87114
//~| NOTE for more information, visit
88-
pub fn foo14(input: TokenStream) -> TokenStream { input }
115+
pub fn foo14(input: TokenStream) -> TokenStream {
116+
input
117+
}
89118

90119
#[proc_macro_derive(d15, attributes(m::a))]
91120
//~^ ERROR malformed `proc_macro_derive` attribute
92121
//~| NOTE expected a valid identifier here
93122
//~| NOTE for more information, visit
94-
pub fn foo15(input: TokenStream) -> TokenStream { input }
123+
pub fn foo15(input: TokenStream) -> TokenStream {
124+
input
125+
}
95126

96127
#[proc_macro_derive(d16, attributes(a(b)))]
97128
//~^ ERROR malformed `proc_macro_derive` attribute
98129
//~| NOTE didn't expect any arguments here
99130
//~| NOTE for more information, visit
100-
pub fn foo16(input: TokenStream) -> TokenStream { input }
131+
pub fn foo16(input: TokenStream) -> TokenStream {
132+
input
133+
}
101134

102135
#[proc_macro_derive(d17, attributes(self))]
103136
//~^ ERROR malformed `proc_macro_derive` attribute
104137
//~| NOTE expected a valid identifier here
105138
//~| NOTE for more information, visit
106-
pub fn foo17(input: TokenStream) -> TokenStream { input }
139+
pub fn foo17(input: TokenStream) -> TokenStream {
140+
input
141+
}

tests/ui/proc-macro/attribute.stderr

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
1313
| ++++++++++++++++++++++++++++++++++++++++++
1414

1515
error[E0539]: malformed `proc_macro_derive` attribute input
16-
--> $DIR/attribute.rs:15:1
16+
--> $DIR/attribute.rs:17:1
1717
|
1818
LL | #[proc_macro_derive = ""]
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected this to be a list
@@ -29,7 +29,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
2929
|
3030

3131
error[E0539]: malformed `proc_macro_derive` attribute input
32-
--> $DIR/attribute.rs:21:1
32+
--> $DIR/attribute.rs:25:1
3333
|
3434
LL | #[proc_macro_derive(d3, a, b)]
3535
| ^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^
@@ -46,13 +46,14 @@ LL - #[proc_macro_derive(d3, a, b)]
4646
LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
4747
|
4848

49-
error[E0565]: malformed `proc_macro_derive` attribute input
50-
--> $DIR/attribute.rs:27:1
49+
error[E0539]: malformed `proc_macro_derive` attribute input
50+
--> $DIR/attribute.rs:33:1
5151
|
5252
LL | #[proc_macro_derive(d4, attributes(a), b)]
53-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
54-
| |
55-
| didn't expect any arguments here
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^-------------^^-^^
54+
| | |
55+
| | remove this argument
56+
| expected no more arguments after this
5657
|
5758
= note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros>
5859
help: try changing it to one of the following valid forms of the attribute
@@ -65,7 +66,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
6566
|
6667

6768
error[E0565]: malformed `proc_macro_derive` attribute input
68-
--> $DIR/attribute.rs:33:1
69+
--> $DIR/attribute.rs:42:1
6970
|
7071
LL | #[proc_macro_derive("a")]
7172
| ^^^^^^^^^^^^^^^^^^^^---^^
@@ -83,7 +84,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
8384
|
8485

8586
error[E0565]: malformed `proc_macro_derive` attribute input
86-
--> $DIR/attribute.rs:39:1
87+
--> $DIR/attribute.rs:50:1
8788
|
8889
LL | #[proc_macro_derive(d6 = "")]
8990
| ^^^^^^^^^^^^^^^^^^^^^^^----^^
@@ -101,7 +102,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
101102
|
102103

103104
error[E0539]: malformed `proc_macro_derive` attribute input
104-
--> $DIR/attribute.rs:45:1
105+
--> $DIR/attribute.rs:58:1
105106
|
106107
LL | #[proc_macro_derive(m::d7)]
107108
| ^^^^^^^^^^^^^^^^^^^^-----^^
@@ -119,7 +120,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
119120
|
120121

121122
error[E0565]: malformed `proc_macro_derive` attribute input
122-
--> $DIR/attribute.rs:51:1
123+
--> $DIR/attribute.rs:66:1
123124
|
124125
LL | #[proc_macro_derive(d8(a))]
125126
| ^^^^^^^^^^^^^^^^^^^^^^---^^
@@ -137,7 +138,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
137138
|
138139

139140
error[E0539]: malformed `proc_macro_derive` attribute input
140-
--> $DIR/attribute.rs:57:1
141+
--> $DIR/attribute.rs:74:1
141142
|
142143
LL | #[proc_macro_derive(self)]
143144
| ^^^^^^^^^^^^^^^^^^^^----^^
@@ -155,7 +156,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
155156
|
156157

157158
error[E0539]: malformed `proc_macro_derive` attribute input
158-
--> $DIR/attribute.rs:66:1
159+
--> $DIR/attribute.rs:87:1
159160
|
160161
LL | #[proc_macro_derive(d11, a)]
161162
| ^^^^^^^^^^^^^^^^^^^^^^^^^-^^
@@ -173,7 +174,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
173174
|
174175

175176
error[E0539]: malformed `proc_macro_derive` attribute input
176-
--> $DIR/attribute.rs:72:1
177+
--> $DIR/attribute.rs:95:1
177178
|
178179
LL | #[proc_macro_derive(d12, attributes)]
179180
| ^^^^^^^^^^^^^^^^^^^^^^^^^----------^^
@@ -191,7 +192,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
191192
|
192193

193194
error[E0539]: malformed `proc_macro_derive` attribute input
194-
--> $DIR/attribute.rs:78:1
195+
--> $DIR/attribute.rs:103:1
195196
|
196197
LL | #[proc_macro_derive(d13, attributes("a"))]
197198
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^
@@ -209,7 +210,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
209210
|
210211

211212
error[E0565]: malformed `proc_macro_derive` attribute input
212-
--> $DIR/attribute.rs:84:1
213+
--> $DIR/attribute.rs:111:1
213214
|
214215
LL | #[proc_macro_derive(d14, attributes(a = ""))]
215216
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^
@@ -227,7 +228,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
227228
|
228229

229230
error[E0539]: malformed `proc_macro_derive` attribute input
230-
--> $DIR/attribute.rs:90:1
231+
--> $DIR/attribute.rs:119:1
231232
|
232233
LL | #[proc_macro_derive(d15, attributes(m::a))]
233234
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^
@@ -245,7 +246,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
245246
|
246247

247248
error[E0565]: malformed `proc_macro_derive` attribute input
248-
--> $DIR/attribute.rs:96:1
249+
--> $DIR/attribute.rs:127:1
249250
|
250251
LL | #[proc_macro_derive(d16, attributes(a(b)))]
251252
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^
@@ -263,7 +264,7 @@ LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
263264
|
264265

265266
error[E0539]: malformed `proc_macro_derive` attribute input
266-
--> $DIR/attribute.rs:102:1
267+
--> $DIR/attribute.rs:135:1
267268
|
268269
LL | #[proc_macro_derive(d17, attributes(self))]
269270
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^

0 commit comments

Comments
 (0)