Skip to content

Commit 32ea4bb

Browse files
committed
Auto merge of #109663 - fee1-dead-contrib:rustc_macros-syn-2.0, r=Nilstrieb
migrate rustc_macros to syn 2.0 WIP at this point since I need to work on migrating the code that heavily uses `NestedMeta` for parsing. Perhaps a full refactor would be nice..
2 parents c934ce9 + d764c2d commit 32ea4bb

15 files changed

+655
-694
lines changed

Cargo.lock

+18-6
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ dependencies = [
632632
"proc-macro2",
633633
"quote",
634634
"syn 1.0.102",
635-
"synstructure",
635+
"synstructure 0.12.6",
636636
]
637637

638638
[[package]]
@@ -4994,8 +4994,8 @@ dependencies = [
49944994
"fluent-syntax",
49954995
"proc-macro2",
49964996
"quote",
4997-
"syn 1.0.102",
4998-
"synstructure",
4997+
"syn 2.0.8",
4998+
"synstructure 0.13.0",
49994999
"unic-langid",
50005000
]
50015001

@@ -6131,6 +6131,18 @@ dependencies = [
61316131
"unicode-xid",
61326132
]
61336133

6134+
[[package]]
6135+
name = "synstructure"
6136+
version = "0.13.0"
6137+
source = "registry+https://github.com/rust-lang/crates.io-index"
6138+
checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
6139+
dependencies = [
6140+
"proc-macro2",
6141+
"quote",
6142+
"syn 2.0.8",
6143+
"unicode-xid",
6144+
]
6145+
61346146
[[package]]
61356147
name = "tar"
61366148
version = "0.4.38"
@@ -7154,7 +7166,7 @@ dependencies = [
71547166
"proc-macro2",
71557167
"quote",
71567168
"syn 1.0.102",
7157-
"synstructure",
7169+
"synstructure 0.12.6",
71587170
]
71597171

71607172
[[package]]
@@ -7175,7 +7187,7 @@ dependencies = [
71757187
"proc-macro2",
71767188
"quote",
71777189
"syn 1.0.102",
7178-
"synstructure",
7190+
"synstructure 0.12.6",
71797191
]
71807192

71817193
[[package]]
@@ -7204,5 +7216,5 @@ dependencies = [
72047216
"proc-macro2",
72057217
"quote",
72067218
"syn 1.0.102",
7207-
"synstructure",
7219+
"synstructure 0.12.6",
72087220
]

compiler/rustc_macros/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ proc-macro = true
1010
annotate-snippets = "0.9"
1111
fluent-bundle = "0.15.2"
1212
fluent-syntax = "0.11"
13-
synstructure = "0.12.1"
14-
syn = { version = "1", features = ["full"] }
13+
synstructure = "0.13.0"
14+
syn = { version = "2", features = ["full"] }
1515
proc-macro2 = "1"
1616
quote = "1"
1717
unic-langid = { version = "0.9.0", features = ["macros"] }

compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs

+67-90
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#![deny(unused_must_use)]
22

33
use crate::diagnostics::error::{
4-
invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
5-
DiagnosticDeriveError,
4+
span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
65
};
76
use crate::diagnostics::utils::{
87
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
@@ -11,9 +10,8 @@ use crate::diagnostics::utils::{
1110
};
1211
use proc_macro2::{Ident, Span, TokenStream};
1312
use quote::{format_ident, quote};
14-
use syn::{
15-
parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type,
16-
};
13+
use syn::Token;
14+
use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
1715
use synstructure::{BindingInfo, Structure, VariantInfo};
1816

1917
/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
@@ -77,7 +75,7 @@ impl DiagnosticDeriveBuilder {
7775
match ast.data {
7876
syn::Data::Struct(..) | syn::Data::Enum(..) => (),
7977
syn::Data::Union(..) => {
80-
span_err(span, "diagnostic derives can only be used on structs and enums");
78+
span_err(span, "diagnostic derives can only be used on structs and enums").emit();
8179
}
8280
}
8381

@@ -160,8 +158,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
160158
};
161159

162160
if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
163-
let meta = attr.parse_meta()?;
164-
throw_invalid_attr!(attr, &meta, |diag| diag
161+
throw_invalid_attr!(attr, |diag| diag
165162
.help("consider creating a `Subdiagnostic` instead"));
166163
}
167164

@@ -191,71 +188,44 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
191188
return Ok(quote! {});
192189
}
193190

194-
let name = attr.path.segments.last().unwrap().ident.to_string();
191+
let name = attr.path().segments.last().unwrap().ident.to_string();
195192
let name = name.as_str();
196-
let meta = attr.parse_meta()?;
197193

198-
if name == "diag" {
199-
let Meta::List(MetaList { ref nested, .. }) = meta else {
200-
throw_invalid_attr!(
201-
attr,
202-
&meta
203-
);
204-
};
194+
let mut first = true;
205195

206-
let mut nested_iter = nested.into_iter().peekable();
196+
if name == "diag" {
197+
let mut tokens = TokenStream::new();
198+
attr.parse_nested_meta(|nested| {
199+
let path = &nested.path;
207200

208-
match nested_iter.peek() {
209-
Some(NestedMeta::Meta(Meta::Path(slug))) => {
210-
self.slug.set_once(slug.clone(), slug.span().unwrap());
211-
nested_iter.next();
201+
if first && (nested.input.is_empty() || nested.input.peek(Token![,])) {
202+
self.slug.set_once(path.clone(), path.span().unwrap());
203+
first = false;
204+
return Ok(())
212205
}
213-
Some(NestedMeta::Meta(Meta::NameValue { .. })) => {}
214-
Some(nested_attr) => throw_invalid_nested_attr!(attr, nested_attr, |diag| diag
215-
.help("a diagnostic slug is required as the first argument")),
216-
None => throw_invalid_attr!(attr, &meta, |diag| diag
217-
.help("a diagnostic slug is required as the first argument")),
218-
};
219206

220-
// Remaining attributes are optional, only `code = ".."` at the moment.
221-
let mut tokens = TokenStream::new();
222-
for nested_attr in nested_iter {
223-
let (value, path) = match nested_attr {
224-
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
225-
lit: syn::Lit::Str(value),
226-
path,
227-
..
228-
})) => (value, path),
229-
NestedMeta::Meta(Meta::Path(_)) => {
230-
invalid_nested_attr(attr, nested_attr)
231-
.help("diagnostic slug must be the first argument")
232-
.emit();
233-
continue;
234-
}
235-
_ => {
236-
invalid_nested_attr(attr, nested_attr).emit();
237-
continue;
238-
}
207+
first = false;
208+
209+
let Ok(nested) = nested.value() else {
210+
span_err(nested.input.span().unwrap(), "diagnostic slug must be the first argument").emit();
211+
return Ok(())
239212
};
240213

241-
let nested_name = path.segments.last().unwrap().ident.to_string();
242-
// Struct attributes are only allowed to be applied once, and the diagnostic
243-
// changes will be set in the initialisation code.
244-
let span = value.span().unwrap();
245-
match nested_name.as_str() {
246-
"code" => {
247-
self.code.set_once((), span);
248-
249-
let code = value.value();
250-
tokens.extend(quote! {
251-
#diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
252-
});
253-
}
254-
_ => invalid_nested_attr(attr, nested_attr)
255-
.help("only `code` is a valid nested attributes following the slug")
256-
.emit(),
214+
if path.is_ident("code") {
215+
self.code.set_once((), path.span().unwrap());
216+
217+
let code = nested.parse::<syn::LitStr>()?;
218+
tokens.extend(quote! {
219+
#diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
220+
});
221+
} else {
222+
span_err(path.span().unwrap(), "unknown argument").note("only the `code` parameter is valid after the slug").emit();
223+
224+
// consume the buffer so we don't have syntax errors from syn
225+
let _ = nested.parse::<TokenStream>();
257226
}
258-
}
227+
Ok(())
228+
})?;
259229
return Ok(tokens);
260230
}
261231

@@ -270,7 +240,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
270240
Ok(self.add_subdiagnostic(&fn_ident, slug))
271241
}
272242
SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
273-
throw_invalid_attr!(attr, &meta, |diag| diag
243+
throw_invalid_attr!(attr, |diag| diag
274244
.help("`#[label]` and `#[suggestion]` can only be applied to fields"));
275245
}
276246
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
@@ -309,7 +279,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
309279
return quote! {};
310280
}
311281

312-
let name = attr.path.segments.last().unwrap().ident.to_string();
282+
let name = attr.path().segments.last().unwrap().ident.to_string();
313283
let needs_clone =
314284
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
315285
let (binding, needs_destructure) = if needs_clone {
@@ -343,11 +313,10 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
343313
binding: TokenStream,
344314
) -> Result<TokenStream, DiagnosticDeriveError> {
345315
let diag = &self.parent.diag;
346-
let meta = attr.parse_meta()?;
347316

348-
let ident = &attr.path.segments.last().unwrap().ident;
317+
let ident = &attr.path().segments.last().unwrap().ident;
349318
let name = ident.to_string();
350-
match (&meta, name.as_str()) {
319+
match (&attr.meta, name.as_str()) {
351320
// Don't need to do anything - by virtue of the attribute existing, the
352321
// `set_arg` call will not be generated.
353322
(Meta::Path(_), "skip_arg") => return Ok(quote! {}),
@@ -361,7 +330,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
361330
});
362331
}
363332
DiagnosticDeriveKind::LintDiagnostic => {
364-
throw_invalid_attr!(attr, &meta, |diag| {
333+
throw_invalid_attr!(attr, |diag| {
365334
diag.help("the `primary_span` field attribute is not valid for lint diagnostics")
366335
})
367336
}
@@ -378,26 +347,34 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
378347
return Ok(quote! { #diag.subdiagnostic(#binding); });
379348
}
380349
}
381-
(Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
382-
if nested.len() == 1
383-
&& let Some(NestedMeta::Meta(Meta::Path(path))) = nested.first()
384-
&& path.is_ident("eager") {
385-
let handler = match &self.parent.kind {
386-
DiagnosticDeriveKind::Diagnostic { handler } => handler,
387-
DiagnosticDeriveKind::LintDiagnostic => {
388-
throw_invalid_attr!(attr, &meta, |diag| {
389-
diag.help("eager subdiagnostics are not supported on lints")
390-
})
391-
}
392-
};
393-
return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
394-
} else {
395-
throw_invalid_attr!(attr, &meta, |diag| {
396-
diag.help(
397-
"`eager` is the only supported nested attribute for `subdiagnostic`",
398-
)
399-
})
350+
(Meta::List(meta_list), "subdiagnostic") => {
351+
let err = || {
352+
span_err(
353+
meta_list.span().unwrap(),
354+
"`eager` is the only supported nested attribute for `subdiagnostic`",
355+
)
356+
.emit();
357+
};
358+
359+
let Ok(p): Result<Path, _> = meta_list.parse_args() else {
360+
err();
361+
return Ok(quote! {});
362+
};
363+
364+
if !p.is_ident("eager") {
365+
err();
366+
return Ok(quote! {});
400367
}
368+
369+
let handler = match &self.parent.kind {
370+
DiagnosticDeriveKind::Diagnostic { handler } => handler,
371+
DiagnosticDeriveKind::LintDiagnostic => {
372+
throw_invalid_attr!(attr, |diag| {
373+
diag.help("eager subdiagnostics are not supported on lints")
374+
})
375+
}
376+
};
377+
return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
401378
}
402379
_ => (),
403380
}
@@ -432,7 +409,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
432409
code_init,
433410
} => {
434411
if let FieldInnerTy::Vec(_) = info.ty {
435-
throw_invalid_attr!(attr, &meta, |diag| {
412+
throw_invalid_attr!(attr, |diag| {
436413
diag
437414
.note("`#[suggestion(...)]` applied to `Vec` field is ambiguous")
438415
.help("to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`")

0 commit comments

Comments
 (0)