summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_macros/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_macros/src')
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic.rs14
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs53
-rw-r--r--compiler/rustc_macros/src/diagnostics/error.rs16
-rw-r--r--compiler/rustc_macros/src/diagnostics/fluent.rs4
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs5
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs10
-rw-r--r--compiler/rustc_macros/src/lib.rs1
-rw-r--r--compiler/rustc_macros/src/newtype.rs155
-rw-r--r--compiler/rustc_macros/src/query.rs2
-rw-r--r--compiler/rustc_macros/src/symbols.rs6
-rw-r--r--compiler/rustc_macros/src/symbols/tests.rs3
-rw-r--r--compiler/rustc_macros/src/type_visitable.rs2
12 files changed, 102 insertions, 169 deletions
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 684835d8c..9ff944864 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -39,10 +39,8 @@ impl<'a> DiagnosticDerive<'a> {
let init = match builder.slug.value_ref() {
None => {
span_err(builder.span, "diagnostic slug not specified")
- .help(format!(
- "specify the slug as the first argument to the `#[diag(...)]` \
- attribute, such as `#[diag(hir_analysis_example_error)]`",
- ))
+ .help("specify the slug as the first argument to the `#[diag(...)]` \
+ attribute, such as `#[diag(hir_analysis_example_error)]`")
.emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
}
@@ -133,10 +131,8 @@ impl<'a> LintDiagnosticDerive<'a> {
match builder.slug.value_ref() {
None => {
span_err(builder.span, "diagnostic slug not specified")
- .help(format!(
- "specify the slug as the first argument to the attribute, such as \
- `#[diag(compiletest_example)]`",
- ))
+ .help("specify the slug as the first argument to the attribute, such as \
+ `#[diag(compiletest_example)]`")
.emit();
DiagnosticDeriveError::ErrorHandled.to_compile_error()
}
@@ -192,7 +188,7 @@ impl Mismatch {
let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
// If we're not in a "rustc_" crate, bail.
- let Some(("rustc", slug_prefix)) = crate_name.split_once("_") else { return None };
+ let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
let slug_name = slug.segments.first()?.ident.to_string();
if !slug_name.starts_with(slug_prefix) {
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 9f2ac5112..e405462bb 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -372,45 +372,36 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
}
}
(Meta::Path(_), "subdiagnostic") => {
- return Ok(quote! { #diag.subdiagnostic(#binding); });
- }
- (Meta::NameValue(_), "subdiagnostic") => {
- throw_invalid_attr!(attr, &meta, |diag| {
- diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
- })
+ if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() {
+ let DiagnosticDeriveKind::Diagnostic { handler } = &self.parent.kind else {
+ // No eager translation for lints.
+ return Ok(quote! { #diag.subdiagnostic(#binding); });
+ };
+ return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
+ } else {
+ return Ok(quote! { #diag.subdiagnostic(#binding); });
+ }
}
(Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
- if nested.len() != 1 {
+ 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`",
)
})
}
-
- 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")
- })
- }
- };
-
- let nested_attr = nested.first().expect("pop failed for single element list");
- match nested_attr {
- NestedMeta::Meta(meta @ Meta::Path(_))
- if meta.path().segments.last().unwrap().ident.to_string().as_str()
- == "eager" =>
- {
- return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
- }
- _ => {
- throw_invalid_nested_attr!(attr, nested_attr, |diag| {
- diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
- })
- }
- }
}
_ => (),
}
diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs
index 4612f54e4..2d62d5931 100644
--- a/compiler/rustc_macros/src/diagnostics/error.rs
+++ b/compiler/rustc_macros/src/diagnostics/error.rs
@@ -76,11 +76,11 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
let span = attr.span().unwrap();
let path = path_to_string(&attr.path);
match meta {
- Meta::Path(_) => span_err(span, &format!("`#[{}]` is not a valid attribute", path)),
+ Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")),
Meta::NameValue(_) => {
- span_err(span, &format!("`#[{} = ...]` is not a valid attribute", path))
+ span_err(span, &format!("`#[{path} = ...]` is not a valid attribute"))
}
- Meta::List(_) => span_err(span, &format!("`#[{}(...)]` is not a valid attribute", path)),
+ Meta::List(_) => span_err(span, &format!("`#[{path}(...)]` is not a valid attribute")),
}
}
@@ -107,7 +107,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag
let meta = match nested {
syn::NestedMeta::Meta(meta) => meta,
syn::NestedMeta::Lit(_) => {
- return span_err(span, &format!("`#[{}(\"...\")]` is not a valid attribute", name));
+ return span_err(span, &format!("`#[{name}(\"...\")]` is not a valid attribute"));
}
};
@@ -115,13 +115,11 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag
let path = path_to_string(meta.path());
match meta {
Meta::NameValue(..) => {
- span_err(span, &format!("`#[{}({} = ...)]` is not a valid attribute", name, path))
- }
- Meta::Path(..) => {
- span_err(span, &format!("`#[{}({})]` is not a valid attribute", name, path))
+ span_err(span, &format!("`#[{name}({path} = ...)]` is not a valid attribute"))
}
+ Meta::Path(..) => span_err(span, &format!("`#[{name}({path})]` is not a valid attribute")),
Meta::List(..) => {
- span_err(span, &format!("`#[{}({}(...))]` is not a valid attribute", name, path))
+ span_err(span, &format!("`#[{name}({path}(...))]` is not a valid attribute"))
}
}
}
diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs
index 3e447c94e..32338f9df 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_macros/src/diagnostics/fluent.rs
@@ -178,7 +178,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
opt: Default::default(),
};
let dl = DisplayList::from(snippet);
- eprintln!("{}\n", dl);
+ eprintln!("{dl}\n");
}
continue;
}
@@ -265,7 +265,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
Diagnostic::spanned(
path_span,
Level::Error,
- format!("overrides existing {}: `{}`", kind, id),
+ format!("overrides existing {kind}: `{id}`"),
)
.span_help(previous_defns[&id], "previously defined in this resource")
.emit();
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 446aebe4f..baffd3cec 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -29,7 +29,7 @@ impl SubdiagnosticDeriveBuilder {
Self { diag, f }
}
- pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream {
+ pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream {
let implementation = {
let ast = structure.ast();
let span = ast.span().unwrap();
@@ -198,8 +198,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
throw_span_err!(
attr.span().unwrap(),
&format!(
- "diagnostic slug must be first argument of a `#[{}(...)]` attribute",
- name
+ "diagnostic slug must be first argument of a `#[{name}(...)]` attribute"
)
);
};
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index da9023352..6f52a3de1 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -322,7 +322,7 @@ pub(crate) trait HasFieldMap {
None => {
span_err(
span.unwrap(),
- &format!("`{}` doesn't refer to a field on this type", field),
+ &format!("`{field}` doesn't refer to a field on this type"),
)
.emit();
quote! {
@@ -385,7 +385,7 @@ impl quote::ToTokens for Applicability {
/// Build the mapping of field names to fields. This allows attributes to peek values from
/// other fields.
-pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap<String, TokenStream> {
+pub(super) fn build_field_mapping(variant: &VariantInfo<'_>) -> HashMap<String, TokenStream> {
let mut fields_map = FieldMap::new();
for binding in variant.bindings() {
if let Some(ident) = &binding.ast().ident {
@@ -603,8 +603,7 @@ impl SubdiagnosticKind {
if suggestion_kind != SuggestionKind::Normal {
invalid_attr(attr, &meta)
.help(format!(
- r#"Use `#[suggestion(..., style = "{}")]` instead"#,
- suggestion_kind
+ r#"Use `#[suggestion(..., style = "{suggestion_kind}")]` instead"#
))
.emit();
}
@@ -621,8 +620,7 @@ impl SubdiagnosticKind {
if suggestion_kind != SuggestionKind::Normal {
invalid_attr(attr, &meta)
.help(format!(
- r#"Use `#[multipart_suggestion(..., style = "{}")]` instead"#,
- suggestion_kind
+ r#"Use `#[multipart_suggestion(..., style = "{suggestion_kind}")]` instead"#
))
.emit();
}
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index ac916bb60..bb3722fe1 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -1,5 +1,6 @@
#![feature(allow_internal_unstable)]
#![feature(if_let_guard)]
+#![feature(let_chains)]
#![feature(never_type)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_span)]
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs
index fd3f52251..89ea89cf5 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_macros/src/newtype.rs
@@ -1,35 +1,15 @@
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::parse::*;
-use syn::punctuated::Punctuated;
use syn::*;
-mod kw {
- syn::custom_keyword!(derive);
- syn::custom_keyword!(DEBUG_FORMAT);
- syn::custom_keyword!(MAX);
- syn::custom_keyword!(ENCODABLE);
- syn::custom_keyword!(custom);
- syn::custom_keyword!(ORD_IMPL);
-}
-
-#[derive(Debug)]
-enum DebugFormat {
- // The user will provide a custom `Debug` impl, so we shouldn't generate
- // one
- Custom,
- // Use the specified format string in the generated `Debug` impl
- // By default, this is "{}"
- Format(String),
-}
-
// We parse the input and emit the output in a single step.
// This field stores the final macro output
struct Newtype(TokenStream);
impl Parse for Newtype {
fn parse(input: ParseStream<'_>) -> Result<Self> {
- let attrs = input.call(Attribute::parse_outer)?;
+ let mut attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
input.parse::<Token![struct]>()?;
let name: Ident = input.parse()?;
@@ -39,93 +19,68 @@ impl Parse for Newtype {
// Any additional `#[derive]` macro paths to apply
let mut derive_paths: Vec<Path> = Vec::new();
- let mut debug_format: Option<DebugFormat> = None;
+ let mut debug_format: Option<Lit> = None;
let mut max = None;
let mut consts = Vec::new();
let mut encodable = true;
let mut ord = true;
- // Parse an optional trailing comma
- let try_comma = || -> Result<()> {
- if body.lookahead1().peek(Token![,]) {
- body.parse::<Token![,]>()?;
- }
- Ok(())
- };
-
- if body.lookahead1().peek(Token![..]) {
- body.parse::<Token![..]>()?;
- } else {
- loop {
- if body.lookahead1().peek(kw::derive) {
- body.parse::<kw::derive>()?;
- let derives;
- bracketed!(derives in body);
- let derives: Punctuated<Path, Token![,]> =
- derives.parse_terminated(Path::parse)?;
- try_comma()?;
- derive_paths.extend(derives);
- continue;
- }
- if body.lookahead1().peek(kw::DEBUG_FORMAT) {
- body.parse::<kw::DEBUG_FORMAT>()?;
- body.parse::<Token![=]>()?;
- let new_debug_format = if body.lookahead1().peek(kw::custom) {
- body.parse::<kw::custom>()?;
- DebugFormat::Custom
- } else {
- let format_str: LitStr = body.parse()?;
- DebugFormat::Format(format_str.value())
- };
- try_comma()?;
- if let Some(old) = debug_format.replace(new_debug_format) {
- panic!("Specified multiple debug format options: {:?}", old);
- }
- continue;
- }
- if body.lookahead1().peek(kw::MAX) {
- body.parse::<kw::MAX>()?;
- body.parse::<Token![=]>()?;
- let val: Lit = body.parse()?;
- try_comma()?;
- if let Some(old) = max.replace(val) {
- panic!("Specified multiple MAX: {:?}", old);
- }
- continue;
- }
- if body.lookahead1().peek(kw::ENCODABLE) {
- body.parse::<kw::ENCODABLE>()?;
- body.parse::<Token![=]>()?;
- body.parse::<kw::custom>()?;
- try_comma()?;
+ attrs.retain(|attr| match attr.path.get_ident() {
+ Some(ident) => match &*ident.to_string() {
+ "custom_encodable" => {
encodable = false;
- continue;
+ false
}
- if body.lookahead1().peek(kw::ORD_IMPL) {
- body.parse::<kw::ORD_IMPL>()?;
- body.parse::<Token![=]>()?;
- body.parse::<kw::custom>()?;
+ "no_ord_impl" => {
ord = false;
- continue;
+ false
}
+ "max" => {
+ let Ok(Meta::NameValue(literal) )= attr.parse_meta() else {
+ panic!("#[max = NUMBER] attribute requires max value");
+ };
+
+ if let Some(old) = max.replace(literal.lit) {
+ panic!("Specified multiple max: {old:?}");
+ }
- // We've parsed everything that the user provided, so we're done
- if body.is_empty() {
- break;
+ false
}
+ "debug_format" => {
+ let Ok(Meta::NameValue(literal) )= attr.parse_meta() else {
+ panic!("#[debug_format = FMT] attribute requires a format");
+ };
- // Otherwise, we are parsing a user-defined constant
- let const_attrs = body.call(Attribute::parse_outer)?;
- body.parse::<Token![const]>()?;
- let const_name: Ident = body.parse()?;
- body.parse::<Token![=]>()?;
- let const_val: Expr = body.parse()?;
- try_comma()?;
- consts.push(quote! { #(#const_attrs)* #vis const #const_name: #name = #name::from_u32(#const_val); });
+ if let Some(old) = debug_format.replace(literal.lit) {
+ panic!("Specified multiple debug format options: {old:?}");
+ }
+
+ false
+ }
+ _ => true,
+ },
+ _ => true,
+ });
+
+ loop {
+ // We've parsed everything that the user provided, so we're done
+ if body.is_empty() {
+ break;
}
+
+ // Otherwise, we are parsing a user-defined constant
+ let const_attrs = body.call(Attribute::parse_outer)?;
+ body.parse::<Token![const]>()?;
+ let const_name: Ident = body.parse()?;
+ body.parse::<Token![=]>()?;
+ let const_val: Expr = body.parse()?;
+ body.parse::<Token![;]>()?;
+ consts.push(quote! { #(#const_attrs)* #vis const #const_name: #name = #name::from_u32(#const_val); });
}
- let debug_format = debug_format.unwrap_or(DebugFormat::Format("{}".to_string()));
+ let debug_format =
+ debug_format.unwrap_or_else(|| Lit::Str(LitStr::new("{}", Span::call_site())));
+
// shave off 256 indices at the end to allow space for packing these indices into enums
let max = max.unwrap_or_else(|| Lit::Int(LitInt::new("0xFFFF_FF00", Span::call_site())));
@@ -180,18 +135,14 @@ impl Parse for Newtype {
quote! {}
};
- let debug_impl = match debug_format {
- DebugFormat::Custom => quote! {},
- DebugFormat::Format(format) => {
- quote! {
- impl ::std::fmt::Debug for #name {
- fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
- write!(fmt, #format, self.as_u32())
- }
- }
+ let debug_impl = quote! {
+ impl ::std::fmt::Debug for #name {
+ fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ write!(fmt, #debug_format, self.as_u32())
}
}
};
+
let spec_partial_eq_impl = if let Lit::Int(max) = &max {
if let Ok(max_val) = max.base10_parse::<u32>() {
quote! {
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 789d83a0d..08e42a8a0 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -239,7 +239,7 @@ fn doc_comment_from_desc(list: &Punctuated<Expr, token::Comma>) -> Result<Attrib
.unwrap();
},
);
- let doc_string = format!("[query description - consider adding a doc-comment!] {}", doc_string);
+ let doc_string = format!("[query description - consider adding a doc-comment!] {doc_string}");
Ok(parse_quote! { #[doc = #doc_string] })
}
diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs
index 92590c33b..04facbf65 100644
--- a/compiler/rustc_macros/src/symbols.rs
+++ b/compiler/rustc_macros/src/symbols.rs
@@ -134,7 +134,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
let mut check_dup = |span: Span, str: &str, errors: &mut Errors| {
if let Some(prev_span) = keys.get(str) {
- errors.error(span, format!("Symbol `{}` is duplicated", str));
+ errors.error(span, format!("Symbol `{str}` is duplicated"));
errors.error(*prev_span, "location of previous definition".to_string());
} else {
keys.insert(str.to_string(), span);
@@ -144,8 +144,8 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
let mut check_order = |span: Span, str: &str, errors: &mut Errors| {
if let Some((prev_span, ref prev_str)) = prev_key {
if str < prev_str {
- errors.error(span, format!("Symbol `{}` must precede `{}`", str, prev_str));
- errors.error(prev_span, format!("location of previous symbol `{}`", prev_str));
+ errors.error(span, format!("Symbol `{str}` must precede `{prev_str}`"));
+ errors.error(prev_span, format!("location of previous symbol `{prev_str}`"));
}
}
prev_key = Some((span, str.to_string()));
diff --git a/compiler/rustc_macros/src/symbols/tests.rs b/compiler/rustc_macros/src/symbols/tests.rs
index 842d2a977..bd0c08a53 100644
--- a/compiler/rustc_macros/src/symbols/tests.rs
+++ b/compiler/rustc_macros/src/symbols/tests.rs
@@ -16,14 +16,13 @@ fn test_symbols() {
let m: &syn::ItemMacro = file
.items
.iter()
- .filter_map(|i| {
+ .find_map(|i| {
if let syn::Item::Macro(m) = i {
if m.mac.path == symbols_path { Some(m) } else { None }
} else {
None
}
})
- .next()
.expect("did not find `symbols!` macro invocation.");
let body_tokens = m.mac.tokens.clone();
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index 14e6aa6e0..1f95661ce 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -26,7 +26,7 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
__visitor: &mut __V
) -> ::std::ops::ControlFlow<__V::BreakTy> {
match *self { #body_visit }
- ::std::ops::ControlFlow::CONTINUE
+ ::std::ops::ControlFlow::Continue(())
}
},
)