Skip to content

Commit 1045e69

Browse files
committed
macros: allow subdiagnostic-kind-less variants
Sometimes it is convenient to return a subdiagnostic enum where one or more of the variants don't add anything to the diagnostic. Signed-off-by: David Wood <david.wood@huawei.com>
1 parent 7fbaf27 commit 1045e69

File tree

3 files changed

+59
-55
lines changed

3 files changed

+59
-55
lines changed

compiler/rustc_macros/src/diagnostics/subdiagnostic.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ impl SubdiagnosticDeriveBuilder {
4141
}
4242
}
4343

44-
if matches!(ast.data, syn::Data::Enum(..)) {
44+
let is_enum = matches!(ast.data, syn::Data::Enum(..));
45+
if is_enum {
4546
for attr in &ast.attrs {
4647
// Always allow documentation comments.
4748
if is_doc_comment(attr) {
@@ -67,6 +68,7 @@ impl SubdiagnosticDeriveBuilder {
6768
span_field: None,
6869
applicability: None,
6970
has_suggestion_parts: false,
71+
is_enum,
7072
};
7173
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
7274
});
@@ -127,6 +129,9 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
127129
/// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
128130
/// during finalization if still `false`.
129131
has_suggestion_parts: bool,
132+
133+
/// Set to true when this variant is an enum variant rather than just the body of a struct.
134+
is_enum: bool,
130135
}
131136

132137
impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
@@ -457,10 +462,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
457462
pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
458463
let kind_slugs = self.identify_kind()?;
459464
if kind_slugs.is_empty() {
460-
throw_span_err!(
461-
self.variant.ast().ident.span().unwrap(),
462-
"subdiagnostic kind not specified"
463-
);
465+
if self.is_enum {
466+
// It's okay for a variant to not be a subdiagnostic at all..
467+
return Ok(quote! {});
468+
} else {
469+
// ..but structs should always be _something_.
470+
throw_span_err!(
471+
self.variant.ast().ident.span().unwrap(),
472+
"subdiagnostic kind not specified"
473+
);
474+
}
464475
};
465476

466477
let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();

src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ enum V {
237237
var: String,
238238
},
239239
B {
240-
//~^ ERROR subdiagnostic kind not specified
241240
#[primary_span]
242241
span: Span,
243242
var: String,

src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr

Lines changed: 43 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -134,20 +134,14 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
134134
LL | #[label(code = "...")]
135135
| ^^^^^^^^^^^^^^^^^^^^^^
136136

137-
error: subdiagnostic kind not specified
138-
--> $DIR/subdiagnostic-derive.rs:239:5
139-
|
140-
LL | B {
141-
| ^
142-
143137
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
144-
--> $DIR/subdiagnostic-derive.rs:251:5
138+
--> $DIR/subdiagnostic-derive.rs:250:5
145139
|
146140
LL | #[primary_span]
147141
| ^^^^^^^^^^^^^^^
148142

149143
error: label without `#[primary_span]` field
150-
--> $DIR/subdiagnostic-derive.rs:248:1
144+
--> $DIR/subdiagnostic-derive.rs:247:1
151145
|
152146
LL | / #[label(parser::add_paren)]
153147
LL | |
@@ -159,35 +153,35 @@ LL | | }
159153
| |_^
160154

161155
error: `#[applicability]` is only valid on suggestions
162-
--> $DIR/subdiagnostic-derive.rs:261:5
156+
--> $DIR/subdiagnostic-derive.rs:260:5
163157
|
164158
LL | #[applicability]
165159
| ^^^^^^^^^^^^^^^^
166160

167161
error: `#[bar]` is not a valid attribute
168-
--> $DIR/subdiagnostic-derive.rs:271:5
162+
--> $DIR/subdiagnostic-derive.rs:270:5
169163
|
170164
LL | #[bar]
171165
| ^^^^^^
172166
|
173167
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
174168

175169
error: `#[bar = ...]` is not a valid attribute
176-
--> $DIR/subdiagnostic-derive.rs:282:5
170+
--> $DIR/subdiagnostic-derive.rs:281:5
177171
|
178172
LL | #[bar = "..."]
179173
| ^^^^^^^^^^^^^^
180174

181175
error: `#[bar(...)]` is not a valid attribute
182-
--> $DIR/subdiagnostic-derive.rs:293:5
176+
--> $DIR/subdiagnostic-derive.rs:292:5
183177
|
184178
LL | #[bar("...")]
185179
| ^^^^^^^^^^^^^
186180
|
187181
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
188182

189183
error: unexpected unsupported untagged union
190-
--> $DIR/subdiagnostic-derive.rs:309:1
184+
--> $DIR/subdiagnostic-derive.rs:308:1
191185
|
192186
LL | / union AC {
193187
LL | |
@@ -197,75 +191,75 @@ LL | | }
197191
| |_^
198192

199193
error: `#[label(parser::add_paren)]` is not a valid attribute
200-
--> $DIR/subdiagnostic-derive.rs:324:28
194+
--> $DIR/subdiagnostic-derive.rs:323:28
201195
|
202196
LL | #[label(parser::add_paren, parser::add_paren)]
203197
| ^^^^^^^^^^^^^^^^^
204198
|
205199
= help: a diagnostic slug must be the first argument to the attribute
206200

207201
error: specified multiple times
208-
--> $DIR/subdiagnostic-derive.rs:337:5
202+
--> $DIR/subdiagnostic-derive.rs:336:5
209203
|
210204
LL | #[primary_span]
211205
| ^^^^^^^^^^^^^^^
212206
|
213207
note: previously specified here
214-
--> $DIR/subdiagnostic-derive.rs:334:5
208+
--> $DIR/subdiagnostic-derive.rs:333:5
215209
|
216210
LL | #[primary_span]
217211
| ^^^^^^^^^^^^^^^
218212

219213
error: subdiagnostic kind not specified
220-
--> $DIR/subdiagnostic-derive.rs:343:8
214+
--> $DIR/subdiagnostic-derive.rs:342:8
221215
|
222216
LL | struct AG {
223217
| ^^
224218

225219
error: specified multiple times
226-
--> $DIR/subdiagnostic-derive.rs:380:47
220+
--> $DIR/subdiagnostic-derive.rs:379:47
227221
|
228222
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
229223
| ^^^^^^^^^^^^
230224
|
231225
note: previously specified here
232-
--> $DIR/subdiagnostic-derive.rs:380:33
226+
--> $DIR/subdiagnostic-derive.rs:379:33
233227
|
234228
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
235229
| ^^^^^^^^^^^^
236230

237231
error: specified multiple times
238-
--> $DIR/subdiagnostic-derive.rs:398:5
232+
--> $DIR/subdiagnostic-derive.rs:397:5
239233
|
240234
LL | #[applicability]
241235
| ^^^^^^^^^^^^^^^^
242236
|
243237
note: previously specified here
244-
--> $DIR/subdiagnostic-derive.rs:395:5
238+
--> $DIR/subdiagnostic-derive.rs:394:5
245239
|
246240
LL | #[applicability]
247241
| ^^^^^^^^^^^^^^^^
248242

249243
error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
250-
--> $DIR/subdiagnostic-derive.rs:408:5
244+
--> $DIR/subdiagnostic-derive.rs:407:5
251245
|
252246
LL | #[applicability]
253247
| ^^^^^^^^^^^^^^^^
254248

255249
error: suggestion without `code = "..."`
256-
--> $DIR/subdiagnostic-derive.rs:421:1
250+
--> $DIR/subdiagnostic-derive.rs:420:1
257251
|
258252
LL | #[suggestion(parser::add_paren)]
259253
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
260254

261255
error: invalid applicability
262-
--> $DIR/subdiagnostic-derive.rs:431:46
256+
--> $DIR/subdiagnostic-derive.rs:430:46
263257
|
264258
LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
265259
| ^^^^^^^^^^^^^^^^^^^^^
266260

267261
error: suggestion without `#[primary_span]` field
268-
--> $DIR/subdiagnostic-derive.rs:449:1
262+
--> $DIR/subdiagnostic-derive.rs:448:1
269263
|
270264
LL | / #[suggestion(parser::add_paren, code = "...")]
271265
LL | |
@@ -275,41 +269,41 @@ LL | | }
275269
| |_^
276270

277271
error: unsupported type attribute for subdiagnostic enum
278-
--> $DIR/subdiagnostic-derive.rs:463:1
272+
--> $DIR/subdiagnostic-derive.rs:462:1
279273
|
280274
LL | #[label]
281275
| ^^^^^^^^
282276

283277
error: `var` doesn't refer to a field on this type
284-
--> $DIR/subdiagnostic-derive.rs:483:39
278+
--> $DIR/subdiagnostic-derive.rs:482:39
285279
|
286280
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
287281
| ^^^^^^^
288282

289283
error: `var` doesn't refer to a field on this type
290-
--> $DIR/subdiagnostic-derive.rs:502:43
284+
--> $DIR/subdiagnostic-derive.rs:501:43
291285
|
292286
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
293287
| ^^^^^^^
294288

295289
error: `#[suggestion_part]` is not a valid attribute
296-
--> $DIR/subdiagnostic-derive.rs:525:5
290+
--> $DIR/subdiagnostic-derive.rs:524:5
297291
|
298292
LL | #[suggestion_part]
299293
| ^^^^^^^^^^^^^^^^^^
300294
|
301295
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
302296

303297
error: `#[suggestion_part(...)]` is not a valid attribute
304-
--> $DIR/subdiagnostic-derive.rs:528:5
298+
--> $DIR/subdiagnostic-derive.rs:527:5
305299
|
306300
LL | #[suggestion_part(code = "...")]
307301
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
308302
|
309303
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions
310304

311305
error: suggestion without `#[primary_span]` field
312-
--> $DIR/subdiagnostic-derive.rs:522:1
306+
--> $DIR/subdiagnostic-derive.rs:521:1
313307
|
314308
LL | / #[suggestion(parser::add_paren, code = "...")]
315309
LL | |
@@ -321,15 +315,15 @@ LL | | }
321315
| |_^
322316

323317
error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
324-
--> $DIR/subdiagnostic-derive.rs:537:43
318+
--> $DIR/subdiagnostic-derive.rs:536:43
325319
|
326320
LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
327321
| ^^^^^^^^^^^^
328322
|
329323
= help: only `applicability` is a valid nested attributes
330324

331325
error: multipart suggestion without any `#[suggestion_part(...)]` fields
332-
--> $DIR/subdiagnostic-derive.rs:537:1
326+
--> $DIR/subdiagnostic-derive.rs:536:1
333327
|
334328
LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
335329
LL | |
@@ -340,27 +334,27 @@ LL | | }
340334
| |_^
341335

342336
error: `#[suggestion_part(...)]` attribute without `code = "..."`
343-
--> $DIR/subdiagnostic-derive.rs:547:5
337+
--> $DIR/subdiagnostic-derive.rs:546:5
344338
|
345339
LL | #[suggestion_part]
346340
| ^^^^^^^^^^^^^^^^^^
347341

348342
error: `#[suggestion_part(...)]` attribute without `code = "..."`
349-
--> $DIR/subdiagnostic-derive.rs:555:5
343+
--> $DIR/subdiagnostic-derive.rs:554:5
350344
|
351345
LL | #[suggestion_part()]
352346
| ^^^^^^^^^^^^^^^^^^^^
353347

354348
error: `#[primary_span]` is not a valid attribute
355-
--> $DIR/subdiagnostic-derive.rs:564:5
349+
--> $DIR/subdiagnostic-derive.rs:563:5
356350
|
357351
LL | #[primary_span]
358352
| ^^^^^^^^^^^^^^^
359353
|
360354
= help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
361355

362356
error: multipart suggestion without any `#[suggestion_part(...)]` fields
363-
--> $DIR/subdiagnostic-derive.rs:561:1
357+
--> $DIR/subdiagnostic-derive.rs:560:1
364358
|
365359
LL | / #[multipart_suggestion(parser::add_paren)]
366360
LL | |
@@ -372,51 +366,51 @@ LL | | }
372366
| |_^
373367

374368
error: `#[suggestion_part(...)]` attribute without `code = "..."`
375-
--> $DIR/subdiagnostic-derive.rs:572:5
369+
--> $DIR/subdiagnostic-derive.rs:571:5
376370
|
377371
LL | #[suggestion_part]
378372
| ^^^^^^^^^^^^^^^^^^
379373

380374
error: `#[suggestion_part(...)]` attribute without `code = "..."`
381-
--> $DIR/subdiagnostic-derive.rs:575:5
375+
--> $DIR/subdiagnostic-derive.rs:574:5
382376
|
383377
LL | #[suggestion_part()]
384378
| ^^^^^^^^^^^^^^^^^^^^
385379

386380
error: `#[suggestion_part(foo = ...)]` is not a valid attribute
387-
--> $DIR/subdiagnostic-derive.rs:578:23
381+
--> $DIR/subdiagnostic-derive.rs:577:23
388382
|
389383
LL | #[suggestion_part(foo = "bar")]
390384
| ^^^^^^^^^^^
391385
|
392386
= help: `code` is the only valid nested attribute
393387

394388
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
395-
--> $DIR/subdiagnostic-derive.rs:581:5
389+
--> $DIR/subdiagnostic-derive.rs:580:5
396390
|
397391
LL | #[suggestion_part(code = "...")]
398392
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
399393

400394
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
401-
--> $DIR/subdiagnostic-derive.rs:584:5
395+
--> $DIR/subdiagnostic-derive.rs:583:5
402396
|
403397
LL | #[suggestion_part()]
404398
| ^^^^^^^^^^^^^^^^^^^^
405399

406400
error: specified multiple times
407-
--> $DIR/subdiagnostic-derive.rs:592:37
401+
--> $DIR/subdiagnostic-derive.rs:591:37
408402
|
409403
LL | #[suggestion_part(code = "...", code = ",,,")]
410404
| ^^^^^^^^^^^^
411405
|
412406
note: previously specified here
413-
--> $DIR/subdiagnostic-derive.rs:592:23
407+
--> $DIR/subdiagnostic-derive.rs:591:23
414408
|
415409
LL | #[suggestion_part(code = "...", code = ",,,")]
416410
| ^^^^^^^^^^^^
417411

418412
error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
419-
--> $DIR/subdiagnostic-derive.rs:621:5
413+
--> $DIR/subdiagnostic-derive.rs:620:5
420414
|
421415
LL | #[applicability]
422416
| ^^^^^^^^^^^^^^^^
@@ -458,19 +452,19 @@ LL | #[bar("...")]
458452
| ^^^
459453

460454
error: cannot find attribute `bar` in this scope
461-
--> $DIR/subdiagnostic-derive.rs:271:7
455+
--> $DIR/subdiagnostic-derive.rs:270:7
462456
|
463457
LL | #[bar]
464458
| ^^^
465459

466460
error: cannot find attribute `bar` in this scope
467-
--> $DIR/subdiagnostic-derive.rs:282:7
461+
--> $DIR/subdiagnostic-derive.rs:281:7
468462
|
469463
LL | #[bar = "..."]
470464
| ^^^
471465

472466
error: cannot find attribute `bar` in this scope
473-
--> $DIR/subdiagnostic-derive.rs:293:7
467+
--> $DIR/subdiagnostic-derive.rs:292:7
474468
|
475469
LL | #[bar("...")]
476470
| ^^^
@@ -481,6 +475,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
481475
LL | #[label(slug)]
482476
| ^^^^ not found in `rustc_errors::fluent`
483477

484-
error: aborting due to 68 previous errors
478+
error: aborting due to 67 previous errors
485479

486480
For more information about this error, try `rustc --explain E0425`.

0 commit comments

Comments
 (0)