From af74ef89934ad30b24132b464b6b4cf7cb0e1381 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 27 Mar 2023 13:44:06 +0000 Subject: [PATCH 1/4] migrate rustc_macros to syn 2.0 --- Cargo.lock | 24 ++- compiler/rustc_macros/Cargo.toml | 4 +- .../src/diagnostics/diagnostic_builder.rs | 154 ++++++--------- .../rustc_macros/src/diagnostics/error.rs | 55 +----- .../src/diagnostics/subdiagnostic.rs | 76 ++++--- .../rustc_macros/src/diagnostics/utils.rs | 186 +++++++++--------- compiler/rustc_macros/src/hash_stable.rs | 45 ++--- compiler/rustc_macros/src/newtype.rs | 10 +- compiler/rustc_macros/src/query.rs | 8 +- compiler/rustc_macros/src/type_foldable.rs | 27 ++- compiler/rustc_macros/src/type_visitable.rs | 30 +-- 11 files changed, 275 insertions(+), 344 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9e9ef9fb0f..be8afa930c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -632,7 +632,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.102", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -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", ] @@ -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" @@ -7154,7 +7166,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.102", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -7175,7 +7187,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.102", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -7204,5 +7216,5 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.102", - "synstructure", + "synstructure 0.12.6", ] diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index 547c8debb50..745983e7e86 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -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"] } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 7fbe3bc2888..fb75d87f8d2 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -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, @@ -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? @@ -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(); } } @@ -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")); } @@ -191,71 +188,39 @@ 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()?; + + let mut first = true; if name == "diag" { - let Meta::List(MetaList { ref nested, .. }) = meta else { - throw_invalid_attr!( - attr, - &meta - ); - }; - - let mut nested_iter = nested.into_iter().peekable(); - - match nested_iter.peek() { - Some(NestedMeta::Meta(Meta::Path(slug))) => { - self.slug.set_once(slug.clone(), slug.span().unwrap()); - nested_iter.next(); - } - 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; - } + attr.parse_nested_meta(|nested| { + let path = &nested.path; + + if first && (nested.input.is_empty() || nested.input.peek(Token![,])) { + self.slug.set_once(path.clone(), path.span().unwrap()); + first = false; + return Ok(()) + } + + 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); + if path.is_ident("code") { + self.code.set_once((), path.span().unwrap()); - 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(), + let code = nested.parse::()?; + tokens.extend(quote! { + #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + }); } - } + Ok(()) + })?; return Ok(tokens); } @@ -270,7 +235,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!(), @@ -309,7 +274,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 { @@ -343,11 +308,10 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { binding: TokenStream, ) -> Result { 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! {}), @@ -361,7 +325,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") }) } @@ -378,26 +342,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 = 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); }); } _ => (), } @@ -432,7 +404,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(...)]`") diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index 2d62d593163..b37dc826d28 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -1,7 +1,7 @@ use proc_macro::{Diagnostic, Level, MultiSpan}; use proc_macro2::TokenStream; use quote::quote; -use syn::{spanned::Spanned, Attribute, Error as SynError, Meta, NestedMeta}; +use syn::{spanned::Spanned, Attribute, Error as SynError, Meta}; #[derive(Debug)] pub(crate) enum DiagnosticDeriveError { @@ -53,6 +53,7 @@ fn path_to_string(path: &syn::Path) -> String { } /// Returns an error diagnostic on span `span` with msg `msg`. +#[must_use] pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic { Diagnostic::spanned(span, Level::Error, msg) } @@ -72,10 +73,10 @@ macro_rules! throw_span_err { pub(crate) use throw_span_err; /// Returns an error diagnostic for an invalid attribute. -pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { +pub(crate) fn invalid_attr(attr: &Attribute) -> Diagnostic { let span = attr.span().unwrap(); - let path = path_to_string(&attr.path); - match meta { + let path = path_to_string(attr.path()); + match attr.meta { Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")), Meta::NameValue(_) => { span_err(span, &format!("`#[{path} = ...]` is not a valid attribute")) @@ -89,51 +90,11 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { /// /// For methods that return a `Result<_, DiagnosticDeriveError>`: macro_rules! throw_invalid_attr { - ($attr:expr, $meta:expr) => {{ throw_invalid_attr!($attr, $meta, |diag| diag) }}; - ($attr:expr, $meta:expr, $f:expr) => {{ - let diag = crate::diagnostics::error::invalid_attr($attr, $meta); + ($attr:expr) => {{ throw_invalid_attr!($attr, |diag| diag) }}; + ($attr:expr, $f:expr) => {{ + let diag = crate::diagnostics::error::invalid_attr($attr); return Err(crate::diagnostics::error::_throw_err(diag, $f)); }}; } pub(crate) use throw_invalid_attr; - -/// Returns an error diagnostic for an invalid nested attribute. -pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diagnostic { - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - - let span = nested.span().unwrap(); - let meta = match nested { - syn::NestedMeta::Meta(meta) => meta, - syn::NestedMeta::Lit(_) => { - return span_err(span, &format!("`#[{name}(\"...\")]` is not a valid attribute")); - } - }; - - let span = meta.span().unwrap(); - let path = path_to_string(meta.path()); - match meta { - Meta::NameValue(..) => { - 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!("`#[{name}({path}(...))]` is not a valid attribute")) - } - } -} - -/// Emit an error diagnostic for an invalid nested attribute (optionally performing additional -/// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. -/// -/// For methods that return a `Result<_, DiagnosticDeriveError>`: -macro_rules! throw_invalid_nested_attr { - ($attr:expr, $nested_attr:expr) => {{ throw_invalid_nested_attr!($attr, $nested_attr, |diag| diag) }}; - ($attr:expr, $nested_attr:expr, $f:expr) => {{ - let diag = crate::diagnostics::error::invalid_nested_attr($attr, $nested_attr); - return Err(crate::diagnostics::error::_throw_err(diag, $f)); - }}; -} - -pub(crate) use throw_invalid_nested_attr; diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 90660fc1f93..2f42a3b0bd4 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -1,8 +1,7 @@ #![deny(unused_must_use)] use crate::diagnostics::error::{ - invalid_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, - DiagnosticDeriveError, + invalid_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError, }; use crate::diagnostics::utils::{ build_field_mapping, is_doc_comment, new_code_ident, @@ -11,7 +10,7 @@ use crate::diagnostics::utils::{ }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; -use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path}; +use syn::{spanned::Spanned, Attribute, Meta, MetaList, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::{build_suggestion_code, AllowMultipleAlternatives}; @@ -39,7 +38,8 @@ impl SubdiagnosticDeriveBuilder { span_err( span, "`#[derive(Subdiagnostic)]` can only be used on structs and enums", - ); + ) + .emit(); } } @@ -192,7 +192,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { }; let Some(slug) = slug else { - 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(); throw_span_err!( @@ -265,17 +265,18 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { info: FieldInfo<'_>, clone_suggestion_code: bool, ) -> Result { - let meta = attr.parse_meta()?; - match meta { - Meta::Path(path) => self.generate_field_code_inner_path(kind_stats, attr, info, path), - Meta::List(list @ MetaList { .. }) => self.generate_field_code_inner_list( + match &attr.meta { + Meta::Path(path) => { + self.generate_field_code_inner_path(kind_stats, attr, info, path.clone()) + } + Meta::List(list) => self.generate_field_code_inner_list( kind_stats, attr, info, list, clone_suggestion_code, ), - _ => throw_invalid_attr!(attr, &meta), + _ => throw_invalid_attr!(attr), } } @@ -296,7 +297,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { "skip_arg" => Ok(quote! {}), "primary_span" => { if kind_stats.has_multipart_suggestion { - invalid_attr(attr, &Meta::Path(path)) + invalid_attr(attr) .help( "multipart suggestions use one or more `#[suggestion_part]`s rather \ than one `#[primary_span]`", @@ -309,7 +310,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { // FIXME(#100717): support `Option` on `primary_span` like in the // diagnostic derive if !matches!(info.ty, FieldInnerTy::Plain(_)) { - throw_invalid_attr!(attr, &Meta::Path(path), |diag| { + throw_invalid_attr!(attr, |diag| { let diag = diag.note("there must be exactly one primary span"); if kind_stats.has_normal_suggestion { @@ -335,7 +336,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") .emit(); } else { - invalid_attr(attr, &Meta::Path(path)) + invalid_attr(attr) .help( "`#[suggestion_part(...)]` is only valid in multipart suggestions, \ use `#[primary_span]` instead", @@ -375,7 +376,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { span_attrs.push("primary_span") } - invalid_attr(attr, &Meta::Path(path)) + invalid_attr(attr) .help(format!( "only `{}`, `applicability` and `skip_arg` are valid field attributes", span_attrs.join(", ") @@ -394,7 +395,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { kind_stats: KindsStatistics, attr: &Attribute, info: FieldInfo<'_>, - list: MetaList, + list: &MetaList, clone_suggestion_code: bool, ) -> Result { let span = attr.span().unwrap(); @@ -405,7 +406,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { match name { "suggestion_part" => { if !kind_stats.has_multipart_suggestion { - throw_invalid_attr!(attr, &Meta::List(list), |diag| { + throw_invalid_attr!(attr, |diag| { diag.help( "`#[suggestion_part(...)]` is only valid in multipart suggestions", ) @@ -417,31 +418,26 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { report_error_if_not_applied_to_span(attr, &info)?; let mut code = None; - for nested_attr in list.nested.iter() { - let NestedMeta::Meta(ref meta) = nested_attr else { - throw_invalid_nested_attr!(attr, nested_attr); - }; - let span = meta.span().unwrap(); - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - - match nested_name { - "code" => { - let code_field = new_code_ident(); - let formatting_init = build_suggestion_code( - &code_field, - meta, - self, - AllowMultipleAlternatives::No, - ); - code.set_once((code_field, formatting_init), span); - } - _ => throw_invalid_nested_attr!(attr, nested_attr, |diag| { - diag.help("`code` is the only valid nested attribute") - }), + list.parse_nested_meta(|nested| { + if nested.path.is_ident("code") { + let code_field = new_code_ident(); + let formatting_init = build_suggestion_code( + &code_field, + nested, + self, + AllowMultipleAlternatives::No, + ); + code.set_once((code_field, formatting_init), span); + } else { + span_err( + nested.path.span().unwrap(), + "`code` is the only valid nested attribute", + ) + .emit(); } - } + Ok(()) + })?; let Some((code_field, formatting_init)) = code.value() else { span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`") @@ -458,7 +454,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { }; Ok(quote! { suggestions.push((#binding, #code_field)); }) } - _ => throw_invalid_attr!(attr, &Meta::List(list), |diag| { + _ => throw_invalid_attr!(attr, |diag| { let mut span_attrs = vec![]; if kind_stats.has_multipart_suggestion { span_attrs.push("suggestion_part"); diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 65bb154d7f3..38292df6d85 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -1,5 +1,5 @@ use crate::diagnostics::error::{ - span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError, + span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError, }; use proc_macro::Span; use proc_macro2::{Ident, TokenStream}; @@ -8,11 +8,13 @@ use std::cell::RefCell; use std::collections::{BTreeSet, HashMap}; use std::fmt; use std::str::FromStr; +use syn::meta::ParseNestedMeta; +use syn::punctuated::Punctuated; +use syn::{parenthesized, LitStr, Path, Token}; use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple}; -use syn::{MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, VariantInfo}; -use super::error::{invalid_attr, invalid_nested_attr}; +use super::error::invalid_attr; thread_local! { pub static CODE_IDENT_COUNT: RefCell = RefCell::new(0); @@ -60,8 +62,8 @@ pub(crate) fn report_type_error( attr: &Attribute, ty_name: &str, ) -> Result { - let name = attr.path.segments.last().unwrap().ident.to_string(); - let meta = attr.parse_meta()?; + let name = attr.path().segments.last().unwrap().ident.to_string(); + let meta = &attr.meta; throw_span_err!( attr.span().unwrap(), @@ -422,55 +424,53 @@ pub(super) enum AllowMultipleAlternatives { /// `#[suggestion*(code("foo", "bar"))]` attribute field pub(super) fn build_suggestion_code( code_field: &Ident, - meta: &Meta, + nested: ParseNestedMeta<'_>, fields: &impl HasFieldMap, allow_multiple: AllowMultipleAlternatives, ) -> TokenStream { - let values = match meta { - // `code = "foo"` - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s], - // `code("foo", "bar")` - Meta::List(MetaList { nested, .. }) => { + let values = match (|| { + let values: Vec = if let Ok(val) = nested.value() { + vec![val.parse()?] + } else { + let content; + parenthesized!(content in nested.input); + if let AllowMultipleAlternatives::No = allow_multiple { span_err( - meta.span().unwrap(), + nested.input.span().unwrap(), "expected exactly one string literal for `code = ...`", ) .emit(); vec![] - } else if nested.is_empty() { - span_err( - meta.span().unwrap(), - "expected at least one string literal for `code(...)`", - ) - .emit(); - vec![] } else { - nested - .into_iter() - .filter_map(|item| { - if let NestedMeta::Lit(syn::Lit::Str(s)) = item { - Some(s) - } else { - span_err( - item.span().unwrap(), - "`code(...)` must contain only string literals", - ) - .emit(); - None - } - }) - .collect() + let literals = Punctuated::::parse_terminated(&content); + + match literals { + Ok(p) if p.is_empty() => { + span_err( + content.span().unwrap(), + "expected at least one string literal for `code(...)`", + ) + .emit(); + vec![] + } + Ok(p) => p.into_iter().collect(), + Err(_) => { + span_err( + content.span().unwrap(), + "`code(...)` must contain only string literals", + ) + .emit(); + vec![] + } + } } - } - _ => { - span_err( - meta.span().unwrap(), - r#"`code = "..."`/`code(...)` must contain only string literals"#, - ) - .emit(); - vec![] - } + }; + + Ok(values) + })() { + Ok(x) => x, + Err(e) => return e.into_compile_error(), }; if let AllowMultipleAlternatives::Yes = allow_multiple { @@ -601,11 +601,9 @@ impl SubdiagnosticKind { let span = attr.span().unwrap(); - 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()?; - let mut kind = match name { "label" => SubdiagnosticKind::Label, "note" => SubdiagnosticKind::Note, @@ -618,7 +616,7 @@ impl SubdiagnosticKind { name.strip_prefix("suggestion").and_then(SuggestionKind::from_suffix) { if suggestion_kind != SuggestionKind::Normal { - invalid_attr(attr, &meta) + invalid_attr(attr) .help(format!( r#"Use `#[suggestion(..., style = "{suggestion_kind}")]` instead"# )) @@ -635,7 +633,7 @@ impl SubdiagnosticKind { name.strip_prefix("multipart_suggestion").and_then(SuggestionKind::from_suffix) { if suggestion_kind != SuggestionKind::Normal { - invalid_attr(attr, &meta) + invalid_attr(attr) .help(format!( r#"Use `#[multipart_suggestion(..., style = "{suggestion_kind}")]` instead"# )) @@ -647,16 +645,16 @@ impl SubdiagnosticKind { applicability: None, } } else { - throw_invalid_attr!(attr, &meta); + throw_invalid_attr!(attr); } } }; - let nested = match meta { - Meta::List(MetaList { ref nested, .. }) => { + let list = match &attr.meta { + Meta::List(list) => { // An attribute with properties, such as `#[suggestion(code = "...")]` or // `#[error(some::slug)]` - nested + list } Meta::Path(_) => { // An attribute without a slug or other properties, such as `#[note]` - return @@ -678,52 +676,51 @@ impl SubdiagnosticKind { } } _ => { - throw_invalid_attr!(attr, &meta) + throw_invalid_attr!(attr) } }; let mut code = None; let mut suggestion_kind = None; - let mut nested_iter = nested.into_iter().peekable(); + let mut first = true; + let mut slug = None; - // Peek at the first nested attribute: if it's a slug path, consume it. - let slug = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() { - let path = path.clone(); - // Advance the iterator. - nested_iter.next(); - Some(path) - } else { - None - }; - - for nested_attr in nested_iter { - let meta = match nested_attr { - NestedMeta::Meta(ref meta) => meta, - NestedMeta::Lit(_) => { - invalid_nested_attr(attr, nested_attr).emit(); - continue; + list.parse_nested_meta(|nested| { + if nested.input.is_empty() || nested.input.peek(Token![,]) { + if first { + slug = Some(nested.path); + } else { + span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit(); } - }; - let span = meta.span().unwrap(); - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); + first = false; + return Ok(()); + } + + first = false; + + let nested_name = nested.path.segments.last().unwrap().ident.to_string(); let nested_name = nested_name.as_str(); - let string_value = match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value), + let path_span = nested.path.span().unwrap(); + let val_span = nested.input.span().unwrap(); - Meta::Path(_) => throw_invalid_nested_attr!(attr, nested_attr, |diag| { - diag.help("a diagnostic slug must be the first argument to the attribute") - }), - _ => None, - }; + macro get_string() { + { + let Ok(value) = nested.value().and_then(|x| x.parse::()) else { + span_err(val_span, "expected `= \"xxx\"`").emit(); + return Ok(()); + }; + value + } + } match (nested_name, &mut kind) { ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { let code_init = build_suggestion_code( code_field, - meta, + nested, fields, AllowMultipleAlternatives::Yes, ); @@ -734,13 +731,9 @@ impl SubdiagnosticKind { SubdiagnosticKind::Suggestion { ref mut applicability, .. } | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. }, ) => { - let Some(value) = string_value else { - invalid_nested_attr(attr, nested_attr).emit(); - continue; - }; - + let value = get_string!(); let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { - span_err(span, "invalid applicability").emit(); + span_err(value.span().unwrap(), "invalid applicability").emit(); Applicability::Unspecified }); applicability.set_once(value, span); @@ -750,10 +743,7 @@ impl SubdiagnosticKind { SubdiagnosticKind::Suggestion { .. } | SubdiagnosticKind::MultipartSuggestion { .. }, ) => { - let Some(value) = string_value else { - invalid_nested_attr(attr, nested_attr).emit(); - continue; - }; + let value = get_string!(); let value = value.value().parse().unwrap_or_else(|()| { span_err(value.span().unwrap(), "invalid suggestion style") @@ -767,22 +757,24 @@ impl SubdiagnosticKind { // Invalid nested attribute (_, SubdiagnosticKind::Suggestion { .. }) => { - invalid_nested_attr(attr, nested_attr) + span_err(path_span, "invalid nested attribute") .help( "only `style`, `code` and `applicability` are valid nested attributes", ) .emit(); } (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { - invalid_nested_attr(attr, nested_attr) + span_err(path_span, "invalid nested attribute") .help("only `style` and `applicability` are valid nested attributes") - .emit() + .emit(); } _ => { - invalid_nested_attr(attr, nested_attr).emit(); + span_err(path_span, "invalid nested attribute").emit(); } } - } + + Ok(()) + })?; match kind { SubdiagnosticKind::Suggestion { @@ -845,5 +837,5 @@ pub(super) fn should_generate_set_arg(field: &Field) -> bool { } pub(super) fn is_doc_comment(attr: &Attribute) -> bool { - attr.path.segments.last().unwrap().ident == "doc" + attr.path().segments.last().unwrap().ident == "doc" } diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index 63bdcea87f8..75a2f7009c2 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -1,6 +1,6 @@ use proc_macro2::{self, Ident}; use quote::quote; -use syn::{self, parse_quote, Meta, NestedMeta}; +use syn::{self, parse_quote}; struct Attributes { ignore: bool, @@ -10,32 +10,29 @@ struct Attributes { fn parse_attributes(field: &syn::Field) -> Attributes { let mut attrs = Attributes { ignore: false, project: None }; for attr in &field.attrs { - if let Ok(meta) = attr.parse_meta() { - if !meta.path().is_ident("stable_hasher") { - continue; + let meta = &attr.meta; + if !meta.path().is_ident("stable_hasher") { + continue; + } + let mut any_attr = false; + let _ = attr.parse_nested_meta(|nested| { + if nested.path.is_ident("ignore") { + attrs.ignore = true; + any_attr = true; } - let mut any_attr = false; - if let Meta::List(list) = meta { - for nested in list.nested.iter() { - if let NestedMeta::Meta(meta) = nested { - if meta.path().is_ident("ignore") { - attrs.ignore = true; - any_attr = true; - } - if meta.path().is_ident("project") { - if let Meta::List(list) = meta { - if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() { - attrs.project = meta.path().get_ident().cloned(); - any_attr = true; - } - } - } + if nested.path.is_ident("project") { + let _ = nested.parse_nested_meta(|meta| { + if attrs.project.is_none() { + attrs.project = meta.path.get_ident().cloned(); } - } - } - if !any_attr { - panic!("error parsing stable_hasher"); + any_attr = true; + Ok(()) + }); } + Ok(()) + }); + if !any_attr { + panic!("error parsing stable_hasher"); } } attrs diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs index 89ea89cf502..04e762e91de 100644 --- a/compiler/rustc_macros/src/newtype.rs +++ b/compiler/rustc_macros/src/newtype.rs @@ -25,7 +25,7 @@ impl Parse for Newtype { let mut encodable = true; let mut ord = true; - attrs.retain(|attr| match attr.path.get_ident() { + attrs.retain(|attr| match attr.path().get_ident() { Some(ident) => match &*ident.to_string() { "custom_encodable" => { encodable = false; @@ -36,22 +36,22 @@ impl Parse for Newtype { false } "max" => { - let Ok(Meta::NameValue(literal) )= attr.parse_meta() else { + let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else { panic!("#[max = NUMBER] attribute requires max value"); }; - if let Some(old) = max.replace(literal.lit) { + if let Some(old) = max.replace(lit.lit.clone()) { panic!("Specified multiple max: {old:?}"); } false } "debug_format" => { - let Ok(Meta::NameValue(literal) )= attr.parse_meta() else { + let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. } ) = &attr.meta else { panic!("#[debug_format = FMT] attribute requires a format"); }; - if let Some(old) = debug_format.replace(literal.lit) { + if let Some(old) = debug_format.replace(lit.lit.clone()) { panic!("Specified multiple debug format options: {old:?}"); } diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 08e42a8a08f..f85ba38003c 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -15,7 +15,7 @@ mod kw { /// Ensures only doc comment attributes are used fn check_attributes(attrs: Vec) -> Result> { let inner = |attr: Attribute| { - if !attr.path.is_ident("doc") { + if !attr.path().is_ident("doc") { Err(Error::new(attr.span(), "attributes not supported on queries")) } else if attr.style != AttrStyle::Outer { Err(Error::new( @@ -48,7 +48,7 @@ impl Parse for Query { let name: Ident = input.parse()?; let arg_content; parenthesized!(arg_content in input); - let key = arg_content.parse()?; + let key = Pat::parse_single(&arg_content)?; arg_content.parse::()?; let arg = arg_content.parse()?; let result = input.parse()?; @@ -158,7 +158,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { } else { None }; - let list = attr_content.parse_terminated(Expr::parse)?; + let list = attr_content.parse_terminated(Expr::parse, Token![,])?; try_insert!(desc = (tcx, list)); } else if modifier == "cache_on_disk_if" { // Parse a cache modifier like: @@ -166,7 +166,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result { let args = if input.peek(token::Paren) { let args; parenthesized!(args in input); - let tcx = args.parse()?; + let tcx = Pat::parse_single(&args)?; Some(tcx) } else { None diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 388e254cd64..5ee4d879313 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -1,5 +1,5 @@ use quote::{quote, ToTokens}; -use syn::{parse_quote, Attribute, Meta, NestedMeta}; +use syn::parse_quote; pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { @@ -17,21 +17,20 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: vi.construct(|_, index| { let bind = &bindings[index]; + let mut fixed = false; + // retain value of fields with #[type_foldable(identity)] - let fixed = bind - .ast() - .attrs - .iter() - .map(Attribute::parse_meta) - .filter_map(Result::ok) - .flat_map(|attr| match attr { - Meta::List(list) if list.path.is_ident("type_foldable") => list.nested, - _ => Default::default(), - }) - .any(|nested| match nested { - NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"), - _ => false, + bind.ast().attrs.iter().for_each(|x| { + if !x.path().is_ident("type_foldable") { + return; + } + let _ = x.parse_nested_meta(|nested| { + if nested.path.is_ident("identity") { + fixed = true; + } + Ok(()) }); + }); if fixed { bind.to_token_stream() diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index f6f4c4779c3..dcd505a105e 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -1,5 +1,5 @@ use quote::quote; -use syn::{parse_quote, Attribute, Meta, NestedMeta}; +use syn::parse_quote; pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { @@ -8,19 +8,21 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2: // ignore fields with #[type_visitable(ignore)] s.filter(|bi| { - !bi.ast() - .attrs - .iter() - .map(Attribute::parse_meta) - .filter_map(Result::ok) - .flat_map(|attr| match attr { - Meta::List(list) if list.path.is_ident("type_visitable") => list.nested, - _ => Default::default(), - }) - .any(|nested| match nested { - NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"), - _ => false, - }) + let mut ignored = false; + + bi.ast().attrs.iter().for_each(|attr| { + if !attr.path().is_ident("type_visitable") { + return; + } + let _ = attr.parse_nested_meta(|nested| { + if nested.path.is_ident("ignore") { + ignored = true; + } + Ok(()) + }); + }); + + !ignored }); if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { From fc01b4b63c5336a0f296b049525e18798b95b374 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 3 Apr 2023 14:36:50 +0000 Subject: [PATCH 2/4] fix and bless ui tests 1/2 --- .../src/diagnostics/diagnostic_builder.rs | 7 +- .../rustc_macros/src/diagnostics/utils.rs | 13 + .../session-diagnostic/diagnostic-derive.rs | 44 ++- .../diagnostic-derive.stderr | 313 ++++++++---------- .../subdiagnostic-derive.stderr | 184 +++++----- 5 files changed, 289 insertions(+), 272 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index fb75d87f8d2..9b91627883a 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -214,10 +214,15 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { if path.is_ident("code") { self.code.set_once((), path.span().unwrap()); - let code = nested.parse::()?; + let code = nested.parse::()?; 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::(); } Ok(()) })?; diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 38292df6d85..bc104941c38 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -716,6 +716,9 @@ impl SubdiagnosticKind { } } + let mut has_errors = false; + let input = nested.input; + match (nested_name, &mut kind) { ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => { let code_init = build_suggestion_code( @@ -734,6 +737,7 @@ impl SubdiagnosticKind { let value = get_string!(); let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| { span_err(value.span().unwrap(), "invalid applicability").emit(); + has_errors = true; Applicability::Unspecified }); applicability.set_once(value, span); @@ -749,6 +753,7 @@ impl SubdiagnosticKind { span_err(value.span().unwrap(), "invalid suggestion style") .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`") .emit(); + has_errors = true; SuggestionKind::Normal }); @@ -762,17 +767,25 @@ impl SubdiagnosticKind { "only `style`, `code` and `applicability` are valid nested attributes", ) .emit(); + has_errors = true; } (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { span_err(path_span, "invalid nested attribute") .help("only `style` and `applicability` are valid nested attributes") .emit(); + has_errors = true; } _ => { span_err(path_span, "invalid nested attribute").emit(); + has_errors = true; } } + if has_errors { + // Consume the rest of the input to avoid spamming errors + let _ = input.parse::(); + } + Ok(()) })?; diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 3151c712566..61724c11745 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -50,7 +50,7 @@ enum DiagnosticOnEnum { #[derive(Diagnostic)] #[diag(no_crate_example, code = "E0123")] #[diag = "E0123"] -//~^ ERROR `#[diag = ...]` is not a valid attribute +//~^ ERROR expected parentheses: #[diag(...)] struct WrongStructAttrStyle {} #[derive(Diagnostic)] @@ -62,8 +62,7 @@ struct InvalidStructAttr {} #[derive(Diagnostic)] #[diag("E0123")] -//~^ ERROR `#[diag("...")]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~^ ERROR diagnostic slug not specified struct InvalidLitNestedAttr {} #[derive(Diagnostic)] @@ -73,27 +72,25 @@ struct InvalidNestedStructAttr {} #[derive(Diagnostic)] #[diag(nonsense("foo"), code = "E0123", slug = "foo")] -//~^ ERROR `#[diag(nonsense(...))]` is not a valid attribute -//~^^ ERROR diagnostic slug not specified +//~^ ERROR diagnostic slug must be the first argument +//~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr1 {} #[derive(Diagnostic)] #[diag(nonsense = "...", code = "E0123", slug = "foo")] -//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute -//~| ERROR `#[diag(slug = ...)]` is not a valid attribute +//~^ ERROR unknown argument //~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr2 {} #[derive(Diagnostic)] #[diag(nonsense = 4, code = "E0123", slug = "foo")] -//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute -//~| ERROR `#[diag(slug = ...)]` is not a valid attribute +//~^ ERROR unknown argument //~| ERROR diagnostic slug not specified struct InvalidNestedStructAttr3 {} #[derive(Diagnostic)] #[diag(no_crate_example, code = "E0123", slug = "foo")] -//~^ ERROR `#[diag(slug = ...)]` is not a valid attribute +//~^ ERROR unknown argument struct InvalidNestedStructAttr4 {} #[derive(Diagnostic)] @@ -118,7 +115,7 @@ struct CodeSpecifiedTwice {} #[derive(Diagnostic)] #[diag(no_crate_example, no_crate::example, code = "E0456")] -//~^ ERROR `#[diag(no_crate::example)]` is not a valid attribute +//~^ ERROR diagnostic slug must be the first argument struct SlugSpecifiedTwice {} #[derive(Diagnostic)] @@ -232,7 +229,7 @@ struct SuggestWithoutCode { #[diag(no_crate_example, code = "E0123")] struct SuggestWithBadKey { #[suggestion(nonsense = "bar")] - //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute + //~^ ERROR invalid nested attribute //~| ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -241,7 +238,7 @@ struct SuggestWithBadKey { #[diag(no_crate_example, code = "E0123")] struct SuggestWithShorthandMsg { #[suggestion(msg = "bar")] - //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute + //~^ ERROR invalid nested attribute //~| ERROR suggestion without `code = "..."` suggestion: (Span, Applicability), } @@ -530,7 +527,7 @@ struct BoolField { #[diag(no_crate_example, code = "E0123")] struct LabelWithTrailingPath { #[label(no_crate_label, foo)] - //~^ ERROR `#[label(foo)]` is not a valid attribute + //~^ ERROR a diagnostic slug must be the first argument to the attribute span: Span, } @@ -538,7 +535,7 @@ struct LabelWithTrailingPath { #[diag(no_crate_example, code = "E0123")] struct LabelWithTrailingNameValue { #[label(no_crate_label, foo = "...")] - //~^ ERROR `#[label(foo = ...)]` is not a valid attribute + //~^ ERROR invalid nested attribute span: Span, } @@ -546,7 +543,7 @@ struct LabelWithTrailingNameValue { #[diag(no_crate_example, code = "E0123")] struct LabelWithTrailingList { #[label(no_crate_label, foo("..."))] - //~^ ERROR `#[label(foo(...))]` is not a valid attribute + //~^ ERROR invalid nested attribute span: Span, } @@ -643,8 +640,8 @@ struct MissingCodeInSuggestion { //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute //~| ERROR cannot find attribute `multipart_suggestion` in this scope #[multipart_suggestion()] -//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute -//~| ERROR cannot find attribute `multipart_suggestion` in this scope +//~^ ERROR cannot find attribute `multipart_suggestion` in this scope +//~| ERROR unexpected end of input, unexpected token in nested attribute, expected ident struct MultipartSuggestion { #[multipart_suggestion(no_crate_suggestion)] //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute @@ -698,7 +695,7 @@ struct RawIdentDiagnosticArg { #[diag(no_crate_example)] struct SubdiagnosticBad { #[subdiagnostic(bad)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` note: Note, } @@ -714,7 +711,7 @@ struct SubdiagnosticBadStr { #[diag(no_crate_example)] struct SubdiagnosticBadTwice { #[subdiagnostic(bad, bad)] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` note: Note, } @@ -722,7 +719,7 @@ struct SubdiagnosticBadTwice { #[diag(no_crate_example)] struct SubdiagnosticBadLitStr { #[subdiagnostic("bad")] - //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute + //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` note: Note, } @@ -797,14 +794,15 @@ struct SuggestionsNoItem { struct SuggestionsInvalidItem { #[suggestion(code(foo))] //~^ ERROR `code(...)` must contain only string literals + //~| ERROR unexpected token sub: Span, } -#[derive(Diagnostic)] +#[derive(Diagnostic)] //~ ERROR cannot find value `__code_34` in this scope #[diag(no_crate_example)] struct SuggestionsInvalidLiteral { #[suggestion(code = 3)] - //~^ ERROR `code = "..."`/`code(...)` must contain only string literals + //~^ ERROR expected string literal sub: Span, } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 513b675e5dd..041ebdee0ab 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -20,11 +20,11 @@ LL | Bar, | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:52:1 +error: expected parentheses: #[diag(...)] + --> $DIR/diagnostic-derive.rs:52:8 | LL | #[diag = "E0123"] - | ^^^^^^^^^^^^^^^^^ + | ^ error: `#[nonsense(...)]` is not a valid attribute --> $DIR/diagnostic-derive.rs:57:1 @@ -44,35 +44,24 @@ LL | | struct InvalidStructAttr {} | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag("...")]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:64:8 - | -LL | #[diag("E0123")] - | ^^^^^^^ - | - = help: a diagnostic slug is required as the first argument - error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:64:1 | LL | / #[diag("E0123")] LL | | -LL | | LL | | struct InvalidLitNestedAttr {} | |______________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag(nonsense(...))]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:75:8 +error: diagnostic slug must be the first argument + --> $DIR/diagnostic-derive.rs:74:16 | LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^ - | - = help: a diagnostic slug is required as the first argument + | ^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:75:1 + --> $DIR/diagnostic-derive.rs:74:1 | LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")] LL | | @@ -82,120 +71,102 @@ LL | | struct InvalidNestedStructAttr1 {} | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:81:8 +error: unknown argument + --> $DIR/diagnostic-derive.rs:80:8 | LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | - = help: only `code` is a valid nested attributes following the slug - -error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:81:42 - | -LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^ - | - = help: only `code` is a valid nested attributes following the slug + = note: only the `code` parameter is valid after the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:81:1 + --> $DIR/diagnostic-derive.rs:80:1 | LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")] LL | | LL | | -LL | | LL | | struct InvalidNestedStructAttr2 {} | |__________________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:88:8 +error: unknown argument + --> $DIR/diagnostic-derive.rs:86:8 | LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^ - -error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:88:38 + | ^^^^^^^^ | -LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^ - | - = help: only `code` is a valid nested attributes following the slug + = note: only the `code` parameter is valid after the slug error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:88:1 + --> $DIR/diagnostic-derive.rs:86:1 | LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")] LL | | LL | | -LL | | LL | | struct InvalidNestedStructAttr3 {} | |__________________________________^ | = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` -error: `#[diag(slug = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:95:42 +error: unknown argument + --> $DIR/diagnostic-derive.rs:92:42 | LL | #[diag(no_crate_example, code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^ + | ^^^^ | - = help: only `code` is a valid nested attributes following the slug + = note: only the `code` parameter is valid after the slug error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:102:5 + --> $DIR/diagnostic-derive.rs:99:5 | LL | #[suggestion = "bar"] | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:8 + --> $DIR/diagnostic-derive.rs:106:8 | LL | #[diag(no_crate_example, code = "E0456")] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:8 + --> $DIR/diagnostic-derive.rs:105:8 | LL | #[diag(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:109:33 + --> $DIR/diagnostic-derive.rs:106:26 | LL | #[diag(no_crate_example, code = "E0456")] - | ^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:33 + --> $DIR/diagnostic-derive.rs:105:26 | LL | #[diag(no_crate_example, code = "E0123")] - | ^^^^^^^ + | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:115:49 + --> $DIR/diagnostic-derive.rs:112:42 | LL | #[diag(no_crate_example, code = "E0456", code = "E0457")] - | ^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:115:33 + --> $DIR/diagnostic-derive.rs:112:26 | LL | #[diag(no_crate_example, code = "E0456", code = "E0457")] - | ^^^^^^^ + | ^^^^ -error: `#[diag(no_crate::example)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:120:26 +error: diagnostic slug must be the first argument + --> $DIR/diagnostic-derive.rs:117:43 | LL | #[diag(no_crate_example, no_crate::example, code = "E0456")] - | ^^^^^^^^^^^^^^^^^ - | - = help: diagnostic slug must be the first argument + | ^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:125:1 + --> $DIR/diagnostic-derive.rs:122:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -203,7 +174,7 @@ LL | struct KindNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:128:1 + --> $DIR/diagnostic-derive.rs:125:1 | LL | / #[diag(code = "E0456")] LL | | @@ -213,31 +184,31 @@ LL | | struct SlugNotProvided {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:139:5 + --> $DIR/diagnostic-derive.rs:136:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:147:5 + --> $DIR/diagnostic-derive.rs:144:5 | LL | #[nonsense] | ^^^^^^^^^^^ error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:164:5 + --> $DIR/diagnostic-derive.rs:161:5 | LL | #[label(no_crate_label)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:172:46 + --> $DIR/diagnostic-derive.rs:169:46 | LL | #[suggestion(no_crate_suggestion, code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:177:10 + --> $DIR/diagnostic-derive.rs:174:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ expected `'}'` in format string @@ -246,7 +217,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:187:10 + --> $DIR/diagnostic-derive.rs:184:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ unmatched `}` in format string @@ -255,47 +226,47 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive.rs:207:5 + --> $DIR/diagnostic-derive.rs:204:5 | LL | #[label(no_crate_label)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:226:5 + --> $DIR/diagnostic-derive.rs:223:5 | LL | #[suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[suggestion(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:234:18 +error: invalid nested attribute + --> $DIR/diagnostic-derive.rs:231:18 | LL | #[suggestion(nonsense = "bar")] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^ | = help: only `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:234:5 + --> $DIR/diagnostic-derive.rs:231:5 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[suggestion(msg = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:243:18 +error: invalid nested attribute + --> $DIR/diagnostic-derive.rs:240:18 | LL | #[suggestion(msg = "bar")] - | ^^^^^^^^^^^ + | ^^^ | = help: only `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:243:5 + --> $DIR/diagnostic-derive.rs:240:5 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:266:5 + --> $DIR/diagnostic-derive.rs:263:5 | LL | / #[suggestion(no_crate_suggestion, code = "This is suggested code")] LL | | @@ -305,81 +276,79 @@ LL | | suggestion: Applicability, = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: specified multiple times - --> $DIR/diagnostic-derive.rs:282:24 + --> $DIR/diagnostic-derive.rs:279:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:282:18 + --> $DIR/diagnostic-derive.rs:279:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:290:33 + --> $DIR/diagnostic-derive.rs:287:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:290:18 + --> $DIR/diagnostic-derive.rs:287:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:297:5 + --> $DIR/diagnostic-derive.rs:294:5 | LL | #[label = "bar"] | ^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:448:53 + --> $DIR/diagnostic-derive.rs:445:5 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:450:24 + --> $DIR/diagnostic-derive.rs:447:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:456:53 + --> $DIR/diagnostic-derive.rs:453:69 | LL | #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")] - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `bool` or `()` - --> $DIR/diagnostic-derive.rs:523:5 + --> $DIR/diagnostic-derive.rs:520:5 | LL | #[help(no_crate_help)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: `#[label(foo)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:532:29 +error: a diagnostic slug must be the first argument to the attribute + --> $DIR/diagnostic-derive.rs:529:32 | LL | #[label(no_crate_label, foo)] - | ^^^ - | - = help: a diagnostic slug must be the first argument to the attribute + | ^ -error: `#[label(foo = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:540:29 +error: invalid nested attribute + --> $DIR/diagnostic-derive.rs:537:29 | LL | #[label(no_crate_label, foo = "...")] - | ^^^^^^^^^^^ + | ^^^ -error: `#[label(foo(...))]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:548:29 +error: invalid nested attribute + --> $DIR/diagnostic-derive.rs:545:29 | LL | #[label(no_crate_label, foo("..."))] - | ^^^^^^^^^^ + | ^^^ error: `#[primary_span]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:560:5 + --> $DIR/diagnostic-derive.rs:557:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -387,13 +356,13 @@ LL | #[primary_span] = help: the `primary_span` field attribute is not valid for lint diagnostics error: `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:580:1 + --> $DIR/diagnostic-derive.rs:577:1 | LL | #[error(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:580:1 + --> $DIR/diagnostic-derive.rs:577:1 | LL | / #[error(no_crate_example, code = "E0123")] LL | | @@ -405,13 +374,13 @@ LL | | struct ErrorAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:587:1 + --> $DIR/diagnostic-derive.rs:584:1 | LL | #[warn_(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:587:1 + --> $DIR/diagnostic-derive.rs:584:1 | LL | / #[warn_(no_crate_example, code = "E0123")] LL | | @@ -423,13 +392,13 @@ LL | | struct WarnAttribute {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:594:1 + --> $DIR/diagnostic-derive.rs:591:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:594:1 + --> $DIR/diagnostic-derive.rs:591:1 | LL | / #[lint(no_crate_example, code = "E0123")] LL | | @@ -441,19 +410,19 @@ LL | | struct LintAttributeOnSessionDiag {} = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]` error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:598:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:598:1 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic slug not specified - --> $DIR/diagnostic-derive.rs:601:1 + --> $DIR/diagnostic-derive.rs:598:1 | LL | / #[lint(no_crate_example, code = "E0123")] LL | | @@ -466,19 +435,19 @@ LL | | struct LintAttributeOnLintDiag {} = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]` error: specified multiple times - --> $DIR/diagnostic-derive.rs:611:53 + --> $DIR/diagnostic-derive.rs:608:5 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:611:39 + --> $DIR/diagnostic-derive.rs:608:5 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:620:24 + --> $DIR/diagnostic-derive.rs:617:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -486,7 +455,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: wrong types for suggestion - --> $DIR/diagnostic-derive.rs:628:17 + --> $DIR/diagnostic-derive.rs:625:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -494,13 +463,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: suggestion without `code = "..."` - --> $DIR/diagnostic-derive.rs:635:5 + --> $DIR/diagnostic-derive.rs:632:5 | LL | #[suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:642:1 + --> $DIR/diagnostic-derive.rs:639:1 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -508,23 +477,21 @@ LL | #[multipart_suggestion(no_crate_suggestion)] = help: consider creating a `Subdiagnostic` instead error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:645:1 - | -LL | #[multipart_suggestion()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider creating a `Subdiagnostic` instead - -error: `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:649:5 + --> $DIR/diagnostic-derive.rs:646:5 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider creating a `Subdiagnostic` instead +error: unexpected end of input, unexpected token in nested attribute, expected ident + --> $DIR/diagnostic-derive.rs:642:24 + | +LL | #[multipart_suggestion()] + | ^ + error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:657:1 + --> $DIR/diagnostic-derive.rs:654:1 | LL | #[suggestion(no_crate_suggestion, code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -532,45 +499,39 @@ LL | #[suggestion(no_crate_suggestion, code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:666:1 + --> $DIR/diagnostic-derive.rs:663:1 | LL | #[label] | ^^^^^^^^ | = help: `#[label]` and `#[suggestion]` can only be applied to fields -error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:700:5 +error: `eager` is the only supported nested attribute for `subdiagnostic` + --> $DIR/diagnostic-derive.rs:697:7 | LL | #[subdiagnostic(bad)] - | ^^^^^^^^^^^^^^^^^^^^^ - | - = help: `eager` is the only supported nested attribute for `subdiagnostic` + | ^^^^^^^^^^^^^^^^^^ error: `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:708:5 + --> $DIR/diagnostic-derive.rs:705:5 | LL | #[subdiagnostic = "bad"] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:716:5 +error: `eager` is the only supported nested attribute for `subdiagnostic` + --> $DIR/diagnostic-derive.rs:713:7 | LL | #[subdiagnostic(bad, bad)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `eager` is the only supported nested attribute for `subdiagnostic` + | ^^^^^^^^^^^^^^^^^^^^^^^ -error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:724:5 +error: `eager` is the only supported nested attribute for `subdiagnostic` + --> $DIR/diagnostic-derive.rs:721:7 | LL | #[subdiagnostic("bad")] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `eager` is the only supported nested attribute for `subdiagnostic` + | ^^^^^^^^^^^^^^^^^^^^ error: `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:732:5 + --> $DIR/diagnostic-derive.rs:729:5 | LL | #[subdiagnostic(eager)] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -578,25 +539,31 @@ LL | #[subdiagnostic(eager)] = help: eager subdiagnostics are not supported on lints error: expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive.rs:790:18 + --> $DIR/diagnostic-derive.rs:787:23 | LL | #[suggestion(code())] - | ^^^^^^ + | ^ error: `code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:798:23 + --> $DIR/diagnostic-derive.rs:795:23 | LL | #[suggestion(code(foo))] | ^^^ -error: `code = "..."`/`code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:806:18 +error: unexpected token + --> $DIR/diagnostic-derive.rs:795:23 + | +LL | #[suggestion(code(foo))] + | ^^^ + +error: expected string literal + --> $DIR/diagnostic-derive.rs:804:25 | LL | #[suggestion(code = 3)] - | ^^^^^^^^ + | ^ error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:821:5 + --> $DIR/diagnostic-derive.rs:819:5 | LL | #[suggestion(no_crate_suggestion, code = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -612,61 +579,69 @@ LL | #[nonsense(no_crate_example, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:147:7 + --> $DIR/diagnostic-derive.rs:144:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive.rs:580:3 + --> $DIR/diagnostic-derive.rs:577:3 | LL | #[error(no_crate_example, code = "E0123")] | ^^^^^ error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive.rs:587:3 + --> $DIR/diagnostic-derive.rs:584:3 | LL | #[warn_(no_crate_example, code = "E0123")] | ^^^^^ help: a built-in attribute with a similar name exists: `warn` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:594:3 + --> $DIR/diagnostic-derive.rs:591:3 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive.rs:601:3 + --> $DIR/diagnostic-derive.rs:598:3 | LL | #[lint(no_crate_example, code = "E0123")] | ^^^^ help: a built-in attribute with a similar name exists: `link` error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:642:3 + --> $DIR/diagnostic-derive.rs:639:3 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:645:3 + --> $DIR/diagnostic-derive.rs:642:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive.rs:649:7 + --> $DIR/diagnostic-derive.rs:646:7 | LL | #[multipart_suggestion(no_crate_suggestion)] | ^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated` - --> $DIR/diagnostic-derive.rs:70:8 + --> $DIR/diagnostic-derive.rs:69:8 | LL | #[diag(nonsense, code = "E0123")] | ^^^^^^^^ not found in `crate::fluent_generated` +error[E0425]: cannot find value `__code_34` in this scope + --> $DIR/diagnostic-derive.rs:801:10 + | +LL | #[derive(Diagnostic)] + | ^^^^^^^^^^ not found in this scope + | + = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:341:10 + --> $DIR/diagnostic-derive.rs:338:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` @@ -676,7 +651,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 85 previous errors +error: aborting due to 84 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 343134af6bc..d8bf0ba413c 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -26,11 +26,11 @@ error: `#[label = ...]` is not a valid attribute LL | #[label = "..."] | ^^^^^^^^^^^^^^^^ -error: `#[label(bug = ...)]` is not a valid attribute +error: invalid nested attribute --> $DIR/subdiagnostic-derive.rs:84:9 | LL | #[label(bug = "...")] - | ^^^^^^^^^^^ + | ^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive.rs:84:1 @@ -38,23 +38,17 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute LL | #[label(bug = "...")] | ^^^^^^^^^^^^^^^^^^^^^ -error: `#[label("...")]` is not a valid attribute +error: unexpected literal in nested attribute, expected ident --> $DIR/subdiagnostic-derive.rs:94:9 | LL | #[label("...")] | ^^^^^ -error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:94:1 - | -LL | #[label("...")] - | ^^^^^^^^^^^^^^^ - -error: `#[label(slug = ...)]` is not a valid attribute +error: invalid nested attribute --> $DIR/subdiagnostic-derive.rs:104:9 | LL | #[label(slug = 4)] - | ^^^^^^^^ + | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive.rs:104:1 @@ -62,11 +56,11 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute LL | #[label(slug = 4)] | ^^^^^^^^^^^^^^^^^^ -error: `#[label(slug(...))]` is not a valid attribute +error: invalid nested attribute --> $DIR/subdiagnostic-derive.rs:114:9 | LL | #[label(slug("..."))] - | ^^^^^^^^^^^ + | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive.rs:114:1 @@ -74,23 +68,23 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute LL | #[label(slug("..."))] | ^^^^^^^^^^^^^^^^^^^^^ -error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:134:1 +error: unexpected end of input, unexpected token in nested attribute, expected ident + --> $DIR/subdiagnostic-derive.rs:134:9 | LL | #[label()] - | ^^^^^^^^^^ + | ^ -error: `#[label(code = ...)]` is not a valid attribute +error: invalid nested attribute --> $DIR/subdiagnostic-derive.rs:143:27 | LL | #[label(no_crate_example, code = "...")] - | ^^^^^^^^^^^^ + | ^^^^ -error: `#[label(applicability = ...)]` is not a valid attribute +error: invalid nested attribute --> $DIR/subdiagnostic-derive.rs:152:27 | LL | #[label(no_crate_example, applicability = "machine-applicable")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum --> $DIR/subdiagnostic-derive.rs:161:1 @@ -122,11 +116,11 @@ error: `#[bar(...)]` is not a valid attribute LL | #[bar("...")] | ^^^^^^^^^^^^^ -error: `#[label(code = ...)]` is not a valid attribute +error: invalid nested attribute --> $DIR/subdiagnostic-derive.rs:223:13 | LL | #[label(code = "...")] - | ^^^^^^^^^^^^ + | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute --> $DIR/subdiagnostic-derive.rs:223:5 @@ -190,13 +184,11 @@ LL | | b: u64, LL | | } | |_^ -error: `#[label(no_crate::example)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:325:27 +error: a diagnostic slug must be the first argument to the attribute + --> $DIR/subdiagnostic-derive.rs:325:44 | LL | #[label(no_crate_example, no_crate::example)] - | ^^^^^^^^^^^^^^^^^ - | - = help: a diagnostic slug must be the first argument to the attribute + | ^ error: specified multiple times --> $DIR/subdiagnostic-derive.rs:338:5 @@ -217,16 +209,16 @@ LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:381:46 + --> $DIR/subdiagnostic-derive.rs:381:1 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:381:32 + --> $DIR/subdiagnostic-derive.rs:381:1 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times --> $DIR/subdiagnostic-derive.rs:399:5 @@ -253,10 +245,10 @@ LL | #[suggestion(no_crate_example)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:432:46 + --> $DIR/subdiagnostic-derive.rs:432:62 | LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ error: suggestion without `#[primary_span]` field --> $DIR/subdiagnostic-derive.rs:450:1 @@ -314,11 +306,11 @@ LL | | var: String, LL | | } | |_^ -error: `#[multipart_suggestion(code = ...)]` is not a valid attribute +error: invalid nested attribute --> $DIR/subdiagnostic-derive.rs:538:42 | LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] - | ^^^^^^^^^^^^ + | ^^^^ | = help: only `style` and `applicability` are valid nested attributes @@ -339,11 +331,11 @@ error: `#[suggestion_part(...)]` attribute without `code = "..."` LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ -error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:556:5 +error: unexpected end of input, unexpected token in nested attribute, expected ident + --> $DIR/subdiagnostic-derive.rs:556:23 | LL | #[suggestion_part()] - | ^^^^^^^^^^^^^^^^^^^^ + | ^ error: `#[primary_span]` is not a valid attribute --> $DIR/subdiagnostic-derive.rs:565:5 @@ -371,19 +363,11 @@ error: `#[suggestion_part(...)]` attribute without `code = "..."` LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ -error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:576:5 - | -LL | #[suggestion_part()] - | ^^^^^^^^^^^^^^^^^^^^ - -error: `#[suggestion_part(foo = ...)]` is not a valid attribute +error: `code` is the only valid nested attribute --> $DIR/subdiagnostic-derive.rs:579:23 | LL | #[suggestion_part(foo = "bar")] - | ^^^^^^^^^^^ - | - = help: `code` is the only valid nested attribute + | ^^^ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` --> $DIR/subdiagnostic-derive.rs:582:5 @@ -397,17 +381,29 @@ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ +error: unexpected end of input, unexpected token in nested attribute, expected ident + --> $DIR/subdiagnostic-derive.rs:576:23 + | +LL | #[suggestion_part()] + | ^ + +error: expected `,` + --> $DIR/subdiagnostic-derive.rs:579:27 + | +LL | #[suggestion_part(foo = "bar")] + | ^ + error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:593:37 + --> $DIR/subdiagnostic-derive.rs:593:5 | LL | #[suggestion_part(code = "...", code = ",,,")] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:593:23 + --> $DIR/subdiagnostic-derive.rs:593:5 | LL | #[suggestion_part(code = "...", code = ",,,")] - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` --> $DIR/subdiagnostic-derive.rs:622:5 @@ -416,46 +412,64 @@ LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:670:23 + --> $DIR/subdiagnostic-derive.rs:670:34 | LL | #[suggestion_part(code("foo"))] - | ^^^^^^^^^^^ + | ^ + +error: unexpected token + --> $DIR/subdiagnostic-derive.rs:670:28 + | +LL | #[suggestion_part(code("foo"))] + | ^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:679:23 + --> $DIR/subdiagnostic-derive.rs:679:41 | LL | #[suggestion_part(code("foo", "bar"))] - | ^^^^^^^^^^^^^^^^^^ + | ^ + +error: unexpected token + --> $DIR/subdiagnostic-derive.rs:679:28 + | +LL | #[suggestion_part(code("foo", "bar"))] + | ^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:688:23 + --> $DIR/subdiagnostic-derive.rs:688:30 | LL | #[suggestion_part(code(3))] - | ^^^^^^^ + | ^ + +error: unexpected token + --> $DIR/subdiagnostic-derive.rs:688:28 + | +LL | #[suggestion_part(code(3))] + | ^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:697:23 + --> $DIR/subdiagnostic-derive.rs:697:29 | LL | #[suggestion_part(code())] - | ^^^^^^ + | ^ -error: `code = "..."`/`code(...)` must contain only string literals - --> $DIR/subdiagnostic-derive.rs:706:23 +error: expected string literal + --> $DIR/subdiagnostic-derive.rs:706:30 | LL | #[suggestion_part(code = 3)] - | ^^^^^^^^ + | ^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:748:61 + --> $DIR/subdiagnostic-derive.rs:748:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:748:43 + --> $DIR/subdiagnostic-derive.rs:748:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion_hidden(...)]` is not a valid attribute --> $DIR/subdiagnostic-derive.rs:757:1 @@ -481,25 +495,29 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")] | = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` -error: `#[suggestion(style = ...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:781:43 +error: expected `= "xxx"` + --> $DIR/subdiagnostic-derive.rs:781:49 | LL | #[suggestion(no_crate_example, code = "", style = 42)] - | ^^^^^^^^^^ + | ^ -error: `#[suggestion(style)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:789:43 +error: a diagnostic slug must be the first argument to the attribute + --> $DIR/subdiagnostic-derive.rs:789:48 | LL | #[suggestion(no_crate_example, code = "", style)] - | ^^^^^ - | - = help: a diagnostic slug must be the first argument to the attribute + | ^ -error: `#[suggestion(style(...))]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:797:43 +error: expected `= "xxx"` + --> $DIR/subdiagnostic-derive.rs:797:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] - | ^^^^^^^^^^^^ + | ^ + +error: expected `,` + --> $DIR/subdiagnostic-derive.rs:797:48 + | +LL | #[suggestion(no_crate_example, code = "", style("foo"))] + | ^ error: `#[primary_span]` is not a valid attribute --> $DIR/subdiagnostic-derive.rs:808:5 @@ -582,6 +600,14 @@ error[E0425]: cannot find value `slug` in module `crate::fluent_generated` LL | #[label(slug)] | ^^^^ not found in `crate::fluent_generated` -error: aborting due to 81 previous errors +error[E0425]: cannot find value `__code_29` in this scope + --> $DIR/subdiagnostic-derive.rs:703:10 + | +LL | #[derive(Subdiagnostic)] + | ^^^^^^^^^^^^^ not found in this scope + | + = note: this error originates in the derive macro `Subdiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 86 previous errors For more information about this error, try `rustc --explain E0425`. From 25fdea009ef0db01134d17cf97cd09b507beca99 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 3 Apr 2023 15:11:30 +0000 Subject: [PATCH 3/4] fix errors --- .../src/diagnostics/subdiagnostic.rs | 1 + .../rustc_macros/src/diagnostics/utils.rs | 2 +- .../diagnostic-derive.stderr | 8 +- .../subdiagnostic-derive.rs | 43 +++-- .../subdiagnostic-derive.stderr | 164 +++++++++--------- 5 files changed, 113 insertions(+), 105 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 2f42a3b0bd4..62d49c1c64e 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -422,6 +422,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { list.parse_nested_meta(|nested| { if nested.path.is_ident("code") { let code_field = new_code_ident(); + let span = nested.path.span().unwrap(); let formatting_init = build_suggestion_code( &code_field, nested, diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index bc104941c38..838347ecb61 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -727,7 +727,7 @@ impl SubdiagnosticKind { fields, AllowMultipleAlternatives::Yes, ); - code.set_once(code_init, span); + code.set_once(code_init, path_span); } ( "applicability", diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 041ebdee0ab..cd14c7496b3 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -435,16 +435,16 @@ LL | | struct LintAttributeOnLintDiag {} = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]` error: specified multiple times - --> $DIR/diagnostic-derive.rs:608:5 + --> $DIR/diagnostic-derive.rs:608:53 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:608:5 + --> $DIR/diagnostic-derive.rs:608:39 | LL | #[suggestion(no_crate_suggestion, code = "...", code = ",,,")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: wrong types for suggestion --> $DIR/diagnostic-derive.rs:617:24 diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index c882f7792d5..1d928ca93f9 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -82,7 +82,7 @@ struct F { #[derive(Subdiagnostic)] #[label(bug = "...")] -//~^ ERROR `#[label(bug = ...)]` is not a valid attribute +//~^ ERROR invalid nested attribute //~| ERROR diagnostic slug must be first argument struct G { #[primary_span] @@ -92,8 +92,7 @@ struct G { #[derive(Subdiagnostic)] #[label("...")] -//~^ ERROR `#[label("...")]` is not a valid attribute -//~| ERROR diagnostic slug must be first argument +//~^ ERROR unexpected literal in nested attribute, expected ident struct H { #[primary_span] span: Span, @@ -102,7 +101,7 @@ struct H { #[derive(Subdiagnostic)] #[label(slug = 4)] -//~^ ERROR `#[label(slug = ...)]` is not a valid attribute +//~^ ERROR invalid nested attribute //~| ERROR diagnostic slug must be first argument struct J { #[primary_span] @@ -112,7 +111,7 @@ struct J { #[derive(Subdiagnostic)] #[label(slug("..."))] -//~^ ERROR `#[label(slug(...))]` is not a valid attribute +//~^ ERROR invalid nested attribute //~| ERROR diagnostic slug must be first argument struct K { #[primary_span] @@ -132,7 +131,7 @@ struct L { #[derive(Subdiagnostic)] #[label()] -//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute +//~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident struct M { #[primary_span] span: Span, @@ -141,7 +140,7 @@ struct M { #[derive(Subdiagnostic)] #[label(no_crate_example, code = "...")] -//~^ ERROR `#[label(code = ...)]` is not a valid attribute +//~^ ERROR invalid nested attribute struct N { #[primary_span] span: Span, @@ -150,7 +149,7 @@ struct N { #[derive(Subdiagnostic)] #[label(no_crate_example, applicability = "machine-applicable")] -//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute +//~^ ERROR invalid nested attribute struct O { #[primary_span] span: Span, @@ -222,7 +221,7 @@ enum T { enum U { #[label(code = "...")] //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute - //~| ERROR `#[label(code = ...)]` is not a valid attribute + //~| ERROR invalid nested attribute A { #[primary_span] span: Span, @@ -323,7 +322,7 @@ struct AD { #[derive(Subdiagnostic)] #[label(no_crate_example, no_crate::example)] -//~^ ERROR `#[label(no_crate::example)]` is not a valid attribute +//~^ ERROR a diagnostic slug must be the first argument to the attribute struct AE { #[primary_span] span: Span, @@ -537,7 +536,7 @@ struct BA { #[derive(Subdiagnostic)] #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] //~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields -//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute +//~| ERROR invalid nested attribute struct BBa { var: String, } @@ -554,7 +553,7 @@ struct BBb { #[multipart_suggestion(no_crate_example, applicability = "machine-applicable")] struct BBc { #[suggestion_part()] - //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident span1: Span, } @@ -574,10 +573,11 @@ struct BD { //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` span1: Span, #[suggestion_part()] - //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."` + //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident span2: Span, #[suggestion_part(foo = "bar")] - //~^ ERROR `#[suggestion_part(foo = ...)]` is not a valid attribute + //~^ ERROR `code` is the only valid nested attribute + //~| ERROR expected `,` span4: Span, #[suggestion_part(code = "...")] //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` @@ -669,6 +669,7 @@ enum BL { struct BM { #[suggestion_part(code("foo"))] //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token span: Span, r#type: String, } @@ -678,6 +679,7 @@ struct BM { struct BN { #[suggestion_part(code("foo", "bar"))] //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token span: Span, r#type: String, } @@ -687,6 +689,7 @@ struct BN { struct BO { #[suggestion_part(code(3))] //~^ ERROR expected exactly one string literal for `code = ...` + //~| ERROR unexpected token span: Span, r#type: String, } @@ -701,10 +704,13 @@ struct BP { } #[derive(Subdiagnostic)] +//~^ ERROR cannot find value `__code_29` in this scope +//~| NOTE in this expansion +//~| NOTE not found in this scope #[multipart_suggestion(no_crate_example)] struct BQ { #[suggestion_part(code = 3)] - //~^ ERROR `code = "..."`/`code(...)` must contain only string literals + //~^ ERROR expected string literal span: Span, r#type: String, } @@ -779,7 +785,7 @@ struct SuggestionStyleInvalid1 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style = 42)] -//~^ ERROR `#[suggestion(style = ...)]` is not a valid attribute +//~^ ERROR expected `= "xxx"` struct SuggestionStyleInvalid2 { #[primary_span] sub: Span, @@ -787,7 +793,7 @@ struct SuggestionStyleInvalid2 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style)] -//~^ ERROR `#[suggestion(style)]` is not a valid attribute +//~^ ERROR a diagnostic slug must be the first argument to the attribute struct SuggestionStyleInvalid3 { #[primary_span] sub: Span, @@ -795,7 +801,8 @@ struct SuggestionStyleInvalid3 { #[derive(Subdiagnostic)] #[suggestion(no_crate_example, code = "", style("foo"))] -//~^ ERROR `#[suggestion(style(...))]` is not a valid attribute +//~^ ERROR expected `= "xxx"` +//~| ERROr expected `,` struct SuggestionStyleInvalid4 { #[primary_span] sub: Span, diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index d8bf0ba413c..4211b91f04a 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -45,97 +45,97 @@ LL | #[label("...")] | ^^^^^ error: invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:104:9 + --> $DIR/subdiagnostic-derive.rs:103:9 | LL | #[label(slug = 4)] | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:104:1 + --> $DIR/subdiagnostic-derive.rs:103:1 | LL | #[label(slug = 4)] | ^^^^^^^^^^^^^^^^^^ error: invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:114:9 + --> $DIR/subdiagnostic-derive.rs:113:9 | LL | #[label(slug("..."))] | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:114:1 + --> $DIR/subdiagnostic-derive.rs:113:1 | LL | #[label(slug("..."))] | ^^^^^^^^^^^^^^^^^^^^^ error: unexpected end of input, unexpected token in nested attribute, expected ident - --> $DIR/subdiagnostic-derive.rs:134:9 + --> $DIR/subdiagnostic-derive.rs:133:9 | LL | #[label()] | ^ error: invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:143:27 + --> $DIR/subdiagnostic-derive.rs:142:27 | LL | #[label(no_crate_example, code = "...")] | ^^^^ error: invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:152:27 + --> $DIR/subdiagnostic-derive.rs:151:27 | LL | #[label(no_crate_example, applicability = "machine-applicable")] | ^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:161:1 + --> $DIR/subdiagnostic-derive.rs:160:1 | LL | #[foo] | ^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:175:5 + --> $DIR/subdiagnostic-derive.rs:174:5 | LL | #[bar] | ^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:187:5 + --> $DIR/subdiagnostic-derive.rs:186:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:199:5 + --> $DIR/subdiagnostic-derive.rs:198:5 | LL | #[bar = 4] | ^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:211:5 + --> $DIR/subdiagnostic-derive.rs:210:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ error: invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:223:13 + --> $DIR/subdiagnostic-derive.rs:222:13 | LL | #[label(code = "...")] | ^^^^ error: diagnostic slug must be first argument of a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:223:5 + --> $DIR/subdiagnostic-derive.rs:222:5 | LL | #[label(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^ error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/subdiagnostic-derive.rs:252:5 + --> $DIR/subdiagnostic-derive.rs:251:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:249:1 + --> $DIR/subdiagnostic-derive.rs:248:1 | LL | / #[label(no_crate_example)] LL | | @@ -147,13 +147,13 @@ LL | | } | |_^ error: `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:262:5 + --> $DIR/subdiagnostic-derive.rs:261:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:272:5 + --> $DIR/subdiagnostic-derive.rs:271:5 | LL | #[bar] | ^^^^^^ @@ -161,13 +161,13 @@ LL | #[bar] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:283:5 + --> $DIR/subdiagnostic-derive.rs:282:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:294:5 + --> $DIR/subdiagnostic-derive.rs:293:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ @@ -175,7 +175,7 @@ LL | #[bar("...")] = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:310:1 + --> $DIR/subdiagnostic-derive.rs:309:1 | LL | / union AC { LL | | @@ -185,73 +185,73 @@ LL | | } | |_^ error: a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:325:44 + --> $DIR/subdiagnostic-derive.rs:324:44 | LL | #[label(no_crate_example, no_crate::example)] | ^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:338:5 + --> $DIR/subdiagnostic-derive.rs:337:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:335:5 + --> $DIR/subdiagnostic-derive.rs:334:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:344:8 + --> $DIR/subdiagnostic-derive.rs:343:8 | LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:381:1 + --> $DIR/subdiagnostic-derive.rs:380:46 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:381:1 + --> $DIR/subdiagnostic-derive.rs:380:32 | LL | #[suggestion(no_crate_example, code = "...", code = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:399:5 + --> $DIR/subdiagnostic-derive.rs:398:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:396:5 + --> $DIR/subdiagnostic-derive.rs:395:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:409:5 + --> $DIR/subdiagnostic-derive.rs:408:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:422:1 + --> $DIR/subdiagnostic-derive.rs:421:1 | LL | #[suggestion(no_crate_example)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:432:62 + --> $DIR/subdiagnostic-derive.rs:431:62 | LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")] | ^^^^^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:450:1 + --> $DIR/subdiagnostic-derive.rs:449:1 | LL | / #[suggestion(no_crate_example, code = "...")] LL | | @@ -261,25 +261,25 @@ LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:464:1 + --> $DIR/subdiagnostic-derive.rs:463:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:484:39 + --> $DIR/subdiagnostic-derive.rs:483:39 | LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:503:43 + --> $DIR/subdiagnostic-derive.rs:502:43 | LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")] | ^^^^^^^ error: `#[suggestion_part]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:526:5 + --> $DIR/subdiagnostic-derive.rs:525:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ @@ -287,7 +287,7 @@ LL | #[suggestion_part] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead error: `#[suggestion_part(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:529:5 + --> $DIR/subdiagnostic-derive.rs:528:5 | LL | #[suggestion_part(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -295,7 +295,7 @@ LL | #[suggestion_part(code = "...")] = help: `#[suggestion_part(...)]` is only valid in multipart suggestions error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:523:1 + --> $DIR/subdiagnostic-derive.rs:522:1 | LL | / #[suggestion(no_crate_example, code = "...")] LL | | @@ -307,7 +307,7 @@ LL | | } | |_^ error: invalid nested attribute - --> $DIR/subdiagnostic-derive.rs:538:42 + --> $DIR/subdiagnostic-derive.rs:537:42 | LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] | ^^^^ @@ -315,7 +315,7 @@ LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "mac = help: only `style` and `applicability` are valid nested attributes error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:538:1 + --> $DIR/subdiagnostic-derive.rs:537:1 | LL | / #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")] LL | | @@ -326,19 +326,19 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:548:5 + --> $DIR/subdiagnostic-derive.rs:547:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: unexpected end of input, unexpected token in nested attribute, expected ident - --> $DIR/subdiagnostic-derive.rs:556:23 + --> $DIR/subdiagnostic-derive.rs:555:23 | LL | #[suggestion_part()] | ^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:565:5 + --> $DIR/subdiagnostic-derive.rs:564:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -346,7 +346,7 @@ LL | #[primary_span] = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]` error: multipart suggestion without any `#[suggestion_part(...)]` fields - --> $DIR/subdiagnostic-derive.rs:562:1 + --> $DIR/subdiagnostic-derive.rs:561:1 | LL | / #[multipart_suggestion(no_crate_example)] LL | | @@ -358,13 +358,13 @@ LL | | } | |_^ error: `#[suggestion_part(...)]` attribute without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:573:5 + --> $DIR/subdiagnostic-derive.rs:572:5 | LL | #[suggestion_part] | ^^^^^^^^^^^^^^^^^^ error: `code` is the only valid nested attribute - --> $DIR/subdiagnostic-derive.rs:579:23 + --> $DIR/subdiagnostic-derive.rs:578:23 | LL | #[suggestion_part(foo = "bar")] | ^^^ @@ -382,28 +382,28 @@ LL | #[suggestion_part()] | ^^^^^^^^^^^^^^^^^^^^ error: unexpected end of input, unexpected token in nested attribute, expected ident - --> $DIR/subdiagnostic-derive.rs:576:23 + --> $DIR/subdiagnostic-derive.rs:575:23 | LL | #[suggestion_part()] | ^ error: expected `,` - --> $DIR/subdiagnostic-derive.rs:579:27 + --> $DIR/subdiagnostic-derive.rs:578:27 | LL | #[suggestion_part(foo = "bar")] | ^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:593:5 + --> $DIR/subdiagnostic-derive.rs:593:37 | LL | #[suggestion_part(code = "...", code = ",,,")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:593:5 + --> $DIR/subdiagnostic-derive.rs:593:23 | LL | #[suggestion_part(code = "...", code = ",,,")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."` --> $DIR/subdiagnostic-derive.rs:622:5 @@ -424,55 +424,55 @@ LL | #[suggestion_part(code("foo"))] | ^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:679:41 + --> $DIR/subdiagnostic-derive.rs:680:41 | LL | #[suggestion_part(code("foo", "bar"))] | ^ error: unexpected token - --> $DIR/subdiagnostic-derive.rs:679:28 + --> $DIR/subdiagnostic-derive.rs:680:28 | LL | #[suggestion_part(code("foo", "bar"))] | ^^^^^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:688:30 + --> $DIR/subdiagnostic-derive.rs:690:30 | LL | #[suggestion_part(code(3))] | ^ error: unexpected token - --> $DIR/subdiagnostic-derive.rs:688:28 + --> $DIR/subdiagnostic-derive.rs:690:28 | LL | #[suggestion_part(code(3))] | ^ error: expected exactly one string literal for `code = ...` - --> $DIR/subdiagnostic-derive.rs:697:29 + --> $DIR/subdiagnostic-derive.rs:700:29 | LL | #[suggestion_part(code())] | ^ error: expected string literal - --> $DIR/subdiagnostic-derive.rs:706:30 + --> $DIR/subdiagnostic-derive.rs:712:30 | LL | #[suggestion_part(code = 3)] | ^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:748:1 + --> $DIR/subdiagnostic-derive.rs:754:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:748:1 + --> $DIR/subdiagnostic-derive.rs:754:1 | LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:757:1 + --> $DIR/subdiagnostic-derive.rs:763:1 | LL | #[suggestion_hidden(no_crate_example, code = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -480,7 +480,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: `#[suggestion_hidden(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:765:1 + --> $DIR/subdiagnostic-derive.rs:771:1 | LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -488,7 +488,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")] = help: Use `#[suggestion(..., style = "hidden")]` instead error: invalid suggestion style - --> $DIR/subdiagnostic-derive.rs:773:51 + --> $DIR/subdiagnostic-derive.rs:779:51 | LL | #[suggestion(no_crate_example, code = "", style = "foo")] | ^^^^^ @@ -496,31 +496,31 @@ LL | #[suggestion(no_crate_example, code = "", style = "foo")] = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only` error: expected `= "xxx"` - --> $DIR/subdiagnostic-derive.rs:781:49 + --> $DIR/subdiagnostic-derive.rs:787:49 | LL | #[suggestion(no_crate_example, code = "", style = 42)] | ^ error: a diagnostic slug must be the first argument to the attribute - --> $DIR/subdiagnostic-derive.rs:789:48 + --> $DIR/subdiagnostic-derive.rs:795:48 | LL | #[suggestion(no_crate_example, code = "", style)] | ^ error: expected `= "xxx"` - --> $DIR/subdiagnostic-derive.rs:797:48 + --> $DIR/subdiagnostic-derive.rs:803:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] | ^ error: expected `,` - --> $DIR/subdiagnostic-derive.rs:797:48 + --> $DIR/subdiagnostic-derive.rs:803:48 | LL | #[suggestion(no_crate_example, code = "", style("foo"))] | ^ error: `#[primary_span]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:808:5 + --> $DIR/subdiagnostic-derive.rs:815:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ @@ -529,7 +529,7 @@ LL | #[primary_span] = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:805:1 + --> $DIR/subdiagnostic-derive.rs:812:1 | LL | / #[suggestion(no_crate_example, code = "")] LL | | @@ -547,61 +547,61 @@ LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:161:3 + --> $DIR/subdiagnostic-derive.rs:160:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:175:7 + --> $DIR/subdiagnostic-derive.rs:174:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:187:7 + --> $DIR/subdiagnostic-derive.rs:186:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:199:7 + --> $DIR/subdiagnostic-derive.rs:198:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:211:7 + --> $DIR/subdiagnostic-derive.rs:210:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:272:7 + --> $DIR/subdiagnostic-derive.rs:271:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:283:7 + --> $DIR/subdiagnostic-derive.rs:282:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:294:7 + --> $DIR/subdiagnostic-derive.rs:293:7 | LL | #[bar("...")] | ^^^ error[E0425]: cannot find value `slug` in module `crate::fluent_generated` - --> $DIR/subdiagnostic-derive.rs:124:9 + --> $DIR/subdiagnostic-derive.rs:123:9 | LL | #[label(slug)] | ^^^^ not found in `crate::fluent_generated` error[E0425]: cannot find value `__code_29` in this scope - --> $DIR/subdiagnostic-derive.rs:703:10 + --> $DIR/subdiagnostic-derive.rs:706:10 | LL | #[derive(Subdiagnostic)] | ^^^^^^^^^^^^^ not found in this scope From d764c2da99fb20032e4dc41c1c23bb90aabd39ad Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 6 Apr 2023 04:52:03 +0000 Subject: [PATCH 4/4] address comments --- .../rustc_macros/src/diagnostics/utils.rs | 93 ++++++++++--------- compiler/rustc_macros/src/newtype.rs | 2 +- 2 files changed, 50 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 838347ecb61..b9b09c66230 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -420,6 +420,51 @@ pub(super) enum AllowMultipleAlternatives { Yes, } +fn parse_suggestion_values( + nested: ParseNestedMeta<'_>, + allow_multiple: AllowMultipleAlternatives, +) -> syn::Result> { + let values = if let Ok(val) = nested.value() { + vec![val.parse()?] + } else { + let content; + parenthesized!(content in nested.input); + + if let AllowMultipleAlternatives::No = allow_multiple { + span_err( + nested.input.span().unwrap(), + "expected exactly one string literal for `code = ...`", + ) + .emit(); + vec![] + } else { + let literals = Punctuated::::parse_terminated(&content); + + match literals { + Ok(p) if p.is_empty() => { + span_err( + content.span().unwrap(), + "expected at least one string literal for `code(...)`", + ) + .emit(); + vec![] + } + Ok(p) => p.into_iter().collect(), + Err(_) => { + span_err( + content.span().unwrap(), + "`code(...)` must contain only string literals", + ) + .emit(); + vec![] + } + } + } + }; + + Ok(values) +} + /// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or /// `#[suggestion*(code("foo", "bar"))]` attribute field pub(super) fn build_suggestion_code( @@ -428,47 +473,7 @@ pub(super) fn build_suggestion_code( fields: &impl HasFieldMap, allow_multiple: AllowMultipleAlternatives, ) -> TokenStream { - let values = match (|| { - let values: Vec = if let Ok(val) = nested.value() { - vec![val.parse()?] - } else { - let content; - parenthesized!(content in nested.input); - - if let AllowMultipleAlternatives::No = allow_multiple { - span_err( - nested.input.span().unwrap(), - "expected exactly one string literal for `code = ...`", - ) - .emit(); - vec![] - } else { - let literals = Punctuated::::parse_terminated(&content); - - match literals { - Ok(p) if p.is_empty() => { - span_err( - content.span().unwrap(), - "expected at least one string literal for `code(...)`", - ) - .emit(); - vec![] - } - Ok(p) => p.into_iter().collect(), - Err(_) => { - span_err( - content.span().unwrap(), - "`code(...)` must contain only string literals", - ) - .emit(); - vec![] - } - } - } - }; - - Ok(values) - })() { + let values = match parse_suggestion_values(nested, allow_multiple) { Ok(x) => x, Err(e) => return e.into_compile_error(), }; @@ -706,14 +711,14 @@ impl SubdiagnosticKind { let path_span = nested.path.span().unwrap(); let val_span = nested.input.span().unwrap(); - macro get_string() { - { + macro_rules! get_string { + () => {{ let Ok(value) = nested.value().and_then(|x| x.parse::()) else { span_err(val_span, "expected `= \"xxx\"`").emit(); return Ok(()); }; value - } + }}; } let mut has_errors = false; diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs index 04e762e91de..78a6f74887d 100644 --- a/compiler/rustc_macros/src/newtype.rs +++ b/compiler/rustc_macros/src/newtype.rs @@ -47,7 +47,7 @@ impl Parse for Newtype { false } "debug_format" => { - let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. } ) = &attr.meta else { + let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else { panic!("#[debug_format = FMT] attribute requires a format"); };