Make derived SessionDiagnostics generic on diagnostic level

Deriving SessionDiagnostic on a type no longer forces that diagnostic to
be one of warning, error, or fatal. The level is instead decided when
the struct is passed to the respective Handler::emit_*() method.
This commit is contained in:
Xiretza 2022-08-19 15:02:10 +02:00
parent 91ad4e38f5
commit a960f8304c
5 changed files with 108 additions and 185 deletions

View File

@ -21,7 +21,7 @@ impl<'a> SessionDiagnosticDerive<'a> {
builder: DiagnosticDeriveBuilder { builder: DiagnosticDeriveBuilder {
diag, diag,
fields: build_field_mapping(&structure), fields: build_field_mapping(&structure),
kind: None, kind: DiagnosticDeriveKind::SessionDiagnostic,
code: None, code: None,
slug: None, slug: None,
}, },
@ -34,49 +34,31 @@ impl<'a> SessionDiagnosticDerive<'a> {
let SessionDiagnosticDerive { mut structure, sess, mut builder } = self; let SessionDiagnosticDerive { mut structure, sess, mut builder } = self;
let ast = structure.ast(); let ast = structure.ast();
let (implementation, param_ty) = { let implementation = {
if let syn::Data::Struct(..) = ast.data { if let syn::Data::Struct(..) = ast.data {
let preamble = builder.preamble(&structure); let preamble = builder.preamble(&structure);
let (attrs, args) = builder.body(&mut structure); let (attrs, args) = builder.body(&mut structure);
let span = ast.span().unwrap(); let span = ast.span().unwrap();
let diag = &builder.diag; let diag = &builder.diag;
let init = match (builder.kind.value(), builder.slug.value()) { let init = match builder.slug.value() {
(None, _) => { None => {
span_err(span, "diagnostic kind not specified")
.help("use the `#[error(...)]` attribute to create an error")
.emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
}
(Some(kind), None) => {
span_err(span, "diagnostic slug not specified") span_err(span, "diagnostic slug not specified")
.help(&format!( .help(&format!(
"specify the slug as the first argument to the attribute, such as \ "specify the slug as the first argument to the `#[diag(...)]` attribute, \
`#[{}(typeck::example_error)]`", such as `#[diag(typeck::example_error)]`",
kind.descr()
)) ))
.emit(); .emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error(); return DiagnosticDeriveError::ErrorHandled.to_compile_error();
} }
(Some(DiagnosticDeriveKind::Lint), _) => { Some(slug) => {
span_err(span, "only `#[error(..)]` and `#[warning(..)]` are supported")
.help("use the `#[error(...)]` attribute to create a error")
.emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
}
(Some(DiagnosticDeriveKind::Error), Some(slug)) => {
quote! { quote! {
let mut #diag = #sess.struct_err(rustc_errors::fluent::#slug); let mut #diag = #sess.struct_diagnostic(rustc_errors::fluent::#slug);
}
}
(Some(DiagnosticDeriveKind::Warn), Some(slug)) => {
quote! {
let mut #diag = #sess.struct_warn(rustc_errors::fluent::#slug);
} }
} }
}; };
let implementation = quote! { quote! {
#init #init
#preamble #preamble
match self { match self {
@ -86,18 +68,7 @@ impl<'a> SessionDiagnosticDerive<'a> {
#args #args
} }
#diag #diag
}; }
let param_ty = match builder.kind {
Some((DiagnosticDeriveKind::Error, _)) => {
quote! { rustc_errors::ErrorGuaranteed }
}
Some((DiagnosticDeriveKind::Lint | DiagnosticDeriveKind::Warn, _)) => {
quote! { () }
}
_ => unreachable!(),
};
(implementation, param_ty)
} else { } else {
span_err( span_err(
ast.span().unwrap(), ast.span().unwrap(),
@ -105,20 +76,20 @@ impl<'a> SessionDiagnosticDerive<'a> {
) )
.emit(); .emit();
let implementation = DiagnosticDeriveError::ErrorHandled.to_compile_error(); DiagnosticDeriveError::ErrorHandled.to_compile_error()
let param_ty = quote! { rustc_errors::ErrorGuaranteed };
(implementation, param_ty)
} }
}; };
structure.gen_impl(quote! { structure.gen_impl(quote! {
gen impl<'__session_diagnostic_sess> rustc_session::SessionDiagnostic<'__session_diagnostic_sess, #param_ty> gen impl<'__session_diagnostic_sess, G>
rustc_session::SessionDiagnostic<'__session_diagnostic_sess, G>
for @Self for @Self
where G: rustc_errors::EmissionGuarantee
{ {
fn into_diagnostic( fn into_diagnostic(
self, self,
#sess: &'__session_diagnostic_sess rustc_session::parse::ParseSess #sess: &'__session_diagnostic_sess rustc_session::parse::ParseSess
) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, #param_ty> { ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, G> {
use rustc_errors::IntoDiagnosticArg; use rustc_errors::IntoDiagnosticArg;
#implementation #implementation
} }
@ -139,7 +110,7 @@ impl<'a> LintDiagnosticDerive<'a> {
builder: DiagnosticDeriveBuilder { builder: DiagnosticDeriveBuilder {
diag, diag,
fields: build_field_mapping(&structure), fields: build_field_mapping(&structure),
kind: None, kind: DiagnosticDeriveKind::LintDiagnostic,
code: None, code: None,
slug: None, slug: None,
}, },
@ -158,30 +129,17 @@ impl<'a> LintDiagnosticDerive<'a> {
let diag = &builder.diag; let diag = &builder.diag;
let span = ast.span().unwrap(); let span = ast.span().unwrap();
let init = match (builder.kind.value(), builder.slug.value()) { let init = match builder.slug.value() {
(None, _) => { None => {
span_err(span, "diagnostic kind not specified")
.help("use the `#[error(...)]` attribute to create an error")
.emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
}
(Some(kind), None) => {
span_err(span, "diagnostic slug not specified") span_err(span, "diagnostic slug not specified")
.help(&format!( .help(&format!(
"specify the slug as the first argument to the attribute, such as \ "specify the slug as the first argument to the attribute, such as \
`#[{}(typeck::example_error)]`", `#[diag(typeck::example_error)]`",
kind.descr()
)) ))
.emit(); .emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error(); return DiagnosticDeriveError::ErrorHandled.to_compile_error();
} }
(Some(DiagnosticDeriveKind::Error | DiagnosticDeriveKind::Warn), _) => { Some(slug) => {
span_err(span, "only `#[lint(..)]` is supported")
.help("use the `#[lint(...)]` attribute to create a lint")
.emit();
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
}
(Some(DiagnosticDeriveKind::Lint), Some(slug)) => {
quote! { quote! {
let mut #diag = #diag.build(rustc_errors::fluent::#slug); let mut #diag = #diag.build(rustc_errors::fluent::#slug);
} }

View File

@ -18,30 +18,15 @@ use syn::{
}; };
use synstructure::{BindingInfo, Structure}; use synstructure::{BindingInfo, Structure};
/// What kind of diagnostic is being derived - an error, a warning or a lint? /// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
#[derive(Copy, Clone)] #[derive(Copy, Clone, PartialEq, Eq)]
pub(crate) enum DiagnosticDeriveKind { pub(crate) enum DiagnosticDeriveKind {
/// `#[error(..)]` SessionDiagnostic,
Error, LintDiagnostic,
/// `#[warn(..)]`
Warn,
/// `#[lint(..)]`
Lint,
}
impl DiagnosticDeriveKind {
/// Returns human-readable string corresponding to the kind.
pub fn descr(&self) -> &'static str {
match self {
DiagnosticDeriveKind::Error => "error",
DiagnosticDeriveKind::Warn => "warning",
DiagnosticDeriveKind::Lint => "lint",
}
}
} }
/// Tracks persistent information required for building up individual calls to diagnostic methods /// Tracks persistent information required for building up individual calls to diagnostic methods
/// for generated diagnostic derives - both `SessionDiagnostic` for errors/warnings and /// for generated diagnostic derives - both `SessionDiagnostic` for fatal/errors/warnings and
/// `LintDiagnostic` for lints. /// `LintDiagnostic` for lints.
pub(crate) struct DiagnosticDeriveBuilder { pub(crate) struct DiagnosticDeriveBuilder {
/// The identifier to use for the generated `DiagnosticBuilder` instance. /// The identifier to use for the generated `DiagnosticBuilder` instance.
@ -51,8 +36,8 @@ pub(crate) struct DiagnosticDeriveBuilder {
/// derive builder. /// derive builder.
pub fields: HashMap<String, TokenStream>, pub fields: HashMap<String, TokenStream>,
/// Kind of diagnostic requested via the struct attribute. /// Kind of diagnostic that should be derived.
pub kind: Option<(DiagnosticDeriveKind, proc_macro::Span)>, pub kind: DiagnosticDeriveKind,
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
/// has the actual diagnostic message. /// has the actual diagnostic message.
pub slug: Option<(Path, proc_macro::Span)>, pub slug: Option<(Path, proc_macro::Span)>,
@ -143,7 +128,7 @@ impl DiagnosticDeriveBuilder {
} }
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
/// attributes like `#[error(..)`, such as the diagnostic kind and slug. Generates /// attributes like `#[diag(..)]`, such as the slug and error code. Generates
/// diagnostic builder calls for setting error code and creating note/help messages. /// diagnostic builder calls for setting error code and creating note/help messages.
fn generate_structure_code_for_attr( fn generate_structure_code_for_attr(
&mut self, &mut self,
@ -156,15 +141,15 @@ impl DiagnosticDeriveBuilder {
let name = name.as_str(); let name = name.as_str();
let meta = attr.parse_meta()?; let meta = attr.parse_meta()?;
let is_help_note_or_warn = matches!(name, "help" | "note" | "warn_"); let is_diag = matches!(name, "error" | "warning" | "lint" | "diag");
let nested = match meta { let nested = match meta {
// Most attributes are lists, like `#[error(..)]`/`#[warning(..)]` for most cases or // Most attributes are lists, like `#[diag(..)]` for most cases or
// `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug. // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug.
Meta::List(MetaList { ref nested, .. }) => nested, Meta::List(MetaList { ref nested, .. }) => nested,
// Subdiagnostics without spans can be applied to the type too, and these are just // Subdiagnostics without spans can be applied to the type too, and these are just
// paths: `#[help]` and `#[note]` // paths: `#[help]`, `#[note]` and `#[warn_]`
Meta::Path(_) if is_help_note_or_warn => { Meta::Path(_) if !is_diag => {
let fn_name = if name == "warn_" { let fn_name = if name == "warn_" {
Ident::new("warn", attr.span()) Ident::new("warn", attr.span())
} else { } else {
@ -178,23 +163,32 @@ impl DiagnosticDeriveBuilder {
// Check the kind before doing any further processing so that there aren't misleading // Check the kind before doing any further processing so that there aren't misleading
// "no kind specified" errors if there are failures later. // "no kind specified" errors if there are failures later.
match name { match name {
"error" => self.kind.set_once((DiagnosticDeriveKind::Error, span)), "error" | "warning" => {
"warning" => self.kind.set_once((DiagnosticDeriveKind::Warn, span)), if self.kind == DiagnosticDeriveKind::LintDiagnostic {
"lint" => self.kind.set_once((DiagnosticDeriveKind::Lint, span)), span_err(span, "only `#[lint(..)]` is supported")
"help" | "note" | "warn_" => (), .help("use the `#[lint(...)]` attribute to create a lint")
.emit();
}
}
"lint" => {
if self.kind == DiagnosticDeriveKind::SessionDiagnostic {
span_err(span, "only `#[error(..)]` and `#[warning(..)]` are supported")
.help("use the `#[error(...)]` attribute to create a error")
.emit();
}
}
"diag" | "help" | "note" | "warn_" => (),
_ => throw_invalid_attr!(attr, &meta, |diag| { _ => throw_invalid_attr!(attr, &meta, |diag| {
diag.help( diag.help("only `diag`, `help`, `note` and `warn_` are valid attributes")
"only `error`, `warning`, `help`, `note` and `warn_` are valid attributes",
)
}), }),
} }
// First nested element should always be the path, e.g. `#[error(typeck::invalid)]` or // First nested element should always be the path, e.g. `#[diag(typeck::invalid)]` or
// `#[help(typeck::another_help)]`. // `#[help(typeck::another_help)]`.
let mut nested_iter = nested.into_iter(); let mut nested_iter = nested.into_iter();
if let Some(nested_attr) = nested_iter.next() { if let Some(nested_attr) = nested_iter.next() {
// Report an error if there are any other list items after the path. // Report an error if there are any other list items after the path.
if is_help_note_or_warn && nested_iter.next().is_some() { if !is_diag && nested_iter.next().is_some() {
throw_invalid_nested_attr!(attr, &nested_attr, |diag| { throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
diag.help( diag.help(
"`help`, `note` and `warn_` struct attributes can only have one argument", "`help`, `note` and `warn_` struct attributes can only have one argument",
@ -203,16 +197,16 @@ impl DiagnosticDeriveBuilder {
} }
match nested_attr { match nested_attr {
NestedMeta::Meta(Meta::Path(path)) if is_help_note_or_warn => {
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)) => { NestedMeta::Meta(Meta::Path(path)) => {
self.slug.set_once((path.clone(), span)); if is_diag {
self.slug.set_once((path.clone(), span));
} else {
let fn_name = proc_macro2::Ident::new(name, attr.span());
return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); });
}
} }
NestedMeta::Meta(meta @ Meta::NameValue(_)) NestedMeta::Meta(meta @ Meta::NameValue(_))
if !is_help_note_or_warn if is_diag && meta.path().segments.last().unwrap().ident == "code" =>
&& meta.path().segments.last().unwrap().ident == "code" =>
{ {
// don't error for valid follow-up attributes // don't error for valid follow-up attributes
} }
@ -347,6 +341,7 @@ impl DiagnosticDeriveBuilder {
} }
"primary_span" => { "primary_span" => {
report_error_if_not_applied_to_span(attr, &info)?; report_error_if_not_applied_to_span(attr, &info)?;
Ok(quote! { Ok(quote! {
#diag.set_span(#binding); #diag.set_span(#binding);
}) })

View File

@ -132,6 +132,7 @@ decl_derive!(
warning, warning,
error, error,
lint, lint,
diag,
help, help,
note, note,
warn_, warn_,
@ -151,6 +152,7 @@ decl_derive!(
warning, warning,
error, error,
lint, lint,
diag,
help, help,
note, note,
warn_, warn_,

View File

@ -52,7 +52,7 @@ struct WrongStructAttrStyle {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
//~^ ERROR `#[nonsense(...)]` is not a valid attribute //~^ ERROR `#[nonsense(...)]` is not a valid attribute
//~^^ ERROR diagnostic kind not specified //~^^ ERROR diagnostic slug not specified
//~^^^ ERROR cannot find attribute `nonsense` in this scope //~^^^ ERROR cannot find attribute `nonsense` in this scope
struct InvalidStructAttr {} struct InvalidStructAttr {}
@ -103,7 +103,6 @@ struct WrongPlaceField {
#[error(typeck::ambiguous_lifetime_bound, code = "E0456")] #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
//~^ ERROR specified multiple times //~^ ERROR specified multiple times
//~^^ ERROR specified multiple times //~^^ ERROR specified multiple times
//~^^^ ERROR specified multiple times
struct ErrorSpecifiedTwice {} struct ErrorSpecifiedTwice {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
@ -111,7 +110,6 @@ struct ErrorSpecifiedTwice {}
#[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
//~^ ERROR specified multiple times //~^ ERROR specified multiple times
//~^^ ERROR specified multiple times //~^^ ERROR specified multiple times
//~^^^ ERROR specified multiple times
struct WarnSpecifiedAfterError {} struct WarnSpecifiedAfterError {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
@ -125,7 +123,7 @@ struct CodeSpecifiedTwice {}
struct SlugSpecifiedTwice {} struct SlugSpecifiedTwice {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
struct KindNotProvided {} //~ ERROR diagnostic kind not specified struct KindNotProvided {} //~ ERROR diagnostic slug not specified
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[error(code = "E0456")] #[error(code = "E0456")]

View File

@ -21,9 +21,9 @@ error: `#[nonsense(...)]` is not a valid attribute
LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= help: only `error`, `warning`, `help`, `note` and `warn_` are valid attributes = help: only `diag`, `help`, `note` and `warn_` are valid attributes
error: diagnostic kind not specified error: diagnostic slug not specified
--> $DIR/diagnostic-derive.rs:53:1 --> $DIR/diagnostic-derive.rs:53:1
| |
LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
@ -33,7 +33,7 @@ LL | |
LL | | struct InvalidStructAttr {} LL | | struct InvalidStructAttr {}
| |___________________________^ | |___________________________^
| |
= help: use the `#[error(...)]` attribute to create an error = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
error: `#[error("...")]` is not a valid attribute error: `#[error("...")]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:60:9 --> $DIR/diagnostic-derive.rs:60:9
@ -52,7 +52,7 @@ LL | |
LL | | struct InvalidLitNestedAttr {} LL | | struct InvalidLitNestedAttr {}
| |______________________________^ | |______________________________^
| |
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
error: `#[error(nonsense(...))]` is not a valid attribute error: `#[error(nonsense(...))]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:71:9 --> $DIR/diagnostic-derive.rs:71:9
@ -71,7 +71,7 @@ LL | |
LL | | struct InvalidNestedStructAttr1 {} LL | | struct InvalidNestedStructAttr1 {}
| |__________________________________^ | |__________________________________^
| |
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
error: `#[error(nonsense = ...)]` is not a valid attribute error: `#[error(nonsense = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:77:9 --> $DIR/diagnostic-derive.rs:77:9
@ -90,7 +90,7 @@ LL | |
LL | | struct InvalidNestedStructAttr2 {} LL | | struct InvalidNestedStructAttr2 {}
| |__________________________________^ | |__________________________________^
| |
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
error: `#[error(nonsense = ...)]` is not a valid attribute error: `#[error(nonsense = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:83:9 --> $DIR/diagnostic-derive.rs:83:9
@ -109,7 +109,7 @@ LL | |
LL | | struct InvalidNestedStructAttr3 {} LL | | struct InvalidNestedStructAttr3 {}
| |__________________________________^ | |__________________________________^
| |
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
error: `#[error(slug = ...)]` is not a valid attribute error: `#[error(slug = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:89:59 --> $DIR/diagnostic-derive.rs:89:59
@ -137,18 +137,6 @@ note: previously specified here
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
--> $DIR/diagnostic-derive.rs:103:1
|
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/diagnostic-derive.rs:102:1
|
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: specified multiple times error: specified multiple times
--> $DIR/diagnostic-derive.rs:103:50 --> $DIR/diagnostic-derive.rs:103:50
| |
@ -162,85 +150,73 @@ LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
| ^^^^^^^ | ^^^^^^^
error: specified multiple times error: specified multiple times
--> $DIR/diagnostic-derive.rs:111:1 --> $DIR/diagnostic-derive.rs:110:1
| |
LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
note: previously specified here note: previously specified here
--> $DIR/diagnostic-derive.rs:110:1 --> $DIR/diagnostic-derive.rs:109:1
| |
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: specified multiple times error: specified multiple times
--> $DIR/diagnostic-derive.rs:111:1 --> $DIR/diagnostic-derive.rs:110:52
|
LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/diagnostic-derive.rs:110:1
|
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
--> $DIR/diagnostic-derive.rs:111:52
| |
LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")] LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
| ^^^^^^^ | ^^^^^^^
| |
note: previously specified here note: previously specified here
--> $DIR/diagnostic-derive.rs:110:50 --> $DIR/diagnostic-derive.rs:109:50
| |
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")] LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
| ^^^^^^^ | ^^^^^^^
error: specified multiple times error: specified multiple times
--> $DIR/diagnostic-derive.rs:118:66 --> $DIR/diagnostic-derive.rs:116:66
| |
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
| ^^^^^^^ | ^^^^^^^
| |
note: previously specified here note: previously specified here
--> $DIR/diagnostic-derive.rs:118:50 --> $DIR/diagnostic-derive.rs:116:50
| |
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")] LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
| ^^^^^^^ | ^^^^^^^
error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:123:43 --> $DIR/diagnostic-derive.rs:121:43
| |
LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")] LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic kind not specified error: diagnostic slug not specified
--> $DIR/diagnostic-derive.rs:128:1 --> $DIR/diagnostic-derive.rs:126:1
| |
LL | struct KindNotProvided {} LL | struct KindNotProvided {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= help: use the `#[error(...)]` attribute to create an error = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
error: diagnostic slug not specified error: diagnostic slug not specified
--> $DIR/diagnostic-derive.rs:131:1 --> $DIR/diagnostic-derive.rs:129:1
| |
LL | / #[error(code = "E0456")] LL | / #[error(code = "E0456")]
LL | | LL | |
LL | | struct SlugNotProvided {} LL | | struct SlugNotProvided {}
| |_________________________^ | |_________________________^
| |
= help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]` = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/diagnostic-derive.rs:142:5 --> $DIR/diagnostic-derive.rs:140:5
| |
LL | #[primary_span] LL | #[primary_span]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: `#[nonsense]` is not a valid attribute error: `#[nonsense]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:150:5 --> $DIR/diagnostic-derive.rs:148:5
| |
LL | #[nonsense] LL | #[nonsense]
| ^^^^^^^^^^^ | ^^^^^^^^^^^
@ -248,19 +224,19 @@ LL | #[nonsense]
= help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes = 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` or `MultiSpan` error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/diagnostic-derive.rs:167:5 --> $DIR/diagnostic-derive.rs:165:5
| |
LL | #[label(typeck::label)] LL | #[label(typeck::label)]
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^
error: `name` doesn't refer to a field on this type error: `name` doesn't refer to a field on this type
--> $DIR/diagnostic-derive.rs:175:45 --> $DIR/diagnostic-derive.rs:173:45
| |
LL | #[suggestion(typeck::suggestion, code = "{name}")] LL | #[suggestion(typeck::suggestion, code = "{name}")]
| ^^^^^^^^ | ^^^^^^^^
error: invalid format string: expected `'}'` but string was terminated error: invalid format string: expected `'}'` but string was terminated
--> $DIR/diagnostic-derive.rs:180:16 --> $DIR/diagnostic-derive.rs:178:16
| |
LL | #[derive(SessionDiagnostic)] LL | #[derive(SessionDiagnostic)]
| - ^ expected `'}'` in format string | - ^ expected `'}'` in format string
@ -271,7 +247,7 @@ LL | #[derive(SessionDiagnostic)]
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) = 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 error: invalid format string: unmatched `}` found
--> $DIR/diagnostic-derive.rs:190:15 --> $DIR/diagnostic-derive.rs:188:15
| |
LL | #[derive(SessionDiagnostic)] LL | #[derive(SessionDiagnostic)]
| ^ unmatched `}` in format string | ^ unmatched `}` in format string
@ -280,13 +256,13 @@ LL | #[derive(SessionDiagnostic)]
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) = 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` or `MultiSpan` error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/diagnostic-derive.rs:210:5 --> $DIR/diagnostic-derive.rs:208:5
| |
LL | #[label(typeck::label)] LL | #[label(typeck::label)]
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion(nonsense = ...)]` is not a valid attribute error: `#[suggestion(nonsense = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:235:18 --> $DIR/diagnostic-derive.rs:233:18
| |
LL | #[suggestion(nonsense = "bar")] LL | #[suggestion(nonsense = "bar")]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
@ -294,7 +270,7 @@ LL | #[suggestion(nonsense = "bar")]
= help: only `message`, `code` and `applicability` are valid field attributes = help: only `message`, `code` and `applicability` are valid field attributes
error: `#[suggestion(msg = ...)]` is not a valid attribute error: `#[suggestion(msg = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:243:18 --> $DIR/diagnostic-derive.rs:241:18
| |
LL | #[suggestion(msg = "bar")] LL | #[suggestion(msg = "bar")]
| ^^^^^^^^^^^ | ^^^^^^^^^^^
@ -302,7 +278,7 @@ LL | #[suggestion(msg = "bar")]
= help: only `message`, `code` and `applicability` are valid field attributes = help: only `message`, `code` and `applicability` are valid field attributes
error: wrong field type for suggestion error: wrong field type for suggestion
--> $DIR/diagnostic-derive.rs:265:5 --> $DIR/diagnostic-derive.rs:263:5
| |
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
LL | | LL | |
@ -312,7 +288,7 @@ LL | | suggestion: Applicability,
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, 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` error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
--> $DIR/diagnostic-derive.rs:280:5 --> $DIR/diagnostic-derive.rs:278:5
| |
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
LL | | LL | |
@ -320,7 +296,7 @@ LL | | suggestion: (Span, Span, Applicability),
| |___________________________________________^ | |___________________________________________^
error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
--> $DIR/diagnostic-derive.rs:288:5 --> $DIR/diagnostic-derive.rs:286:5
| |
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")] LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
LL | | LL | |
@ -328,60 +304,54 @@ LL | | suggestion: (Applicability, Applicability, Span),
| |____________________________________________________^ | |____________________________________________________^
error: `#[label = ...]` is not a valid attribute error: `#[label = ...]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:296:5 --> $DIR/diagnostic-derive.rs:294:5
| |
LL | #[label = "bar"] LL | #[label = "bar"]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: applicability cannot be set in both the field and attribute error: applicability cannot be set in both the field and attribute
--> $DIR/diagnostic-derive.rs:447:52 --> $DIR/diagnostic-derive.rs:445:52
| |
LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")] LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: invalid applicability error: invalid applicability
--> $DIR/diagnostic-derive.rs:455:52 --> $DIR/diagnostic-derive.rs:453:52
| |
LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")] LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[label(...)]` is not a valid attribute error: `#[label(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:518:5 --> $DIR/diagnostic-derive.rs:516:5
| |
LL | #[label(typeck::label, foo)] LL | #[label(typeck::label, foo)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[label(...)]` is not a valid attribute error: `#[label(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:526:5 --> $DIR/diagnostic-derive.rs:524:5
| |
LL | #[label(typeck::label, foo = "...")] LL | #[label(typeck::label, foo = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[label(...)]` is not a valid attribute error: `#[label(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:534:5 --> $DIR/diagnostic-derive.rs:532:5
| |
LL | #[label(typeck::label, foo("..."))] LL | #[label(typeck::label, foo("..."))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: only `#[error(..)]` and `#[warning(..)]` are supported error: only `#[error(..)]` and `#[warning(..)]` are supported
--> $DIR/diagnostic-derive.rs:540:1 --> $DIR/diagnostic-derive.rs:538:1
| |
LL | / #[lint(typeck::ambiguous_lifetime_bound)] LL | #[lint(typeck::ambiguous_lifetime_bound)]
LL | | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | | struct LintsBad {
LL | | }
| |_^
| |
= help: use the `#[error(...)]` attribute to create a error = help: use the `#[error(...)]` attribute to create a error
error: only `#[lint(..)]` is supported error: only `#[lint(..)]` is supported
--> $DIR/diagnostic-derive.rs:551:1 --> $DIR/diagnostic-derive.rs:549:1
| |
LL | / #[error(typeck::ambiguous_lifetime_bound)] LL | #[error(typeck::ambiguous_lifetime_bound)]
LL | | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | | struct ErrorsBad {
LL | | }
| |_^
| |
= help: use the `#[lint(...)]` attribute to create a lint = help: use the `#[lint(...)]` attribute to create a lint
@ -392,7 +362,7 @@ LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
| ^^^^^^^^ | ^^^^^^^^
error: cannot find attribute `nonsense` in this scope error: cannot find attribute `nonsense` in this scope
--> $DIR/diagnostic-derive.rs:150:7 --> $DIR/diagnostic-derive.rs:148:7
| |
LL | #[nonsense] LL | #[nonsense]
| ^^^^^^^^ | ^^^^^^^^
@ -404,7 +374,7 @@ LL | #[error(nonsense, code = "E0123")]
| ^^^^^^^^ not found in `rustc_errors::fluent` | ^^^^^^^^ not found in `rustc_errors::fluent`
error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
--> $DIR/diagnostic-derive.rs:340:10 --> $DIR/diagnostic-derive.rs:338:10
| |
LL | #[derive(SessionDiagnostic)] LL | #[derive(SessionDiagnostic)]
| ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello` | ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
@ -417,7 +387,7 @@ LL | arg: impl IntoDiagnosticArg,
| ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg` | ^^^^^^^^^^^^^^^^^ 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) = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 48 previous errors error: aborting due to 46 previous errors
Some errors have detailed explanations: E0277, E0425. Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`. For more information about an error, try `rustc --explain E0277`.