Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate rustc_macros to syn 2.0 #109663

Merged
merged 4 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ dependencies = [
"proc-macro2",
"quote",
"syn 1.0.102",
"synstructure",
"synstructure 0.12.6",
]

[[package]]
Expand Down Expand Up @@ -4994,8 +4994,8 @@ dependencies = [
"fluent-syntax",
"proc-macro2",
"quote",
"syn 1.0.102",
"synstructure",
"syn 2.0.8",
"synstructure 0.13.0",
"unic-langid",
]

Expand Down Expand Up @@ -6131,6 +6131,18 @@ dependencies = [
"unicode-xid",
]

[[package]]
name = "synstructure"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.8",
"unicode-xid",
]

[[package]]
name = "tar"
version = "0.4.38"
Expand Down Expand Up @@ -7154,7 +7166,7 @@ dependencies = [
"proc-macro2",
"quote",
"syn 1.0.102",
"synstructure",
"synstructure 0.12.6",
]

[[package]]
Expand All @@ -7175,7 +7187,7 @@ dependencies = [
"proc-macro2",
"quote",
"syn 1.0.102",
"synstructure",
"synstructure 0.12.6",
]

[[package]]
Expand Down Expand Up @@ -7204,5 +7216,5 @@ dependencies = [
"proc-macro2",
"quote",
"syn 1.0.102",
"synstructure",
"synstructure 0.12.6",
]
4 changes: 2 additions & 2 deletions compiler/rustc_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ proc-macro = true
annotate-snippets = "0.9"
fluent-bundle = "0.15.2"
fluent-syntax = "0.11"
synstructure = "0.12.1"
syn = { version = "1", features = ["full"] }
synstructure = "0.13.0"
syn = { version = "2", features = ["full"] }
proc-macro2 = "1"
quote = "1"
unic-langid = { version = "0.9.0", features = ["macros"] }
157 changes: 67 additions & 90 deletions compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#![deny(unused_must_use)]

use crate::diagnostics::error::{
invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
DiagnosticDeriveError,
span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
};
use crate::diagnostics::utils::{
build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
Expand All @@ -11,9 +10,8 @@ use crate::diagnostics::utils::{
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote};
use syn::{
parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type,
};
use syn::Token;
use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
use synstructure::{BindingInfo, Structure, VariantInfo};

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

Expand Down Expand Up @@ -160,8 +158,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
};

if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
let meta = attr.parse_meta()?;
throw_invalid_attr!(attr, &meta, |diag| diag
throw_invalid_attr!(attr, |diag| diag
.help("consider creating a `Subdiagnostic` instead"));
}

Expand Down Expand Up @@ -191,71 +188,44 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
return Ok(quote! {});
}

let name = attr.path.segments.last().unwrap().ident.to_string();
let name = attr.path().segments.last().unwrap().ident.to_string();
let name = name.as_str();
let meta = attr.parse_meta()?;

if name == "diag" {
let Meta::List(MetaList { ref nested, .. }) = meta else {
throw_invalid_attr!(
attr,
&meta
);
};
let mut first = true;

let mut nested_iter = nested.into_iter().peekable();
if name == "diag" {
let mut tokens = TokenStream::new();
attr.parse_nested_meta(|nested| {
let path = &nested.path;

match nested_iter.peek() {
Some(NestedMeta::Meta(Meta::Path(slug))) => {
self.slug.set_once(slug.clone(), slug.span().unwrap());
nested_iter.next();
if first && (nested.input.is_empty() || nested.input.peek(Token![,])) {
self.slug.set_once(path.clone(), path.span().unwrap());
first = false;
return Ok(())
}
Some(NestedMeta::Meta(Meta::NameValue { .. })) => {}
Some(nested_attr) => throw_invalid_nested_attr!(attr, nested_attr, |diag| diag
.help("a diagnostic slug is required as the first argument")),
None => throw_invalid_attr!(attr, &meta, |diag| diag
.help("a diagnostic slug is required as the first argument")),
};

// Remaining attributes are optional, only `code = ".."` at the moment.
let mut tokens = TokenStream::new();
for nested_attr in nested_iter {
let (value, path) = match nested_attr {
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
lit: syn::Lit::Str(value),
path,
..
})) => (value, path),
NestedMeta::Meta(Meta::Path(_)) => {
invalid_nested_attr(attr, nested_attr)
.help("diagnostic slug must be the first argument")
.emit();
continue;
}
_ => {
invalid_nested_attr(attr, nested_attr).emit();
continue;
}
first = false;

let Ok(nested) = nested.value() else {
span_err(nested.input.span().unwrap(), "diagnostic slug must be the first argument").emit();
return Ok(())
};

let nested_name = path.segments.last().unwrap().ident.to_string();
// Struct attributes are only allowed to be applied once, and the diagnostic
// changes will be set in the initialisation code.
let span = value.span().unwrap();
match nested_name.as_str() {
"code" => {
self.code.set_once((), span);

let code = value.value();
tokens.extend(quote! {
#diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
});
}
_ => invalid_nested_attr(attr, nested_attr)
.help("only `code` is a valid nested attributes following the slug")
.emit(),
if path.is_ident("code") {
self.code.set_once((), path.span().unwrap());

let code = nested.parse::<syn::LitStr>()?;
tokens.extend(quote! {
#diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
});
} else {
span_err(path.span().unwrap(), "unknown argument").note("only the `code` parameter is valid after the slug").emit();

// consume the buffer so we don't have syntax errors from syn
let _ = nested.parse::<TokenStream>();
}
}
Ok(())
})?;
return Ok(tokens);
}

Expand All @@ -270,7 +240,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
Ok(self.add_subdiagnostic(&fn_ident, slug))
}
SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
throw_invalid_attr!(attr, &meta, |diag| diag
throw_invalid_attr!(attr, |diag| diag
.help("`#[label]` and `#[suggestion]` can only be applied to fields"));
}
SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
Expand Down Expand Up @@ -309,7 +279,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
return quote! {};
}

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

let ident = &attr.path.segments.last().unwrap().ident;
let ident = &attr.path().segments.last().unwrap().ident;
let name = ident.to_string();
match (&meta, name.as_str()) {
match (&attr.meta, name.as_str()) {
// Don't need to do anything - by virtue of the attribute existing, the
// `set_arg` call will not be generated.
(Meta::Path(_), "skip_arg") => return Ok(quote! {}),
Expand All @@ -361,7 +330,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
});
}
DiagnosticDeriveKind::LintDiagnostic => {
throw_invalid_attr!(attr, &meta, |diag| {
throw_invalid_attr!(attr, |diag| {
diag.help("the `primary_span` field attribute is not valid for lint diagnostics")
})
}
Expand All @@ -378,26 +347,34 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
return Ok(quote! { #diag.subdiagnostic(#binding); });
}
}
(Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
if nested.len() == 1
&& let Some(NestedMeta::Meta(Meta::Path(path))) = nested.first()
&& path.is_ident("eager") {
let handler = match &self.parent.kind {
DiagnosticDeriveKind::Diagnostic { handler } => handler,
DiagnosticDeriveKind::LintDiagnostic => {
throw_invalid_attr!(attr, &meta, |diag| {
diag.help("eager subdiagnostics are not supported on lints")
})
}
};
return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
} else {
throw_invalid_attr!(attr, &meta, |diag| {
diag.help(
"`eager` is the only supported nested attribute for `subdiagnostic`",
)
})
(Meta::List(meta_list), "subdiagnostic") => {
let err = || {
span_err(
meta_list.span().unwrap(),
"`eager` is the only supported nested attribute for `subdiagnostic`",
)
.emit();
};

let Ok(p): Result<Path, _> = meta_list.parse_args() else {
err();
return Ok(quote! {});
};

if !p.is_ident("eager") {
err();
return Ok(quote! {});
}

let handler = match &self.parent.kind {
DiagnosticDeriveKind::Diagnostic { handler } => handler,
DiagnosticDeriveKind::LintDiagnostic => {
throw_invalid_attr!(attr, |diag| {
diag.help("eager subdiagnostics are not supported on lints")
})
}
};
return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
}
_ => (),
}
Expand Down Expand Up @@ -432,7 +409,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
code_init,
} => {
if let FieldInnerTy::Vec(_) = info.ty {
throw_invalid_attr!(attr, &meta, |diag| {
throw_invalid_attr!(attr, |diag| {
diag
.note("`#[suggestion(...)]` applied to `Vec` field is ambiguous")
.help("to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`")
Expand Down
Loading