diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index c75d83bd0a0e3..aa355150b4f81 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -36,7 +36,7 @@ pub fn expand_cfg( } #[derive(SessionDiagnostic)] -#[error(slug = "builtin-macros-requires-cfg-pattern")] +#[error(builtin_macros::requires_cfg_pattern)] struct RequiresCfgPattern { #[primary_span] #[label] @@ -44,7 +44,7 @@ struct RequiresCfgPattern { } #[derive(SessionDiagnostic)] -#[error(slug = "builtin-macros-expected-one-cfg-pattern")] +#[error(builtin_macros::expected_one_cfg_pattern)] struct OneCfgPattern { #[primary_span] span: Span, diff --git a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl index 1d3e33c81851f..4a42d52f71004 100644 --- a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl +++ b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl @@ -1,5 +1,5 @@ -builtin-macros-requires-cfg-pattern = +builtin_macros-requires-cfg-pattern = macro requires a cfg-pattern as an argument .label = cfg-pattern required -builtin-macros-expected-one-cfg-pattern = expected 1 cfg-pattern +builtin_macros-expected-one-cfg-pattern = expected 1 cfg-pattern diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 7211c05432698..673e160cc1e74 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -258,18 +258,6 @@ pub enum SubdiagnosticMessage { FluentAttr(FluentId), } -impl SubdiagnosticMessage { - /// Create a `SubdiagnosticMessage` for the provided Fluent attribute. - pub fn attr(id: impl Into) -> Self { - SubdiagnosticMessage::FluentAttr(id.into()) - } - - /// Create a `SubdiagnosticMessage` for the provided Fluent identifier. - pub fn message(id: impl Into) -> Self { - SubdiagnosticMessage::FluentIdentifier(id.into()) - } -} - /// `From` impl that enables existing diagnostic calls to functions which now take /// `impl Into` to continue to work as before. impl> From for SubdiagnosticMessage { @@ -332,11 +320,6 @@ impl DiagnosticMessage { _ => panic!("expected non-translatable diagnostic message"), } } - - /// Create a `DiagnosticMessage` for the provided Fluent identifier. - pub fn new(id: impl Into) -> Self { - DiagnosticMessage::FluentIdentifier(id.into(), None) - } } /// `From` impl that enables existing diagnostic calls to functions which now take @@ -347,6 +330,27 @@ impl> From for DiagnosticMessage { } } +/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but +/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the +/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be +/// able to convert between these, as much as they'll be converted back into `DiagnosticMessage` +/// using `with_subdiagnostic_message` eventually. Don't use this other than for the derive. +impl Into for DiagnosticMessage { + fn into(self) -> SubdiagnosticMessage { + match self { + DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s), + DiagnosticMessage::FluentIdentifier(id, None) => { + SubdiagnosticMessage::FluentIdentifier(id) + } + // There isn't really a sensible behaviour for this because it loses information but + // this is the most sensible of the behaviours. + DiagnosticMessage::FluentIdentifier(_, Some(attr)) => { + SubdiagnosticMessage::FluentAttr(attr) + } + } + } +} + /// A span together with some additional data. #[derive(Clone, Debug)] pub struct SpanLabel { diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 95ee0d4a060d2..d0c8652718969 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -12,7 +12,9 @@ use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use std::collections::HashMap; use std::str::FromStr; -use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, Type}; +use syn::{ + parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type, +}; use synstructure::{BindingInfo, Structure}; /// The central struct for constructing the `into_diagnostic` method from an annotated struct. @@ -118,23 +120,23 @@ impl<'a> SessionDiagnosticDerive<'a> { return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); } (Some((kind, _)), None) => { - span_err(span, "`slug` not specified") - .help(&format!("use the `#[{}(slug = \"...\")]` attribute to set this diagnostic's slug", kind.descr())) + span_err(span, "diagnostic slug not specified") + .help(&format!( + "specify the slug as the first argument to the attribute, such as \ + `#[{}(typeck::example_error)]`", + kind.descr() + )) .emit(); return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error(); } (Some((SessionDiagnosticKind::Error, _)), Some((slug, _))) => { quote! { - let mut #diag = #sess.struct_err( - rustc_errors::DiagnosticMessage::new(#slug), - ); + let mut #diag = #sess.struct_err(rustc_errors::fluent::#slug); } } (Some((SessionDiagnosticKind::Warn, _)), Some((slug, _))) => { quote! { - let mut #diag = #sess.struct_warn( - rustc_errors::DiagnosticMessage::new(#slug), - ); + let mut #diag = #sess.struct_warn(rustc_errors::fluent::#slug); } } }; @@ -226,7 +228,7 @@ struct SessionDiagnosticDeriveBuilder { kind: Option<(SessionDiagnosticKind, proc_macro::Span)>, /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// has the actual diagnostic message. - slug: Option<(String, proc_macro::Span)>, + slug: Option<(Path, proc_macro::Span)>, /// Error codes are a optional part of the struct attribute - this is only set to detect /// multiple specifications. code: Option<(String, proc_macro::Span)>, @@ -240,50 +242,79 @@ impl HasFieldMap for SessionDiagnosticDeriveBuilder { impl SessionDiagnosticDeriveBuilder { /// Establishes state in the `SessionDiagnosticDeriveBuilder` resulting from the struct - /// attributes like `#[error(..)#`, such as the diagnostic kind and slug. Generates + /// attributes like `#[error(..)`, such as the diagnostic kind and slug. Generates /// diagnostic builder calls for setting error code and creating note/help messages. fn generate_structure_code( &mut self, attr: &Attribute, ) -> Result { + let diag = &self.diag; let span = attr.span().unwrap(); let name = attr.path.segments.last().unwrap().ident.to_string(); let name = name.as_str(); let meta = attr.parse_meta()?; - if matches!(name, "help" | "note") && matches!(meta, Meta::Path(_) | Meta::NameValue(_)) { - let diag = &self.diag; - let id = match meta { - Meta::Path(..) => quote! { #name }, - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - quote! { #s } - } - _ => unreachable!(), - }; - let fn_name = proc_macro2::Ident::new(name, attr.span()); - - return Ok(quote! { - #diag.#fn_name(rustc_errors::SubdiagnosticMessage::attr(#id)); - }); - } + let is_help_or_note = matches!(name, "help" | "note"); let nested = match meta { + // Most attributes are lists, like `#[error(..)]`/`#[warning(..)]` for most cases or + // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. Meta::List(MetaList { ref nested, .. }) => nested, + // Subdiagnostics without spans can be applied to the type too, and these are just + // paths: `#[help]` and `#[note]` + Meta::Path(_) if is_help_or_note => { + let fn_name = proc_macro2::Ident::new(name, attr.span()); + return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); }); + } _ => throw_invalid_attr!(attr, &meta), }; - let kind = match name { - "error" => SessionDiagnosticKind::Error, - "warning" => SessionDiagnosticKind::Warn, + // Check the kind before doing any further processing so that there aren't misleading + // "no kind specified" errors if there are failures later. + match name { + "error" => self.kind.set_once((SessionDiagnosticKind::Error, span)), + "warning" => self.kind.set_once((SessionDiagnosticKind::Warn, span)), + "help" | "note" => (), _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `error` and `warning` are valid attributes") + diag.help("only `error`, `warning`, `help` and `note` are valid attributes") }), - }; - self.kind.set_once((kind, span)); + } + + // First nested element should always be the path, e.g. `#[error(typeck::invalid)]` or + // `#[help(typeck::another_help)]`. + let mut nested_iter = nested.into_iter(); + if let Some(nested_attr) = nested_iter.next() { + // Report an error if there are any other list items after the path. + if is_help_or_note && nested_iter.next().is_some() { + throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("`help` and `note` struct attributes can only have one argument") + }); + } + match nested_attr { + NestedMeta::Meta(Meta::Path(path)) if is_help_or_note => { + let fn_name = proc_macro2::Ident::new(name, attr.span()); + return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); }); + } + NestedMeta::Meta(Meta::Path(path)) => { + self.slug.set_once((path.clone(), span)); + } + NestedMeta::Meta(meta @ Meta::NameValue(_)) + if !is_help_or_note + && meta.path().segments.last().unwrap().ident.to_string() == "code" => + { + // don't error for valid follow-up attributes + } + nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help("first argument of the attribute should be the diagnostic slug") + }), + }; + } + + // Remaining attributes are optional, only `code = ".."` at the moment. let mut tokens = Vec::new(); - for nested_attr in nested { + for nested_attr in nested_iter { let meta = match nested_attr { syn::NestedMeta::Meta(meta) => meta, _ => throw_invalid_nested_attr!(attr, &nested_attr), @@ -291,28 +322,24 @@ impl SessionDiagnosticDeriveBuilder { let path = meta.path(); let nested_name = path.segments.last().unwrap().ident.to_string(); - match &meta { - // Struct attributes are only allowed to be applied once, and the diagnostic - // changes will be set in the initialisation code. - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - let span = s.span().unwrap(); - match nested_name.as_str() { - "slug" => { - self.slug.set_once((s.value(), span)); - } - "code" => { - self.code.set_once((s.value(), span)); - let (diag, code) = (&self.diag, &self.code.as_ref().map(|(v, _)| v)); - tokens.push(quote! { - #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); - }); - } - _ => invalid_nested_attr(attr, &nested_attr) - .help("only `slug` and `code` are valid nested attributes") - .emit(), + // Struct attributes are only allowed to be applied once, and the diagnostic + // changes will be set in the initialisation code. + if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta { + let span = s.span().unwrap(); + match nested_name.as_str() { + "code" => { + self.code.set_once((s.value(), span)); + let code = &self.code.as_ref().map(|(v, _)| v); + tokens.push(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(), } - _ => invalid_nested_attr(attr, &nested_attr).emit(), + } else { + invalid_nested_attr(attr, &nested_attr).emit() } } @@ -382,142 +409,215 @@ impl SessionDiagnosticDeriveBuilder { info: FieldInfo<'_>, binding: TokenStream, ) -> Result { + let meta = attr.parse_meta()?; + match meta { + Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding), + Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding), + _ => throw_invalid_attr!(attr, &meta), + } + } + + fn generate_inner_field_code_path( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + binding: TokenStream, + ) -> Result { + assert!(matches!(attr.parse_meta()?, Meta::Path(_))); let diag = &self.diag; + let meta = attr.parse_meta()?; + let ident = &attr.path.segments.last().unwrap().ident; let name = ident.to_string(); let name = name.as_str(); + match name { + "skip_arg" => { + // Don't need to do anything - by virtue of the attribute existing, the + // `set_arg` call will not be generated. + Ok(quote! {}) + } + "primary_span" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(quote! { + #diag.set_span(#binding); + }) + } + "label" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label })) + } + "note" | "help" => { + let path = match name { + "note" => parse_quote! { _subdiag::note }, + "help" => parse_quote! { _subdiag::help }, + _ => unreachable!(), + }; + if type_matches_path(&info.ty, &["rustc_span", "Span"]) { + Ok(self.add_spanned_subdiagnostic(binding, ident, path)) + } else if type_is_unit(&info.ty) { + Ok(self.add_subdiagnostic(ident, path)) + } else { + report_type_error(attr, "`Span` or `()`")?; + } + } + "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), + _ => throw_invalid_attr!(attr, &meta, |diag| { + diag.help( + "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \ + are valid field attributes", + ) + }), + } + } + fn generate_inner_field_code_list( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + binding: TokenStream, + ) -> Result { let meta = attr.parse_meta()?; - match meta { - Meta::Path(_) => match name { - "skip_arg" => { - // Don't need to do anything - by virtue of the attribute existing, the - // `set_arg` call will not be generated. - Ok(quote! {}) - } - "primary_span" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(quote! { - #diag.set_span(#binding); - }) - } - "label" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, name)) - } - "note" | "help" => { - if type_matches_path(&info.ty, &["rustc_span", "Span"]) { - Ok(self.add_spanned_subdiagnostic(binding, ident, name)) - } else if type_is_unit(&info.ty) { - Ok(self.add_subdiagnostic(ident, name)) - } else { - report_type_error(attr, "`Span` or `()`")?; - } - } - "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag - .help("only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes") - }), - }, - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(ref s), .. }) => match name { - "label" => { - report_error_if_not_applied_to_span(attr, &info)?; - Ok(self.add_spanned_subdiagnostic(binding, ident, &s.value())) - } - "note" | "help" => { - if type_matches_path(&info.ty, &["rustc_span", "Span"]) { - Ok(self.add_spanned_subdiagnostic(binding, ident, &s.value())) - } else if type_is_unit(&info.ty) { - Ok(self.add_subdiagnostic(ident, &s.value())) - } else { - report_type_error(attr, "`Span` or `()`")?; - } - } - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `label`, `note` and `help` are valid field attributes") - }), - }, - Meta::List(MetaList { ref path, ref nested, .. }) => { - let name = path.segments.last().unwrap().ident.to_string(); - let name = name.as_ref(); - - match name { - "suggestion" | "suggestion_short" | "suggestion_hidden" - | "suggestion_verbose" => (), - _ => throw_invalid_attr!(attr, &meta, |diag| { - diag - .help("only `suggestion{,_short,_hidden,_verbose}` are valid field attributes") - }), - }; + let Meta::List(MetaList { ref path, ref nested, .. }) = meta else { unreachable!() }; - let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; + let ident = &attr.path.segments.last().unwrap().ident; + let name = path.segments.last().unwrap().ident.to_string(); + let name = name.as_ref(); + match name { + "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => { + return self.generate_inner_field_code_suggestion(attr, info); + } + "label" | "help" | "note" => (), + _ => throw_invalid_attr!(attr, &meta, |diag| { + diag.help( + "only `label`, `note`, `help` or `suggestion{,_short,_hidden,_verbose}` are \ + valid field attributes", + ) + }), + } - let mut msg = None; - let mut code = None; + // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a + // path, e.g. `#[label(typeck::label)]`. + let mut nested_iter = nested.into_iter(); + let msg = match nested_iter.next() { + Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(), + Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr), + None => throw_invalid_attr!(attr, &meta), + }; - for nested_attr in nested { - let meta = match nested_attr { - syn::NestedMeta::Meta(ref meta) => meta, - syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr), - }; + // None of these attributes should have anything following the slug. + if nested_iter.next().is_some() { + throw_invalid_attr!(attr, &meta); + } - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); - match meta { - Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { - let span = meta.span().unwrap(); - match nested_name { - "message" => { - msg = Some(s.value()); - } - "code" => { - let formatted_str = self.build_format(&s.value(), s.span()); - code = Some(formatted_str); + match name { + "label" => { + report_error_if_not_applied_to_span(attr, &info)?; + Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) + } + "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => { + Ok(self.add_spanned_subdiagnostic(binding, ident, msg)) + } + "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)), + "note" | "help" => { + report_type_error(attr, "`Span` or `()`")?; + } + _ => unreachable!(), + } + } + + fn generate_inner_field_code_suggestion( + &mut self, + attr: &Attribute, + info: FieldInfo<'_>, + ) -> Result { + let diag = &self.diag; + + let mut meta = attr.parse_meta()?; + let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta else { unreachable!() }; + + let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?; + + let mut msg = None; + let mut code = None; + + let mut nested_iter = nested.into_iter().peekable(); + if let Some(nested_attr) = nested_iter.peek() { + if let NestedMeta::Meta(Meta::Path(path)) = nested_attr { + msg = Some(path.clone()); + } + }; + // Move the iterator forward if a path was found (don't otherwise so that + // code/applicability can be found or an error emitted). + if msg.is_some() { + let _ = nested_iter.next(); + } + + for nested_attr in nested_iter { + let meta = match nested_attr { + syn::NestedMeta::Meta(ref meta) => meta, + syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr), + }; + + let nested_name = meta.path().segments.last().unwrap().ident.to_string(); + let nested_name = nested_name.as_str(); + match meta { + Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { + let span = meta.span().unwrap(); + match nested_name { + "code" => { + let formatted_str = self.build_format(&s.value(), s.span()); + code = Some(formatted_str); + } + "applicability" => { + applicability = match applicability { + Some(v) => { + span_err( + span, + "applicability cannot be set in both the field and \ + attribute", + ) + .emit(); + Some(v) } - "applicability" => { - applicability = match applicability { - Some(v) => { - span_err( - span, - "applicability cannot be set in both the field and attribute" - ).emit(); - Some(v) - } - None => match Applicability::from_str(&s.value()) { - Ok(v) => Some(quote! { #v }), - Err(()) => { - span_err(span, "invalid applicability").emit(); - None - } - }, + None => match Applicability::from_str(&s.value()) { + Ok(v) => Some(quote! { #v }), + Err(()) => { + span_err(span, "invalid applicability").emit(); + None } - } - _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help( - "only `message`, `code` and `applicability` are valid field attributes", - ) - }), + }, } } - _ => throw_invalid_nested_attr!(attr, &nested_attr), + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help( + "only `message`, `code` and `applicability` are valid field \ + attributes", + ) + }), } } + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + if matches!(meta, Meta::Path(_)) { + diag.help("a diagnostic slug must be the first argument to the attribute") + } else { + diag + } + }), + } + } - let applicability = applicability - .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); + let applicability = + applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified)); - let method = format_ident!("span_{}", name); + let name = path.segments.last().unwrap().ident.to_string(); + let method = format_ident!("span_{}", name); - let msg = msg.as_deref().unwrap_or("suggestion"); - let msg = quote! { rustc_errors::SubdiagnosticMessage::attr(#msg) }; - let code = code.unwrap_or_else(|| quote! { String::new() }); + let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion }); + let msg = quote! { rustc_errors::fluent::#msg }; + let code = code.unwrap_or_else(|| quote! { String::new() }); - Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) - } - _ => throw_invalid_attr!(attr, &meta), - } + Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); }) } /// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug @@ -526,24 +626,24 @@ impl SessionDiagnosticDeriveBuilder { &self, field_binding: TokenStream, kind: &Ident, - fluent_attr_identifier: &str, + fluent_attr_identifier: Path, ) -> TokenStream { let diag = &self.diag; let fn_name = format_ident!("span_{}", kind); quote! { #diag.#fn_name( #field_binding, - rustc_errors::SubdiagnosticMessage::attr(#fluent_attr_identifier) + rustc_errors::fluent::#fluent_attr_identifier ); } } /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug /// and `fluent_attr_identifier`. - fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: &str) -> TokenStream { + fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { let diag = &self.diag; quote! { - #diag.#kind(rustc_errors::SubdiagnosticMessage::attr(#fluent_attr_identifier)); + #diag.#kind(rustc_errors::fluent::#fluent_attr_identifier); } } @@ -569,7 +669,8 @@ impl SessionDiagnosticDeriveBuilder { } else { throw_span_err!( info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more than one `Span`" + "type of field annotated with `#[suggestion(...)]` contains more \ + than one `Span`" ); } } else if type_matches_path(elem, &["rustc_errors", "Applicability"]) { @@ -578,7 +679,8 @@ impl SessionDiagnosticDeriveBuilder { } else { throw_span_err!( info.span.unwrap(), - "type of field annotated with `#[suggestion(...)]` contains more than one Applicability" + "type of field annotated with `#[suggestion(...)]` contains more \ + than one Applicability" ); } } @@ -595,12 +697,18 @@ impl SessionDiagnosticDeriveBuilder { } throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| { - diag.help("`#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`") + diag.help( + "`#[suggestion(...)]` on a tuple field must be applied to fields of type \ + `(Span, Applicability)`", + ) }); } // If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error. _ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| { - diag.help("`#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`") + diag.help( + "`#[suggestion(...)]` should be applied to fields of type `Span` or \ + `(Span, Applicability)`", + ) }), } } diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index fd1dc2f307397..d088402abc6da 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -39,6 +39,19 @@ pub(crate) fn _throw_err( SessionDiagnosticDeriveError::ErrorHandled } +/// Helper function for printing `syn::Path` - doesn't handle arguments in paths and these are +/// unlikely to come up much in use of the macro. +fn path_to_string(path: &syn::Path) -> String { + let mut out = String::new(); + for (i, segment) in path.segments.iter().enumerate() { + if i > 0 || path.leading_colon.is_some() { + out.push_str("::"); + } + out.push_str(&segment.ident.to_string()); + } + out +} + /// Returns an error diagnostic on span `span` with msg `msg`. pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic { Diagnostic::spanned(span, Level::Error, msg) @@ -61,15 +74,13 @@ pub(crate) use throw_span_err; /// Returns an error diagnostic for an invalid attribute. pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { let span = attr.span().unwrap(); - let name = attr.path.segments.last().unwrap().ident.to_string(); - let name = name.as_str(); - + let path = path_to_string(&attr.path); match meta { - Meta::Path(_) => span_err(span, &format!("`#[{}]` is not a valid attribute", name)), + Meta::Path(_) => span_err(span, &format!("`#[{}]` is not a valid attribute", path)), Meta::NameValue(_) => { - span_err(span, &format!("`#[{} = ...]` is not a valid attribute", name)) + span_err(span, &format!("`#[{} = ...]` is not a valid attribute", path)) } - Meta::List(_) => span_err(span, &format!("`#[{}(...)]` is not a valid attribute", name)), + Meta::List(_) => span_err(span, &format!("`#[{}(...)]` is not a valid attribute", path)), } } @@ -101,18 +112,16 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag }; let span = meta.span().unwrap(); - let nested_name = meta.path().segments.last().unwrap().ident.to_string(); - let nested_name = nested_name.as_str(); + let path = path_to_string(meta.path()); match meta { - Meta::NameValue(..) => span_err( - span, - &format!("`#[{}({} = ...)]` is not a valid attribute", name, nested_name), - ), + Meta::NameValue(..) => { + span_err(span, &format!("`#[{}({} = ...)]` is not a valid attribute", name, path)) + } Meta::Path(..) => { - span_err(span, &format!("`#[{}({})]` is not a valid attribute", name, nested_name)) + span_err(span, &format!("`#[{}({})]` is not a valid attribute", name, path)) } Meta::List(..) => { - span_err(span, &format!("`#[{}({}(...))]` is not a valid attribute", name, nested_name)) + span_err(span, &format!("`#[{}({}(...))]` is not a valid attribute", name, path)) } } } diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs index 42a9bf477a41c..2317186e65502 100644 --- a/compiler/rustc_macros/src/diagnostics/fluent.rs +++ b/compiler/rustc_macros/src/diagnostics/fluent.rs @@ -254,6 +254,17 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok ]; #generated + + pub mod _subdiag { + pub const note: crate::SubdiagnosticMessage = + crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("note")); + pub const help: crate::SubdiagnosticMessage = + crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("help")); + pub const label: crate::SubdiagnosticMessage = + crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("label")); + pub const suggestion: crate::SubdiagnosticMessage = + crate::SubdiagnosticMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion")); + } } } .into() diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index 69573d904d4a9..2eee4bfb5dd45 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -22,14 +22,14 @@ use synstructure::Structure; /// # extern crate rust_middle; /// # use rustc_middle::ty::Ty; /// #[derive(SessionDiagnostic)] -/// #[error(code = "E0505", slug = "borrowck-move-out-of-borrow")] +/// #[error(borrowck::move_out_of_borrow, code = "E0505")] /// pub struct MoveOutOfBorrowError<'tcx> { /// pub name: Ident, /// pub ty: Ty<'tcx>, /// #[primary_span] /// #[label] /// pub span: Span, -/// #[label = "first-borrow-label"] +/// #[label(borrowck::first_borrow_label)] /// pub first_borrow_span: Span, /// #[suggestion(code = "{name}.clone()")] /// pub clone_sugg: Option<(Span, Applicability)> @@ -72,12 +72,12 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// ```ignore (rust) /// #[derive(SessionSubdiagnostic)] /// pub enum ExpectedIdentifierLabel<'tcx> { -/// #[label(slug = "parser-expected-identifier")] +/// #[label(parser::expected_identifier)] /// WithoutFound { /// #[primary_span] /// span: Span, /// } -/// #[label(slug = "parser-expected-identifier-found")] +/// #[label(parser::expected_identifier_found)] /// WithFound { /// #[primary_span] /// span: Span, @@ -86,7 +86,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// } /// /// #[derive(SessionSubdiagnostic)] -/// #[suggestion_verbose(slug = "parser-raw-identifier")] +/// #[suggestion_verbose(parser::raw_identifier)] /// pub struct RawIdentifierSuggestion<'tcx> { /// #[primary_span] /// span: Span, diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 9aeb484bfd52d..eab954a9c1bf9 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -13,7 +13,7 @@ use quote::{format_ident, quote}; use std::collections::HashMap; use std::fmt; use std::str::FromStr; -use syn::{spanned::Spanned, Meta, MetaList, MetaNameValue}; +use syn::{parse_quote, spanned::Spanned, Meta, MetaList, MetaNameValue, NestedMeta, Path}; use synstructure::{BindingInfo, Structure, VariantInfo}; /// Which kind of suggestion is being created? @@ -194,8 +194,8 @@ struct SessionSubdiagnosticDeriveBuilder<'a> { kind: Option<(SubdiagnosticKind, proc_macro::Span)>, /// Slug of the subdiagnostic - corresponds to the Fluent identifier for the message - from the - /// `#[kind(slug = "...")]` attribute on the type or variant. - slug: Option<(String, proc_macro::Span)>, + /// `#[kind(slug)]` attribute on the type or variant. + slug: Option<(Path, proc_macro::Span)>, /// If a suggestion, the code to suggest as a replacement - from the `#[kind(code = "...")]` /// attribute on the type or variant. code: Option<(TokenStream, proc_macro::Span)>, @@ -224,9 +224,34 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { let meta = attr.parse_meta()?; let kind = match meta { Meta::List(MetaList { ref nested, .. }) => { - for nested_attr in nested { + let mut nested_iter = nested.into_iter(); + if let Some(nested_attr) = nested_iter.next() { + match nested_attr { + NestedMeta::Meta(Meta::Path(path)) => { + self.slug.set_once((path.clone(), span)); + } + NestedMeta::Meta(meta @ Meta::NameValue(_)) + if matches!( + meta.path().segments.last().unwrap().ident.to_string().as_str(), + "code" | "applicability" + ) => + { + // don't error for valid follow-up attributes + } + nested_attr => { + throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + diag.help( + "first argument of the attribute should be the diagnostic \ + slug", + ) + }) + } + }; + } + + for nested_attr in nested_iter { let meta = match nested_attr { - syn::NestedMeta::Meta(ref meta) => meta, + NestedMeta::Meta(ref meta) => meta, _ => throw_invalid_nested_attr!(attr, &nested_attr), }; @@ -241,7 +266,6 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { let formatted_str = self.build_format(&s.value(), s.span()); self.code.set_once((formatted_str, span)); } - "slug" => self.slug.set_once((s.value(), span)), "applicability" => { let value = match Applicability::from_str(&s.value()) { Ok(v) => v, @@ -253,11 +277,23 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { self.applicability.set_once((quote! { #value }, span)); } _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { - diag.help("only `code`, `slug` and `applicability` are valid nested attributes") + diag.help( + "only `code` and `applicability` are valid nested \ + attributes", + ) }), } } - _ => throw_invalid_nested_attr!(attr, &nested_attr), + _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| { + if matches!(meta, Meta::Path(_)) { + diag.help( + "a diagnostic slug must be the first argument to the \ + attribute", + ) + } else { + diag + } + }), } } @@ -281,10 +317,27 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { ); } + if matches!( + kind, + SubdiagnosticKind::Label | SubdiagnosticKind::Help | SubdiagnosticKind::Note + ) && self.applicability.is_some() + { + throw_span_err!( + span, + &format!( + "`applicability` is not a valid nested attribute of a `{}` attribute", + name + ) + ); + } + if self.slug.is_none() { throw_span_err!( span, - &format!("`slug` must be set in a `#[{}(...)]` attribute", name) + &format!( + "diagnostic slug must be first argument of a `#[{}(...)]` attribute", + name + ) ); } @@ -335,7 +388,10 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { return Ok(quote! {}); } _ => throw_invalid_attr!(attr, &meta, |diag| { - diag.help("only `primary_span`, `applicability` and `skip_arg` are valid field attributes") + diag.help( + "only `primary_span`, `applicability` and `skip_arg` are valid field \ + attributes", + ) }), }, _ => throw_invalid_attr!(attr, &meta), @@ -375,7 +431,11 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { } // Missing slug errors will already have been reported. - let slug = self.slug.as_ref().map(|(slug, _)| &**slug).unwrap_or("missing-slug"); + let slug = self + .slug + .as_ref() + .map(|(slug, _)| slug.clone()) + .unwrap_or_else(|| parse_quote! { you::need::to::specify::a::slug }); let code = match self.code.as_ref() { Some((code, _)) => Some(quote! { #code }), None if is_suggestion => { @@ -397,7 +457,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> { let diag = &self.diag; let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); - let message = quote! { rustc_errors::SubdiagnosticMessage::message(#slug) }; + let message = quote! { rustc_errors::fluent::#slug }; let call = if matches!(kind, SubdiagnosticKind::Suggestion(..)) { if let Some(span) = span_field { quote! { #diag.#name(#span, #message, #code, #applicability); } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ba325d704228d..58d5d43cfbfa8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -244,7 +244,7 @@ impl MultiSugg { } #[derive(SessionDiagnostic)] -#[error(slug = "parser-maybe-report-ambiguous-plus")] +#[error(parser::maybe_report_ambiguous_plus)] struct AmbiguousPlus { pub sum_ty: String, #[primary_span] @@ -253,7 +253,7 @@ struct AmbiguousPlus { } #[derive(SessionDiagnostic)] -#[error(code = "E0178", slug = "parser-maybe-recover-from-bad-type-plus")] +#[error(parser::maybe_recover_from_bad_type_plus, code = "E0178")] struct BadTypePlus { pub ty: String, #[primary_span] @@ -265,7 +265,7 @@ struct BadTypePlus { #[derive(SessionSubdiagnostic)] pub enum BadTypePlusSub { #[suggestion( - slug = "parser-add-paren", + parser::add_paren, code = "{sum_with_parens}", applicability = "machine-applicable" )] @@ -274,12 +274,12 @@ pub enum BadTypePlusSub { #[primary_span] span: Span, }, - #[label(slug = "parser-forgot-paren")] + #[label(parser::forgot_paren)] ForgotParen { #[primary_span] span: Span, }, - #[label(slug = "parser-expect-path")] + #[label(parser::expect_path)] ExpectPath { #[primary_span] span: Span, @@ -287,7 +287,7 @@ pub enum BadTypePlusSub { } #[derive(SessionDiagnostic)] -#[error(slug = "parser-maybe-recover-from-bad-qpath-stage-2")] +#[error(parser::maybe_recover_from_bad_qpath_stage_2)] struct BadQPathStage2 { #[primary_span] #[suggestion(applicability = "maybe-incorrect")] @@ -296,7 +296,7 @@ struct BadQPathStage2 { } #[derive(SessionDiagnostic)] -#[error(slug = "parser-incorrect-semicolon")] +#[error(parser::incorrect_semicolon)] struct IncorrectSemicolon<'a> { #[primary_span] #[suggestion_short(applicability = "machine-applicable")] @@ -307,26 +307,26 @@ struct IncorrectSemicolon<'a> { } #[derive(SessionDiagnostic)] -#[error(slug = "parser-incorrect-use-of-await")] +#[error(parser::incorrect_use_of_await)] struct IncorrectUseOfAwait { #[primary_span] - #[suggestion(message = "parentheses-suggestion", applicability = "machine-applicable")] + #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")] span: Span, } #[derive(SessionDiagnostic)] -#[error(slug = "parser-incorrect-use-of-await")] +#[error(parser::incorrect_use_of_await)] struct IncorrectAwait { #[primary_span] span: Span, - #[suggestion(message = "postfix-suggestion", code = "{expr}.await{question_mark}")] + #[suggestion(parser::postfix_suggestion, code = "{expr}.await{question_mark}")] sugg_span: (Span, Applicability), expr: String, question_mark: &'static str, } #[derive(SessionDiagnostic)] -#[error(slug = "parser-in-in-typo")] +#[error(parser::in_in_typo)] struct InInTypo { #[primary_span] span: Span, diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 67a3d4a4d020c..4cdec615d8290 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -6,18 +6,18 @@ use rustc_session::{parse::ParseSess, SessionDiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; #[derive(SessionDiagnostic)] -#[error(code = "E0062", slug = "typeck-field-multiply-specified-in-initializer")] +#[error(typeck::field_multiply_specified_in_initializer, code = "E0062")] pub struct FieldMultiplySpecifiedInInitializer { #[primary_span] #[label] pub span: Span, - #[label = "previous-use-label"] + #[label(typeck::previous_use_label)] pub prev_span: Span, pub ident: Ident, } #[derive(SessionDiagnostic)] -#[error(code = "E0092", slug = "typeck-unrecognized-atomic-operation")] +#[error(typeck::unrecognized_atomic_operation, code = "E0092")] pub struct UnrecognizedAtomicOperation<'a> { #[primary_span] #[label] @@ -26,7 +26,7 @@ pub struct UnrecognizedAtomicOperation<'a> { } #[derive(SessionDiagnostic)] -#[error(code = "E0094", slug = "typeck-wrong-number-of-generic-arguments-to-intrinsic")] +#[error(typeck::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")] pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { #[primary_span] #[label] @@ -37,7 +37,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> { } #[derive(SessionDiagnostic)] -#[error(code = "E0093", slug = "typeck-unrecognized-intrinsic-function")] +#[error(typeck::unrecognized_intrinsic_function, code = "E0093")] pub struct UnrecognizedIntrinsicFunction { #[primary_span] #[label] @@ -46,19 +46,19 @@ pub struct UnrecognizedIntrinsicFunction { } #[derive(SessionDiagnostic)] -#[error(code = "E0195", slug = "typeck-lifetimes-or-bounds-mismatch-on-trait")] +#[error(typeck::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")] pub struct LifetimesOrBoundsMismatchOnTrait { #[primary_span] #[label] pub span: Span, - #[label = "generics-label"] + #[label(typeck::generics_label)] pub generics_span: Option, pub item_kind: &'static str, pub ident: Ident, } #[derive(SessionDiagnostic)] -#[error(code = "E0120", slug = "typeck-drop-impl-on-wrong-item")] +#[error(typeck::drop_impl_on_wrong_item, code = "E0120")] pub struct DropImplOnWrongItem { #[primary_span] #[label] @@ -66,18 +66,18 @@ pub struct DropImplOnWrongItem { } #[derive(SessionDiagnostic)] -#[error(code = "E0124", slug = "typeck-field-already-declared")] +#[error(typeck::field_already_declared, code = "E0124")] pub struct FieldAlreadyDeclared { pub field_name: Ident, #[primary_span] #[label] pub span: Span, - #[label = "previous-decl-label"] + #[label(typeck::previous_decl_label)] pub prev_span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0184", slug = "typeck-copy-impl-on-type-with-dtor")] +#[error(typeck::copy_impl_on_type_with_dtor, code = "E0184")] pub struct CopyImplOnTypeWithDtor { #[primary_span] #[label] @@ -85,14 +85,14 @@ pub struct CopyImplOnTypeWithDtor { } #[derive(SessionDiagnostic)] -#[error(code = "E0203", slug = "typeck-multiple-relaxed-default-bounds")] +#[error(typeck::multiple_relaxed_default_bounds, code = "E0203")] pub struct MultipleRelaxedDefaultBounds { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0206", slug = "typeck-copy-impl-on-non-adt")] +#[error(typeck::copy_impl_on_non_adt, code = "E0206")] pub struct CopyImplOnNonAdt { #[primary_span] #[label] @@ -100,23 +100,23 @@ pub struct CopyImplOnNonAdt { } #[derive(SessionDiagnostic)] -#[error(code = "E0224", slug = "typeck-trait-object-declared-with-no-traits")] +#[error(typeck::trait_object_declared_with_no_traits, code = "E0224")] pub struct TraitObjectDeclaredWithNoTraits { #[primary_span] pub span: Span, - #[label = "alias-span"] + #[label(typeck::alias_span)] pub trait_alias_span: Option, } #[derive(SessionDiagnostic)] -#[error(code = "E0227", slug = "typeck-ambiguous-lifetime-bound")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0227")] pub struct AmbiguousLifetimeBound { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0229", slug = "typeck-assoc-type-binding-not-allowed")] +#[error(typeck::assoc_type_binding_not_allowed, code = "E0229")] pub struct AssocTypeBindingNotAllowed { #[primary_span] #[label] @@ -124,14 +124,14 @@ pub struct AssocTypeBindingNotAllowed { } #[derive(SessionDiagnostic)] -#[error(code = "E0436", slug = "typeck-functional-record-update-on-non-struct")] +#[error(typeck::functional_record_update_on_non_struct, code = "E0436")] pub struct FunctionalRecordUpdateOnNonStruct { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")] +#[error(typeck::typeof_reserved_keyword_used, code = "E0516")] pub struct TypeofReservedKeywordUsed<'tcx> { pub ty: Ty<'tcx>, #[primary_span] @@ -142,25 +142,25 @@ pub struct TypeofReservedKeywordUsed<'tcx> { } #[derive(SessionDiagnostic)] -#[error(code = "E0572", slug = "typeck-return-stmt-outside-of-fn-body")] +#[error(typeck::return_stmt_outside_of_fn_body, code = "E0572")] pub struct ReturnStmtOutsideOfFnBody { #[primary_span] pub span: Span, - #[label = "encl-body-label"] + #[label(typeck::encl_body_label)] pub encl_body_span: Option, - #[label = "encl-fn-label"] + #[label(typeck::encl_fn_label)] pub encl_fn_span: Option, } #[derive(SessionDiagnostic)] -#[error(code = "E0627", slug = "typeck-yield-expr-outside-of-generator")] +#[error(typeck::yield_expr_outside_of_generator, code = "E0627")] pub struct YieldExprOutsideOfGenerator { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0639", slug = "typeck-struct-expr-non-exhaustive")] +#[error(typeck::struct_expr_non_exhaustive, code = "E0639")] pub struct StructExprNonExhaustive { #[primary_span] pub span: Span, @@ -168,26 +168,26 @@ pub struct StructExprNonExhaustive { } #[derive(SessionDiagnostic)] -#[error(code = "E0699", slug = "typeck-method-call-on-unknown-type")] +#[error(typeck::method_call_on_unknown_type, code = "E0699")] pub struct MethodCallOnUnknownType { #[primary_span] pub span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0719", slug = "typeck-value-of-associated-struct-already-specified")] +#[error(typeck::value_of_associated_struct_already_specified, code = "E0719")] pub struct ValueOfAssociatedStructAlreadySpecified { #[primary_span] #[label] pub span: Span, - #[label = "previous-bound-label"] + #[label(typeck::previous_bound_label)] pub prev_span: Span, pub item_name: Ident, pub def_path: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0745", slug = "typeck-address-of-temporary-taken")] +#[error(typeck::address_of_temporary_taken, code = "E0745")] pub struct AddressOfTemporaryTaken { #[primary_span] #[label] @@ -197,7 +197,7 @@ pub struct AddressOfTemporaryTaken { #[derive(SessionSubdiagnostic)] pub enum AddReturnTypeSuggestion<'tcx> { #[suggestion( - slug = "typeck-add-return-type-add", + typeck::add_return_type_add, code = "-> {found} ", applicability = "machine-applicable" )] @@ -207,7 +207,7 @@ pub enum AddReturnTypeSuggestion<'tcx> { found: Ty<'tcx>, }, #[suggestion( - slug = "typeck-add-return-type-missing-here", + typeck::add_return_type_missing_here, code = "-> _ ", applicability = "has-placeholders" )] @@ -219,12 +219,12 @@ pub enum AddReturnTypeSuggestion<'tcx> { #[derive(SessionSubdiagnostic)] pub enum ExpectedReturnTypeLabel<'tcx> { - #[label(slug = "typeck-expected-default-return-type")] + #[label(typeck::expected_default_return_type)] Unit { #[primary_span] span: Span, }, - #[label(slug = "typeck-expected-return-type")] + #[label(typeck::expected_return_type)] Other { #[primary_span] span: Span, @@ -233,7 +233,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> { } #[derive(SessionDiagnostic)] -#[error(slug = "typeck-unconstrained-opaque-type")] +#[error(typeck::unconstrained_opaque_type)] #[note] pub struct UnconstrainedOpaqueType { #[primary_span] @@ -301,7 +301,7 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams { } #[derive(SessionDiagnostic)] -#[error(code = "E0183", slug = "typeck-manual-implementation")] +#[error(typeck::manual_implementation, code = "E0183")] #[help] pub struct ManualImplementation { #[primary_span] @@ -311,7 +311,7 @@ pub struct ManualImplementation { } #[derive(SessionDiagnostic)] -#[error(slug = "typeck-substs-on-overridden-impl")] +#[error(typeck::substs_on_overridden_impl)] pub struct SubstsOnOverriddenImpl { #[primary_span] pub span: Span, diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs index 817d8531da905..d6f63d44ba6a8 100644 --- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs +++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs @@ -16,14 +16,14 @@ use rustc_session::{parse::ParseSess, SessionDiagnostic}; use rustc_span::Span; #[derive(SessionDiagnostic)] -#[error(slug = "parser-expect-path")] +#[error(parser::expect_path)] struct DeriveSessionDiagnostic { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[note(slug = "note")] +#[note(parser::add_paren)] struct Note { #[primary_span] span: Span, diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index 84d5de173091b..7bec1897fa53e 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -26,15 +26,15 @@ use rustc_errors::Applicability; extern crate rustc_session; #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "hello-world")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct Hello {} #[derive(SessionDiagnostic)] -#[warning(code = "E0123", slug = "hello-world")] +#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")] struct HelloWarn {} #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] //~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs enum SessionDiagnosticOnEnum { Foo, @@ -42,13 +42,13 @@ enum SessionDiagnosticOnEnum { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] #[error = "E0123"] //~^ ERROR `#[error = ...]` is not a valid attribute struct WrongStructAttrStyle {} #[derive(SessionDiagnostic)] -#[nonsense(code = "E0123", slug = "foo")] +#[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] //~^ ERROR `#[nonsense(...)]` is not a valid attribute //~^^ ERROR diagnostic kind not specified //~^^^ ERROR cannot find attribute `nonsense` in this scope @@ -57,31 +57,39 @@ struct InvalidStructAttr {} #[derive(SessionDiagnostic)] #[error("E0123")] //~^ ERROR `#[error("...")]` is not a valid attribute -//~^^ ERROR `slug` not specified +//~^^ ERROR diagnostic slug not specified struct InvalidLitNestedAttr {} #[derive(SessionDiagnostic)] -#[error(nonsense, code = "E0123", slug = "foo")] -//~^ ERROR `#[error(nonsense)]` is not a valid attribute +#[error(nonsense, code = "E0123")] +//~^ ERROR cannot find value `nonsense` in module `rustc_errors::fluent` struct InvalidNestedStructAttr {} #[derive(SessionDiagnostic)] #[error(nonsense("foo"), code = "E0123", slug = "foo")] //~^ ERROR `#[error(nonsense(...))]` is not a valid attribute +//~^^ ERROR diagnostic slug not specified struct InvalidNestedStructAttr1 {} #[derive(SessionDiagnostic)] #[error(nonsense = "...", code = "E0123", slug = "foo")] //~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute +//~^^ ERROR diagnostic slug not specified struct InvalidNestedStructAttr2 {} #[derive(SessionDiagnostic)] #[error(nonsense = 4, code = "E0123", slug = "foo")] //~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute +//~^^ ERROR diagnostic slug not specified struct InvalidNestedStructAttr3 {} #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] +//~^ ERROR `#[error(slug = ...)]` is not a valid attribute +struct InvalidNestedStructAttr4 {} + +#[derive(SessionDiagnostic)] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct WrongPlaceField { #[suggestion = "bar"] //~^ ERROR `#[suggestion = ...]` is not a valid attribute @@ -89,44 +97,45 @@ struct WrongPlaceField { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] -#[error(code = "E0456", slug = "bar")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0456")] //~^ ERROR specified multiple times //~^^ ERROR specified multiple times //~^^^ ERROR specified multiple times struct ErrorSpecifiedTwice {} #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] -#[warning(code = "E0293", slug = "bar")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] //~^ ERROR specified multiple times //~^^ ERROR specified multiple times //~^^^ ERROR specified multiple times struct WarnSpecifiedAfterError {} #[derive(SessionDiagnostic)] -#[error(code = "E0456", code = "E0457", slug = "bar")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] //~^ ERROR specified multiple times struct CodeSpecifiedTwice {} #[derive(SessionDiagnostic)] -#[error(code = "E0456", slug = "foo", slug = "bar")] -//~^ ERROR specified multiple times +#[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")] +//~^ ERROR `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute struct SlugSpecifiedTwice {} #[derive(SessionDiagnostic)] struct KindNotProvided {} //~ ERROR diagnostic kind not specified #[derive(SessionDiagnostic)] -#[error(code = "E0456")] //~ ERROR `slug` not specified +#[error(code = "E0456")] +//~^ ERROR diagnostic slug not specified struct SlugNotProvided {} #[derive(SessionDiagnostic)] -#[error(slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound)] struct CodeNotProvided {} #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct MessageWrongType { #[primary_span] //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` @@ -134,7 +143,7 @@ struct MessageWrongType { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct InvalidPathFieldAttr { #[nonsense] //~^ ERROR `#[nonsense]` is not a valid attribute @@ -143,34 +152,34 @@ struct InvalidPathFieldAttr { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithField { name: String, - #[label = "bar"] + #[label(typeck::label)] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithMessageAppliedToField { - #[label = "bar"] - //~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span` + #[label(typeck::label)] + //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` name: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithNonexistentField { - #[suggestion(message = "bar", code = "{name}")] + #[suggestion(typeck::suggestion, code = "{name}")] //~^ ERROR `name` doesn't refer to a field on this type suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] //~^ ERROR invalid format string: expected `'}'` -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorMissingClosingBrace { - #[suggestion(message = "bar", code = "{name")] + #[suggestion(typeck::suggestion, code = "{name")] suggestion: (Span, Applicability), name: String, val: usize, @@ -178,48 +187,48 @@ struct ErrorMissingClosingBrace { #[derive(SessionDiagnostic)] //~^ ERROR invalid format string: unmatched `}` -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorMissingOpeningBrace { - #[suggestion(message = "bar", code = "name}")] + #[suggestion(typeck::suggestion, code = "name}")] suggestion: (Span, Applicability), name: String, val: usize, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelOnSpan { - #[label = "bar"] + #[label(typeck::label)] sp: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct LabelOnNonSpan { - #[label = "bar"] - //~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span` + #[label(typeck::label)] + //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` id: u32, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct Suggest { - #[suggestion(message = "bar", code = "This is the suggested code")] - #[suggestion_short(message = "qux", code = "This is the suggested code")] - #[suggestion_hidden(message = "foobar", code = "This is the suggested code")] - #[suggestion_verbose(message = "fooqux", code = "This is the suggested code")] + #[suggestion(typeck::suggestion, code = "This is the suggested code")] + #[suggestion_short(typeck::suggestion, code = "This is the suggested code")] + #[suggestion_hidden(typeck::suggestion, code = "This is the suggested code")] + #[suggestion_verbose(typeck::suggestion, code = "This is the suggested code")] suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithoutCode { - #[suggestion(message = "bar")] + #[suggestion(typeck::suggestion)] suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithBadKey { #[suggestion(nonsense = "bar")] //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute @@ -227,7 +236,7 @@ struct SuggestWithBadKey { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithShorthandMsg { #[suggestion(msg = "bar")] //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute @@ -235,91 +244,91 @@ struct SuggestWithShorthandMsg { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithoutMsg { #[suggestion(code = "bar")] suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithTypesSwapped { - #[suggestion(message = "bar", code = "This is suggested code")] + #[suggestion(typeck::suggestion, code = "This is suggested code")] suggestion: (Applicability, Span), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithWrongTypeApplicabilityOnly { - #[suggestion(message = "bar", code = "This is suggested code")] + #[suggestion(typeck::suggestion, code = "This is suggested code")] //~^ ERROR wrong field type for suggestion suggestion: Applicability, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithSpanOnly { - #[suggestion(message = "bar", code = "This is suggested code")] + #[suggestion(typeck::suggestion, code = "This is suggested code")] suggestion: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithDuplicateSpanAndApplicability { - #[suggestion(message = "bar", code = "This is suggested code")] + #[suggestion(typeck::suggestion, code = "This is suggested code")] //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span` suggestion: (Span, Span, Applicability), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct SuggestWithDuplicateApplicabilityAndSpan { - #[suggestion(message = "bar", code = "This is suggested code")] + #[suggestion(typeck::suggestion, code = "This is suggested code")] //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one suggestion: (Applicability, Applicability, Span), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct WrongKindOfAnnotation { - #[label("bar")] - //~^ ERROR `#[label(...)]` is not a valid attribute + #[label = "bar"] + //~^ ERROR `#[label = ...]` is not a valid attribute z: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct OptionsInErrors { - #[label = "bar"] + #[label(typeck::label)] label: Option, - #[suggestion(message = "bar")] + #[suggestion(typeck::suggestion)] opt_sugg: Option<(Span, Applicability)>, } #[derive(SessionDiagnostic)] -#[error(code = "E0456", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0456")] struct MoveOutOfBorrowError<'tcx> { name: Ident, ty: Ty<'tcx>, #[primary_span] - #[label = "bar"] + #[label(typeck::label)] span: Span, - #[label = "qux"] + #[label(typeck::label)] other_span: Span, - #[suggestion(message = "bar", code = "{name}.clone()")] + #[suggestion(typeck::suggestion, code = "{name}.clone()")] opt_sugg: Option<(Span, Applicability)>, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithLifetime<'a> { - #[label = "bar"] + #[label(typeck::label)] span: Span, name: &'a str, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithDefaultLabelAttr<'a> { #[label] span: Span, @@ -328,7 +337,7 @@ struct ErrorWithDefaultLabelAttr<'a> { #[derive(SessionDiagnostic)] //~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ArgFieldWithoutSkip { #[primary_span] span: Span, @@ -336,7 +345,7 @@ struct ArgFieldWithoutSkip { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ArgFieldWithSkip { #[primary_span] span: Span, @@ -347,132 +356,132 @@ struct ArgFieldWithSkip { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithSpannedNote { #[note] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithSpannedNoteCustom { - #[note = "bar"] + #[note(typeck::note)] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] #[note] struct ErrorWithNote { val: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] -#[note = "bar"] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[note(typeck::note)] struct ErrorWithNoteCustom { val: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithSpannedHelp { #[help] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithSpannedHelpCustom { - #[help = "bar"] + #[help(typeck::help)] span: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] #[help] struct ErrorWithHelp { val: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] -#[help = "bar"] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +#[help(typeck::help)] struct ErrorWithHelpCustom { val: String, } #[derive(SessionDiagnostic)] #[help] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithHelpWrongOrder { val: String, } #[derive(SessionDiagnostic)] -#[help = "bar"] -#[error(code = "E0123", slug = "foo")] +#[help(typeck::help)] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithHelpCustomWrongOrder { val: String, } #[derive(SessionDiagnostic)] #[note] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithNoteWrongOrder { val: String, } #[derive(SessionDiagnostic)] -#[note = "bar"] -#[error(code = "E0123", slug = "foo")] +#[note(typeck::note)] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ErrorWithNoteCustomWrongOrder { val: String, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ApplicabilityInBoth { - #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")] + #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] //~^ ERROR applicability cannot be set in both the field and attribute suggestion: (Span, Applicability), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct InvalidApplicability { - #[suggestion(message = "bar", code = "...", applicability = "batman")] + #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] //~^ ERROR invalid applicability suggestion: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct ValidApplicability { - #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")] + #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] suggestion: Span, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct NoApplicability { - #[suggestion(message = "bar", code = "...")] + #[suggestion(typeck::suggestion, code = "...")] suggestion: Span, } #[derive(SessionSubdiagnostic)] -#[note(slug = "note")] +#[note(parser::add_paren)] struct Note; #[derive(SessionDiagnostic)] -#[error(slug = "subdiagnostic")] +#[error(typeck::ambiguous_lifetime_bound)] struct Subdiagnostic { #[subdiagnostic] note: Note, } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct VecField { #[primary_span] #[label] @@ -480,23 +489,47 @@ struct VecField { } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct UnitField { #[primary_span] spans: Span, #[help] foo: (), - #[help = "a"] + #[help(typeck::help)] bar: (), } #[derive(SessionDiagnostic)] -#[error(code = "E0123", slug = "foo")] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] struct OptUnitField { #[primary_span] spans: Span, #[help] foo: Option<()>, - #[help = "a"] + #[help(typeck::help)] bar: Option<()>, } + +#[derive(SessionDiagnostic)] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct LabelWithTrailingPath { + #[label(typeck::label, foo)] + //~^ ERROR `#[label(...)]` is not a valid attribute + span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct LabelWithTrailingNameValue { + #[label(typeck::label, foo = "...")] + //~^ ERROR `#[label(...)]` is not a valid attribute + span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(typeck::ambiguous_lifetime_bound, code = "E0123")] +struct LabelWithTrailingList { + #[label(typeck::label, foo("..."))] + //~^ ERROR `#[label(...)]` is not a valid attribute + span: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 85ea44ec278c0..0d9690e1f5a99 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -1,7 +1,7 @@ error: `#[derive(SessionDiagnostic)]` can only be used on structs --> $DIR/diagnostic-derive.rs:37:1 | -LL | / #[error(code = "E0123", slug = "foo")] +LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | LL | | enum SessionDiagnosticOnEnum { LL | | Foo, @@ -18,15 +18,15 @@ LL | #[error = "E0123"] error: `#[nonsense(...)]` is not a valid attribute --> $DIR/diagnostic-derive.rs:51:1 | -LL | #[nonsense(code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: only `error` and `warning` are valid attributes + = help: only `error`, `warning`, `help` and `note` are valid attributes error: diagnostic kind not specified --> $DIR/diagnostic-derive.rs:51:1 | -LL | / #[nonsense(code = "E0123", slug = "foo")] +LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | | LL | | LL | | @@ -40,8 +40,10 @@ error: `#[error("...")]` is not a valid attribute | LL | #[error("E0123")] | ^^^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug -error: `slug` not specified +error: diagnostic slug not specified --> $DIR/diagnostic-derive.rs:58:1 | LL | / #[error("E0123")] @@ -50,183 +52,215 @@ LL | | LL | | struct InvalidLitNestedAttr {} | |______________________________^ | - = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug - -error: `#[error(nonsense)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:64:9 - | -LL | #[error(nonsense, code = "E0123", slug = "foo")] - | ^^^^^^^^ + = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: `#[error(nonsense(...))]` is not a valid attribute --> $DIR/diagnostic-derive.rs:69:9 | LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug + +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:69:1 + | +LL | / #[error(nonsense("foo"), code = "E0123", slug = "foo")] +LL | | +LL | | +LL | | struct InvalidNestedStructAttr1 {} + | |__________________________________^ + | + = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: `#[error(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:74:9 + --> $DIR/diagnostic-derive.rs:75:9 | LL | #[error(nonsense = "...", code = "E0123", slug = "foo")] | ^^^^^^^^^^^^^^^^ | - = help: only `slug` and `code` are valid nested attributes + = help: first argument of the attribute should be the diagnostic slug + +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:75:1 + | +LL | / #[error(nonsense = "...", code = "E0123", slug = "foo")] +LL | | +LL | | +LL | | struct InvalidNestedStructAttr2 {} + | |__________________________________^ + | + = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: `#[error(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:79:9 + --> $DIR/diagnostic-derive.rs:81:9 | LL | #[error(nonsense = 4, code = "E0123", slug = "foo")] | ^^^^^^^^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug -error: `#[suggestion = ...]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:86:5 +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:81:1 | -LL | #[suggestion = "bar"] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | / #[error(nonsense = 4, code = "E0123", slug = "foo")] +LL | | +LL | | +LL | | struct InvalidNestedStructAttr3 {} + | |__________________________________^ | - = help: only `label`, `note` and `help` are valid field attributes + = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` -error: specified multiple times - --> $DIR/diagnostic-derive.rs:93:1 +error: `#[error(slug = ...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:87:59 | -LL | #[error(code = "E0456", slug = "bar")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")] + | ^^^^^^^^^^^^ | -note: previously specified here - --> $DIR/diagnostic-derive.rs:92:1 + = help: only `code` is a valid nested attributes following the slug + +error: `#[suggestion = ...]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:94:5 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[suggestion = "bar"] + | ^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:93:16 + --> $DIR/diagnostic-derive.rs:101:1 | -LL | #[error(code = "E0456", slug = "bar")] - | ^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:92:16 + --> $DIR/diagnostic-derive.rs:100:1 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:93:32 + --> $DIR/diagnostic-derive.rs:101:1 | -LL | #[error(code = "E0456", slug = "bar")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:92:32 + --> $DIR/diagnostic-derive.rs:100:1 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:1 + --> $DIR/diagnostic-derive.rs:101:50 | -LL | #[warning(code = "E0293", slug = "bar")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")] + | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:1 + --> $DIR/diagnostic-derive.rs:100:50 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:18 + --> $DIR/diagnostic-derive.rs:109:1 | -LL | #[warning(code = "E0293", slug = "bar")] - | ^^^^^^^ +LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:16 + --> $DIR/diagnostic-derive.rs:108:1 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:101:34 + --> $DIR/diagnostic-derive.rs:109:1 | -LL | #[warning(code = "E0293", slug = "bar")] - | ^^^^^ +LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:100:32 + --> $DIR/diagnostic-derive.rs:108:1 | -LL | #[error(code = "E0123", slug = "foo")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:108:32 + --> $DIR/diagnostic-derive.rs:109:52 | -LL | #[error(code = "E0456", code = "E0457", slug = "bar")] - | ^^^^^^^ +LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] + | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:108:16 + --> $DIR/diagnostic-derive.rs:108:50 | -LL | #[error(code = "E0456", code = "E0457", slug = "bar")] - | ^^^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] + | ^^^^^^^ error: specified multiple times - --> $DIR/diagnostic-derive.rs:113:46 + --> $DIR/diagnostic-derive.rs:116:66 | -LL | #[error(code = "E0456", slug = "foo", slug = "bar")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] + | ^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive.rs:113:32 + --> $DIR/diagnostic-derive.rs:116:50 | -LL | #[error(code = "E0456", slug = "foo", slug = "bar")] - | ^^^^^ +LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] + | ^^^^^^^ + +error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:121:43 + | +LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostic kind not specified - --> $DIR/diagnostic-derive.rs:118:1 + --> $DIR/diagnostic-derive.rs:126:1 | LL | struct KindNotProvided {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use the `#[error(...)]` attribute to create an error -error: `slug` not specified - --> $DIR/diagnostic-derive.rs:121:1 +error: diagnostic slug not specified + --> $DIR/diagnostic-derive.rs:129:1 | LL | / #[error(code = "E0456")] +LL | | LL | | struct SlugNotProvided {} | |_________________________^ | - = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug + = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` - --> $DIR/diagnostic-derive.rs:131:5 + --> $DIR/diagnostic-derive.rs:140:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:139:5 + --> $DIR/diagnostic-derive.rs:148:5 | LL | #[nonsense] | ^^^^^^^^^^^ | = help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes -error: the `#[label = ...]` attribute can only be applied to fields of type `Span` - --> $DIR/diagnostic-derive.rs:156:5 +error: the `#[label(...)]` attribute can only be applied to fields of type `Span` + --> $DIR/diagnostic-derive.rs:165:5 | -LL | #[label = "bar"] - | ^^^^^^^^^^^^^^^^ +LL | #[label(typeck::label)] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive.rs:164:42 + --> $DIR/diagnostic-derive.rs:173:45 | -LL | #[suggestion(message = "bar", code = "{name}")] - | ^^^^^^^^ +LL | #[suggestion(typeck::suggestion, code = "{name}")] + | ^^^^^^^^ error: invalid format string: expected `'}'` but string was terminated - --> $DIR/diagnostic-derive.rs:169:16 + --> $DIR/diagnostic-derive.rs:178:16 | LL | #[derive(SessionDiagnostic)] | - ^ expected `'}'` in format string @@ -237,7 +271,7 @@ LL | #[derive(SessionDiagnostic)] = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive.rs:179:15 + --> $DIR/diagnostic-derive.rs:188:15 | LL | #[derive(SessionDiagnostic)] | ^ unmatched `}` in format string @@ -245,14 +279,14 @@ LL | #[derive(SessionDiagnostic)] = note: if you intended to print `}`, you can escape it using `}}` = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: the `#[label = ...]` attribute can only be applied to fields of type `Span` - --> $DIR/diagnostic-derive.rs:199:5 +error: the `#[label(...)]` attribute can only be applied to fields of type `Span` + --> $DIR/diagnostic-derive.rs:208:5 | -LL | #[label = "bar"] - | ^^^^^^^^^^^^^^^^ +LL | #[label(typeck::label)] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: `#[suggestion(nonsense = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:224:18 + --> $DIR/diagnostic-derive.rs:233:18 | LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^ @@ -260,7 +294,7 @@ LL | #[suggestion(nonsense = "bar")] = help: only `message`, `code` and `applicability` are valid field attributes error: `#[suggestion(msg = ...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:232:18 + --> $DIR/diagnostic-derive.rs:241:18 | LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^ @@ -268,9 +302,9 @@ LL | #[suggestion(msg = "bar")] = help: only `message`, `code` and `applicability` are valid field attributes error: wrong field type for suggestion - --> $DIR/diagnostic-derive.rs:254:5 + --> $DIR/diagnostic-derive.rs:263:5 | -LL | / #[suggestion(message = "bar", code = "This is suggested code")] +LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | LL | | suggestion: Applicability, | |_____________________________^ @@ -278,55 +312,77 @@ LL | | suggestion: Applicability, = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: type of field annotated with `#[suggestion(...)]` contains more than one `Span` - --> $DIR/diagnostic-derive.rs:269:5 + --> $DIR/diagnostic-derive.rs:278:5 | -LL | / #[suggestion(message = "bar", code = "This is suggested code")] +LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | LL | | suggestion: (Span, Span, Applicability), | |___________________________________________^ error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability - --> $DIR/diagnostic-derive.rs:277:5 + --> $DIR/diagnostic-derive.rs:286:5 | -LL | / #[suggestion(message = "bar", code = "This is suggested code")] +LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | | LL | | suggestion: (Applicability, Applicability, Span), | |____________________________________________________^ -error: `#[label(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:285:5 - | -LL | #[label("bar")] - | ^^^^^^^^^^^^^^^ +error: `#[label = ...]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:294:5 | - = help: only `suggestion{,_short,_hidden,_verbose}` are valid field attributes +LL | #[label = "bar"] + | ^^^^^^^^^^^^^^^^ error: applicability cannot be set in both the field and attribute - --> $DIR/diagnostic-derive.rs:436:49 + --> $DIR/diagnostic-derive.rs:445:52 | -LL | #[suggestion(message = "bar", code = "...", applicability = "maybe-incorrect")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid applicability - --> $DIR/diagnostic-derive.rs:444:49 + --> $DIR/diagnostic-derive.rs:453:52 + | +LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[label(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:516:5 + | +LL | #[label(typeck::label, foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[label(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:524:5 + | +LL | #[label(typeck::label, foo = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[label(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:532:5 | -LL | #[suggestion(message = "bar", code = "...", applicability = "batman")] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label(typeck::label, foo("..."))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot find attribute `nonsense` in this scope --> $DIR/diagnostic-derive.rs:51:3 | -LL | #[nonsense(code = "E0123", slug = "foo")] +LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive.rs:139:7 + --> $DIR/diagnostic-derive.rs:148:7 | LL | #[nonsense] | ^^^^^^^^ +error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent` + --> $DIR/diagnostic-derive.rs:64:9 + | +LL | #[error(nonsense, code = "E0123")] + | ^^^^^^^^ not found in `rustc_errors::fluent` + error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied - --> $DIR/diagnostic-derive.rs:329:10 + --> $DIR/diagnostic-derive.rs:338:10 | LL | #[derive(SessionDiagnostic)] | ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` @@ -345,6 +401,7 @@ LL | arg: impl IntoDiagnosticArg, | ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 39 previous errors +error: aborting due to 46 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index bb406c35c0eef..6f4b6105b3e49 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -20,7 +20,7 @@ use rustc_span::Span; use rustc_macros::SessionSubdiagnostic; #[derive(SessionSubdiagnostic)] -#[label(slug = "label-a")] +#[label(parser::add_paren)] struct A { #[primary_span] span: Span, @@ -29,13 +29,13 @@ struct A { #[derive(SessionSubdiagnostic)] enum B { - #[label(slug = "label-b-a")] + #[label(parser::add_paren)] A { #[primary_span] span: Span, var: String, }, - #[label(slug = "label-b-b")] + #[label(parser::add_paren)] B { #[primary_span] span: Span, @@ -44,7 +44,7 @@ enum B { } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-c")] +#[label(parser::add_paren)] //~^ ERROR label without `#[primary_span]` field struct C { var: String, @@ -116,7 +116,8 @@ struct K { #[derive(SessionSubdiagnostic)] #[label(slug)] -//~^ ERROR `#[label(slug)]` is not a valid attribute +//~^ ERROR cannot find value `slug` in module `rustc_errors::fluent` +//~^^ NOTE not found in `rustc_errors::fluent` struct L { #[primary_span] span: Span, @@ -125,7 +126,7 @@ struct L { #[derive(SessionSubdiagnostic)] #[label()] -//~^ ERROR `slug` must be set in a `#[label(...)]` attribute +//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute struct M { #[primary_span] span: Span, @@ -133,7 +134,7 @@ struct M { } #[derive(SessionSubdiagnostic)] -#[label(code = "...")] +#[label(parser::add_paren, code = "...")] //~^ ERROR `code` is not a valid nested attribute of a `label` attribute struct N { #[primary_span] @@ -141,12 +142,21 @@ struct N { var: String, } +#[derive(SessionSubdiagnostic)] +#[label(parser::add_paren, applicability = "machine-applicable")] +//~^ ERROR `applicability` is not a valid nested attribute of a `label` attribute +struct O { + #[primary_span] + span: Span, + var: String, +} + #[derive(SessionSubdiagnostic)] #[foo] //~^ ERROR cannot find attribute `foo` in this scope //~^^ ERROR unsupported type attribute for subdiagnostic enum -enum O { - #[label(slug = "...")] +enum P { + #[label(parser::add_paren)] A { #[primary_span] span: Span, @@ -155,7 +165,7 @@ enum O { } #[derive(SessionSubdiagnostic)] -enum P { +enum Q { #[bar] //~^ ERROR `#[bar]` is not a valid attribute //~^^ ERROR cannot find attribute `bar` in this scope @@ -167,7 +177,7 @@ enum P { } #[derive(SessionSubdiagnostic)] -enum Q { +enum R { #[bar = "..."] //~^ ERROR `#[bar = ...]` is not a valid attribute //~^^ ERROR cannot find attribute `bar` in this scope @@ -179,7 +189,7 @@ enum Q { } #[derive(SessionSubdiagnostic)] -enum R { +enum S { #[bar = 4] //~^ ERROR `#[bar = ...]` is not a valid attribute //~^^ ERROR cannot find attribute `bar` in this scope @@ -191,7 +201,7 @@ enum R { } #[derive(SessionSubdiagnostic)] -enum S { +enum T { #[bar("...")] //~^ ERROR `#[bar("...")]` is not a valid attribute //~^^ ERROR cannot find attribute `bar` in this scope @@ -203,9 +213,9 @@ enum S { } #[derive(SessionSubdiagnostic)] -enum T { +enum U { #[label(code = "...")] -//~^ ERROR `code` is not a valid nested attribute of a `label` +//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute A { #[primary_span] span: Span, @@ -214,8 +224,8 @@ enum T { } #[derive(SessionSubdiagnostic)] -enum U { - #[label(slug = "label-u")] +enum V { + #[label(parser::add_paren)] A { #[primary_span] span: Span, @@ -230,17 +240,17 @@ enum U { } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] +#[label(parser::add_paren)] //~^ ERROR label without `#[primary_span]` field -struct V { +struct W { #[primary_span] //~^ ERROR the `#[primary_span]` attribute can only be applied to fields of type `Span` span: String, } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] -struct W { +#[label(parser::add_paren)] +struct X { #[primary_span] span: Span, #[applicability] @@ -249,8 +259,8 @@ struct W { } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] -struct X { +#[label(parser::add_paren)] +struct Y { #[primary_span] span: Span, #[bar] @@ -260,8 +270,8 @@ struct X { } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] -struct Y { +#[label(parser::add_paren)] +struct Z { #[primary_span] span: Span, #[bar = "..."] @@ -271,8 +281,8 @@ struct Y { } #[derive(SessionSubdiagnostic)] -#[label(slug = "...")] -struct Z { +#[label(parser::add_paren)] +struct AA { #[primary_span] span: Span, #[bar("...")] @@ -282,8 +292,8 @@ struct Z { } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-aa")] -struct AA { +#[label(parser::add_paren)] +struct AB { #[primary_span] span: Span, #[skip_arg] @@ -291,36 +301,35 @@ struct AA { } #[derive(SessionSubdiagnostic)] -union AB { +union AC { //~^ ERROR unexpected unsupported untagged union span: u32, b: u64 } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-ac-1")] +#[label(parser::add_paren)] //~^ NOTE previously specified here //~^^ NOTE previously specified here -#[label(slug = "label-ac-2")] +#[label(parser::add_paren)] //~^ ERROR specified multiple times //~^^ ERROR specified multiple times -struct AC { +struct AD { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-ad-1", slug = "label-ad-2")] -//~^ ERROR specified multiple times -//~^^ NOTE previously specified here -struct AD { +#[label(parser::add_paren, parser::add_paren)] +//~^ ERROR `#[label(parser::add_paren)]` is not a valid attribute +struct AE { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[label(slug = "label-ad-1")] -struct AE { +#[label(parser::add_paren)] +struct AF { #[primary_span] //~^ NOTE previously specified here span_a: Span, @@ -330,15 +339,15 @@ struct AE { } #[derive(SessionSubdiagnostic)] -struct AF { +struct AG { //~^ ERROR subdiagnostic kind not specified #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "suggestion-af", code = "...")] -struct AG { +#[suggestion(parser::add_paren, code = "...")] +struct AH { #[primary_span] span: Span, #[applicability] @@ -347,8 +356,8 @@ struct AG { } #[derive(SessionSubdiagnostic)] -enum AH { - #[suggestion(slug = "suggestion-ag-a", code = "...")] +enum AI { + #[suggestion(parser::add_paren, code = "...")] A { #[primary_span] span: Span, @@ -356,7 +365,7 @@ enum AH { applicability: Applicability, var: String, }, - #[suggestion(slug = "suggestion-ag-b", code = "...")] + #[suggestion(parser::add_paren, code = "...")] B { #[primary_span] span: Span, @@ -367,10 +376,10 @@ enum AH { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...", code = "...")] +#[suggestion(parser::add_paren, code = "...", code = "...")] //~^ ERROR specified multiple times //~^^ NOTE previously specified here -struct AI { +struct AJ { #[primary_span] span: Span, #[applicability] @@ -378,8 +387,8 @@ struct AI { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...")] -struct AJ { +#[suggestion(parser::add_paren, code = "...")] +struct AK { #[primary_span] span: Span, #[applicability] @@ -391,9 +400,9 @@ struct AJ { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...")] +#[suggestion(parser::add_paren, code = "...")] //~^ ERROR suggestion without `applicability` -struct AK { +struct AL { #[primary_span] span: Span, #[applicability] @@ -402,17 +411,17 @@ struct AK { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...")] +#[suggestion(parser::add_paren, code = "...")] //~^ ERROR suggestion without `applicability` -struct AL { +struct AM { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...")] +#[suggestion(parser::add_paren)] //~^ ERROR suggestion without `code = "..."` -struct AM { +struct AN { #[primary_span] span: Span, #[applicability] @@ -420,34 +429,34 @@ struct AM { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code ="...", applicability = "foo")] +#[suggestion(parser::add_paren, code ="...", applicability = "foo")] //~^ ERROR invalid applicability -struct AN { +struct AO { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -#[help(slug = "label-am")] -struct AO { +#[help(parser::add_paren)] +struct AP { var: String } #[derive(SessionSubdiagnostic)] -#[note(slug = "label-an")] -struct AP; +#[note(parser::add_paren)] +struct AQ; #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code = "...")] +#[suggestion(parser::add_paren, code = "...")] //~^ ERROR suggestion without `applicability` //~^^ ERROR suggestion without `#[primary_span]` field -struct AQ { +struct AR { var: String, } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code ="...", applicability = "machine-applicable")] -struct AR { +#[suggestion(parser::add_paren, code ="...", applicability = "machine-applicable")] +struct AS { #[primary_span] span: Span, } @@ -455,8 +464,8 @@ struct AR { #[derive(SessionSubdiagnostic)] #[label] //~^ ERROR unsupported type attribute for subdiagnostic enum -enum AS { - #[label(slug = "...")] +enum AT { + #[label(parser::add_paren)] A { #[primary_span] span: Span, @@ -465,24 +474,24 @@ enum AS { } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] -struct AT { +#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] +struct AU { #[primary_span] span: Span, var: String, } #[derive(SessionSubdiagnostic)] -#[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] +#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] //~^ ERROR `var` doesn't refer to a field on this type -struct AU { +struct AV { #[primary_span] span: Span, } #[derive(SessionSubdiagnostic)] -enum AV { - #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] +enum AW { + #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] A { #[primary_span] span: Span, @@ -491,8 +500,8 @@ enum AV { } #[derive(SessionSubdiagnostic)] -enum AW { - #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] +enum AX { + #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] //~^ ERROR `var` doesn't refer to a field on this type A { #[primary_span] diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index 4984cc4b3186c..f833bd210f7f5 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -1,7 +1,7 @@ error: label without `#[primary_span]` field --> $DIR/subdiagnostic-derive.rs:47:1 | -LL | / #[label(slug = "label-c")] +LL | / #[label(parser::add_paren)] LL | | LL | | struct C { LL | | var: String, @@ -32,98 +32,106 @@ error: `#[label(bug = ...)]` is not a valid attribute LL | #[label(bug = "...")] | ^^^^^^^^^^^ | - = help: only `code`, `slug` and `applicability` are valid nested attributes + = help: first argument of the attribute should be the diagnostic slug error: `#[label("...")]` is not a valid attribute --> $DIR/subdiagnostic-derive.rs:91:9 | LL | #[label("...")] | ^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug error: `#[label(slug = ...)]` is not a valid attribute --> $DIR/subdiagnostic-derive.rs:100:9 | LL | #[label(slug = 4)] | ^^^^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug error: `#[label(slug(...))]` is not a valid attribute --> $DIR/subdiagnostic-derive.rs:109:9 | LL | #[label(slug("..."))] | ^^^^^^^^^^^ - -error: `#[label(slug)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:118:9 | -LL | #[label(slug)] - | ^^^^ + = help: first argument of the attribute should be the diagnostic slug -error: `slug` must be set in a `#[label(...)]` attribute - --> $DIR/subdiagnostic-derive.rs:127:1 +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:128:1 | LL | #[label()] | ^^^^^^^^^^ error: `code` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:136:1 + --> $DIR/subdiagnostic-derive.rs:137:1 + | +LL | #[label(parser::add_paren, code = "...")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `applicability` is not a valid nested attribute of a `label` attribute + --> $DIR/subdiagnostic-derive.rs:146:1 | -LL | #[label(code = "...")] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren, applicability = "machine-applicable")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:145:1 + --> $DIR/subdiagnostic-derive.rs:155:1 | LL | #[foo] | ^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:159:5 + --> $DIR/subdiagnostic-derive.rs:169:5 | LL | #[bar] | ^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:171:5 + --> $DIR/subdiagnostic-derive.rs:181:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar = ...]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:183:5 + --> $DIR/subdiagnostic-derive.rs:193:5 | LL | #[bar = 4] | ^^^^^^^^^^ error: `#[bar("...")]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:195:11 + --> $DIR/subdiagnostic-derive.rs:205:11 | LL | #[bar("...")] | ^^^^^ + | + = help: first argument of the attribute should be the diagnostic slug -error: `code` is not a valid nested attribute of a `label` attribute - --> $DIR/subdiagnostic-derive.rs:207:5 +error: diagnostic slug must be first argument of a `#[label(...)]` attribute + --> $DIR/subdiagnostic-derive.rs:217:5 | LL | #[label(code = "...")] | ^^^^^^^^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:224:5 + --> $DIR/subdiagnostic-derive.rs:234:5 | LL | B { | ^ error: the `#[primary_span]` attribute can only be applied to fields of type `Span` - --> $DIR/subdiagnostic-derive.rs:236:5 + --> $DIR/subdiagnostic-derive.rs:246:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: label without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:233:1 + --> $DIR/subdiagnostic-derive.rs:243:1 | -LL | / #[label(slug = "...")] +LL | / #[label(parser::add_paren)] LL | | -LL | | struct V { +LL | | struct W { LL | | #[primary_span] LL | | LL | | span: String, @@ -131,13 +139,13 @@ LL | | } | |_^ error: `#[applicability]` is only valid on suggestions - --> $DIR/subdiagnostic-derive.rs:246:5 + --> $DIR/subdiagnostic-derive.rs:256:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: `#[bar]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:256:5 + --> $DIR/subdiagnostic-derive.rs:266:5 | LL | #[bar] | ^^^^^^ @@ -145,21 +153,21 @@ 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:267:5 + --> $DIR/subdiagnostic-derive.rs:277:5 | LL | #[bar = "..."] | ^^^^^^^^^^^^^^ error: `#[bar(...)]` is not a valid attribute - --> $DIR/subdiagnostic-derive.rs:278:5 + --> $DIR/subdiagnostic-derive.rs:288:5 | LL | #[bar("...")] | ^^^^^^^^^^^^^ error: unexpected unsupported untagged union - --> $DIR/subdiagnostic-derive.rs:294:1 + --> $DIR/subdiagnostic-derive.rs:304:1 | -LL | / union AB { +LL | / union AC { LL | | LL | | span: u32, LL | | b: u64 @@ -167,95 +175,91 @@ LL | | } | |_^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:304:9 + --> $DIR/subdiagnostic-derive.rs:314:1 | -LL | #[label(slug = "label-ac-2")] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:301:9 + --> $DIR/subdiagnostic-derive.rs:311:1 | -LL | #[label(slug = "label-ac-1")] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:304:1 + --> $DIR/subdiagnostic-derive.rs:314:1 | -LL | #[label(slug = "label-ac-2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:301:1 + --> $DIR/subdiagnostic-derive.rs:311:1 | -LL | #[label(slug = "label-ac-1")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:313:30 +error: `#[label(parser::add_paren)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:323:28 | -LL | #[label(slug = "label-ad-1", slug = "label-ad-2")] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[label(parser::add_paren, parser::add_paren)] + | ^^^^^^^^^^^^^^^^^ | -note: previously specified here - --> $DIR/subdiagnostic-derive.rs:313:9 - | -LL | #[label(slug = "label-ad-1", slug = "label-ad-2")] - | ^^^^^^^^^^^^^^^^^^^ + = help: a diagnostic slug must be the first argument to the attribute error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:327:5 + --> $DIR/subdiagnostic-derive.rs:336:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:324:5 + --> $DIR/subdiagnostic-derive.rs:333:5 | LL | #[primary_span] | ^^^^^^^^^^^^^^^ error: subdiagnostic kind not specified - --> $DIR/subdiagnostic-derive.rs:333:8 + --> $DIR/subdiagnostic-derive.rs:342:8 | -LL | struct AF { +LL | struct AG { | ^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:370:42 + --> $DIR/subdiagnostic-derive.rs:379:47 | -LL | #[suggestion(slug = "...", code = "...", code = "...")] - | ^^^^^^^^^^^^ +LL | #[suggestion(parser::add_paren, code = "...", code = "...")] + | ^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:370:28 + --> $DIR/subdiagnostic-derive.rs:379:33 | -LL | #[suggestion(slug = "...", code = "...", code = "...")] - | ^^^^^^^^^^^^ +LL | #[suggestion(parser::add_paren, code = "...", code = "...")] + | ^^^^^^^^^^^^ error: specified multiple times - --> $DIR/subdiagnostic-derive.rs:388:5 + --> $DIR/subdiagnostic-derive.rs:397:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/subdiagnostic-derive.rs:385:5 + --> $DIR/subdiagnostic-derive.rs:394:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: the `#[applicability]` attribute can only be applied to fields of type `Applicability` - --> $DIR/subdiagnostic-derive.rs:399:5 + --> $DIR/subdiagnostic-derive.rs:408:5 | LL | #[applicability] | ^^^^^^^^^^^^^^^^ error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:394:1 + --> $DIR/subdiagnostic-derive.rs:403:1 | -LL | / #[suggestion(slug = "...", code = "...")] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | -LL | | struct AK { +LL | | struct AL { LL | | #[primary_span] ... | LL | | applicability: Span, @@ -263,22 +267,22 @@ LL | | } | |_^ error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:405:1 + --> $DIR/subdiagnostic-derive.rs:414:1 | -LL | / #[suggestion(slug = "...", code = "...")] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | -LL | | struct AL { +LL | | struct AM { LL | | #[primary_span] LL | | span: Span, LL | | } | |_^ error: suggestion without `code = "..."` - --> $DIR/subdiagnostic-derive.rs:413:1 + --> $DIR/subdiagnostic-derive.rs:422:1 | -LL | / #[suggestion(slug = "...")] +LL | / #[suggestion(parser::add_paren)] LL | | -LL | | struct AM { +LL | | struct AN { LL | | #[primary_span] ... | LL | | applicability: Applicability, @@ -286,50 +290,50 @@ LL | | } | |_^ error: invalid applicability - --> $DIR/subdiagnostic-derive.rs:423:41 + --> $DIR/subdiagnostic-derive.rs:432:46 | -LL | #[suggestion(slug = "...", code ="...", applicability = "foo")] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")] + | ^^^^^^^^^^^^^^^^^^^^^ error: suggestion without `applicability` - --> $DIR/subdiagnostic-derive.rs:441:1 + --> $DIR/subdiagnostic-derive.rs:450:1 | -LL | / #[suggestion(slug = "...", code = "...")] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | LL | | -LL | | struct AQ { +LL | | struct AR { LL | | var: String, LL | | } | |_^ error: suggestion without `#[primary_span]` field - --> $DIR/subdiagnostic-derive.rs:441:1 + --> $DIR/subdiagnostic-derive.rs:450:1 | -LL | / #[suggestion(slug = "...", code = "...")] +LL | / #[suggestion(parser::add_paren, code = "...")] LL | | LL | | -LL | | struct AQ { +LL | | struct AR { LL | | var: String, LL | | } | |_^ error: unsupported type attribute for subdiagnostic enum - --> $DIR/subdiagnostic-derive.rs:456:1 + --> $DIR/subdiagnostic-derive.rs:465:1 | LL | #[label] | ^^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:476:34 + --> $DIR/subdiagnostic-derive.rs:485:39 | -LL | #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] - | ^^^^^^^ +LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] + | ^^^^^^^ error: `var` doesn't refer to a field on this type - --> $DIR/subdiagnostic-derive.rs:495:38 + --> $DIR/subdiagnostic-derive.rs:504:43 | -LL | #[suggestion(slug = "...", code ="{var}", applicability = "machine-applicable")] - | ^^^^^^^ +LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")] + | ^^^^^^^ error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:63:3 @@ -338,52 +342,59 @@ LL | #[foo] | ^^^ error: cannot find attribute `foo` in this scope - --> $DIR/subdiagnostic-derive.rs:145:3 + --> $DIR/subdiagnostic-derive.rs:155:3 | LL | #[foo] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:159:7 + --> $DIR/subdiagnostic-derive.rs:169:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:171:7 + --> $DIR/subdiagnostic-derive.rs:181:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:183:7 + --> $DIR/subdiagnostic-derive.rs:193:7 | LL | #[bar = 4] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:195:7 + --> $DIR/subdiagnostic-derive.rs:205:7 | LL | #[bar("...")] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:256:7 + --> $DIR/subdiagnostic-derive.rs:266:7 | LL | #[bar] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:267:7 + --> $DIR/subdiagnostic-derive.rs:277:7 | LL | #[bar = "..."] | ^^^ error: cannot find attribute `bar` in this scope - --> $DIR/subdiagnostic-derive.rs:278:7 + --> $DIR/subdiagnostic-derive.rs:288:7 | LL | #[bar("...")] | ^^^ -error: aborting due to 51 previous errors +error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` + --> $DIR/subdiagnostic-derive.rs:118:9 + | +LL | #[label(slug)] + | ^^^^ not found in `rustc_errors::fluent` + +error: aborting due to 52 previous errors +For more information about this error, try `rustc --explain E0425`.