1
Fork 0

macros: add helper functions for invalid attrs

Remove some duplicated code between both diagnostic derives by
introducing helper functions for reporting an error in case of a invalid
attribute.

Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
David Wood 2022-04-27 04:06:13 +01:00
parent 071f07274b
commit 36a396ce51
7 changed files with 226 additions and 292 deletions

View file

@ -1,6 +1,9 @@
#![deny(unused_must_use)] #![deny(unused_must_use)]
use crate::diagnostics::error::{span_err, throw_span_err, SessionDiagnosticDeriveError}; use crate::diagnostics::error::{
invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
SessionDiagnosticDeriveError,
};
use crate::diagnostics::utils::{ use crate::diagnostics::utils::{
option_inner_ty, report_error_if_not_applied_to_span, type_matches_path, FieldInfo, HasFieldMap, option_inner_ty, report_error_if_not_applied_to_span, type_matches_path, FieldInfo, HasFieldMap,
}; };
@ -292,39 +295,24 @@ impl SessionDiagnosticDeriveBuilder {
} }
let nested = match meta { let nested = match meta {
Meta::List(MetaList { nested, .. }) => nested, Meta::List(MetaList { ref nested, .. }) => nested,
Meta::Path(..) => throw_span_err!( _ => throw_invalid_attr!(attr, &meta),
span,
&format!("`#[{}]` is not a valid `SessionDiagnostic` struct attribute", name)
),
Meta::NameValue(..) => throw_span_err!(
span,
&format!("`#[{} = ...]` is not a valid `SessionDiagnostic` struct attribute", name)
),
}; };
let kind = match name { let kind = match name {
"error" => SessionDiagnosticKind::Error, "error" => SessionDiagnosticKind::Error,
"warning" => SessionDiagnosticKind::Warn, "warning" => SessionDiagnosticKind::Warn,
other => throw_span_err!( _ => throw_invalid_attr!(attr, &meta, |diag| {
span, diag.help("only `error` and `warning` are valid attributes")
&format!("`#[{}(...)]` is not a valid `SessionDiagnostic` struct attribute", other) }),
),
}; };
self.set_kind_once(kind, span)?; self.set_kind_once(kind, span)?;
let mut tokens = Vec::new(); let mut tokens = Vec::new();
for attr in nested { for nested_attr in nested {
let span = attr.span().unwrap(); let meta = match nested_attr {
let meta = match attr {
syn::NestedMeta::Meta(meta) => meta, syn::NestedMeta::Meta(meta) => meta,
syn::NestedMeta::Lit(_) => throw_span_err!( _ => throw_invalid_nested_attr!(attr, &nested_attr),
span,
&format!(
"`#[{}(\"...\")]` is not a valid `SessionDiagnostic` struct attribute",
name
)
),
}; };
let path = meta.path(); let path = meta.path();
@ -340,49 +328,12 @@ impl SessionDiagnosticDeriveBuilder {
"code" => { "code" => {
tokens.push(self.set_code_once(s.value(), s.span().unwrap())); tokens.push(self.set_code_once(s.value(), s.span().unwrap()));
} }
other => { _ => invalid_nested_attr(attr, &nested_attr)
let diag = span_err( .help("only `slug` and `code` are valid nested attributes")
span, .emit(),
&format!(
"`#[{}({} = ...)]` is not a valid `SessionDiagnostic` struct attribute",
name, other
),
);
diag.emit();
}
} }
} }
Meta::NameValue(..) => { _ => invalid_nested_attr(attr, &nested_attr).emit(),
span_err(
span,
&format!(
"`#[{}({} = ...)]` is not a valid `SessionDiagnostic` struct attribute",
name, nested_name
),
)
.help("value must be a string")
.emit();
}
Meta::Path(..) => {
span_err(
span,
&format!(
"`#[{}({})]` is not a valid `SessionDiagnostic` struct attribute",
name, nested_name
),
)
.emit();
}
Meta::List(..) => {
span_err(
span,
&format!(
"`#[{}({}(...))]` is not a valid `SessionDiagnostic` struct attribute",
name, nested_name
),
)
.emit();
}
} }
} }
@ -478,7 +429,6 @@ impl SessionDiagnosticDeriveBuilder {
info: FieldInfo<'_>, info: FieldInfo<'_>,
) -> Result<TokenStream, SessionDiagnosticDeriveError> { ) -> Result<TokenStream, SessionDiagnosticDeriveError> {
let diag = &self.diag; let diag = &self.diag;
let span = attr.span().unwrap();
let field_binding = &info.binding.binding; let field_binding = &info.binding.binding;
let name = attr.path.segments.last().unwrap().ident.to_string(); let name = attr.path.segments.last().unwrap().ident.to_string();
@ -502,43 +452,31 @@ impl SessionDiagnosticDeriveBuilder {
report_error_if_not_applied_to_span(attr, &info)?; report_error_if_not_applied_to_span(attr, &info)?;
Ok(self.add_subdiagnostic(field_binding, name, name)) Ok(self.add_subdiagnostic(field_binding, name, name))
} }
other => throw_span_err!( _ => throw_invalid_attr!(attr, &meta, |diag| {
span, diag
&format!("`#[{}]` is not a valid `SessionDiagnostic` field attribute", other) .help("only `skip_arg`, `primary_span`, `label`, `note` and `help` are valid field attributes")
), }),
}, },
Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => match name { Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(ref s), .. }) => match name {
"label" | "note" | "help" => { "label" | "note" | "help" => {
report_error_if_not_applied_to_span(attr, &info)?; report_error_if_not_applied_to_span(attr, &info)?;
Ok(self.add_subdiagnostic(field_binding, name, &s.value())) Ok(self.add_subdiagnostic(field_binding, name, &s.value()))
} }
other => throw_span_err!( _ => throw_invalid_attr!(attr, &meta, |diag| {
span, diag.help("only `label`, `note` and `help` are valid field attributes")
&format!( }),
"`#[{} = ...]` is not a valid `SessionDiagnostic` field attribute",
other
)
),
}, },
Meta::NameValue(_) => throw_span_err!( Meta::List(MetaList { ref path, ref nested, .. }) => {
span,
&format!("`#[{} = ...]` is not a valid `SessionDiagnostic` field attribute", name),
|diag| diag.help("value must be a string")
),
Meta::List(MetaList { path, nested, .. }) => {
let name = path.segments.last().unwrap().ident.to_string(); let name = path.segments.last().unwrap().ident.to_string();
let name = name.as_ref(); let name = name.as_ref();
match name { match name {
"suggestion" | "suggestion_short" | "suggestion_hidden" "suggestion" | "suggestion_short" | "suggestion_hidden"
| "suggestion_verbose" => (), | "suggestion_verbose" => (),
other => throw_span_err!( _ => throw_invalid_attr!(attr, &meta, |diag| {
span, diag
&format!( .help("only `suggestion{,_short,_hidden,_verbose}` are valid field attributes")
"`#[{}(...)]` is not a valid `SessionDiagnostic` field attribute", }),
other
)
),
}; };
let (span_, applicability) = self.span_and_applicability_of_ty(info)?; let (span_, applicability) = self.span_and_applicability_of_ty(info)?;
@ -546,22 +484,14 @@ impl SessionDiagnosticDeriveBuilder {
let mut msg = None; let mut msg = None;
let mut code = None; let mut code = None;
for attr in nested { for nested_attr in nested {
let meta = match attr { let meta = match nested_attr {
syn::NestedMeta::Meta(meta) => meta, syn::NestedMeta::Meta(ref meta) => meta,
syn::NestedMeta::Lit(_) => throw_span_err!( syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr),
span,
&format!(
"`#[{}(\"...\")]` is not a valid `SessionDiagnostic` field attribute",
name
)
),
}; };
let span = meta.span().unwrap();
let nested_name = meta.path().segments.last().unwrap().ident.to_string(); let nested_name = meta.path().segments.last().unwrap().ident.to_string();
let nested_name = nested_name.as_str(); let nested_name = nested_name.as_str();
match meta { match meta {
Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => { Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
match nested_name { match nested_name {
@ -572,37 +502,14 @@ impl SessionDiagnosticDeriveBuilder {
let formatted_str = self.build_format(&s.value(), s.span()); let formatted_str = self.build_format(&s.value(), s.span());
code = Some(formatted_str); code = Some(formatted_str);
} }
other => throw_span_err!( _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
span, diag.help(
&format!( "only `message` and `code` are valid field attributes",
"`#[{}({} = ...)]` is not a valid `SessionDiagnostic` field attribute",
name, other
) )
), }),
} }
} }
Meta::NameValue(..) => throw_span_err!( _ => throw_invalid_nested_attr!(attr, &nested_attr),
span,
&format!(
"`#[{}({} = ...)]` is not a valid `SessionDiagnostic` struct attribute",
name, nested_name
),
|diag| diag.help("value must be a string")
),
Meta::Path(..) => throw_span_err!(
span,
&format!(
"`#[{}({})]` is not a valid `SessionDiagnostic` struct attribute",
name, nested_name
)
),
Meta::List(..) => throw_span_err!(
span,
&format!(
"`#[{}({}(...))]` is not a valid `SessionDiagnostic` struct attribute",
name, nested_name
)
),
} }
} }
@ -619,6 +526,7 @@ impl SessionDiagnosticDeriveBuilder {
Ok(quote! { #diag.#method(#span_, #msg, #code, #applicability); }) Ok(quote! { #diag.#method(#span_, #msg, #code, #applicability); })
} }
_ => throw_invalid_attr!(attr, &meta),
} }
} }

View file

@ -1,11 +1,11 @@
use proc_macro::{Diagnostic, Level, MultiSpan}; use proc_macro::{Diagnostic, Level, MultiSpan};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use syn; use syn::{spanned::Spanned, Attribute, Error as SynError, Meta, NestedMeta};
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum SessionDiagnosticDeriveError { pub(crate) enum SessionDiagnosticDeriveError {
SynError(syn::Error), SynError(SynError),
ErrorHandled, ErrorHandled,
} }
@ -24,37 +24,109 @@ impl SessionDiagnosticDeriveError {
} }
} }
impl From<SynError> for SessionDiagnosticDeriveError {
fn from(e: SynError) -> Self {
SessionDiagnosticDeriveError::SynError(e)
}
}
/// Helper function for use with `throw_*` macros - constraints `$f` to an `impl FnOnce`.
pub(crate) fn _throw_err(
diag: Diagnostic,
f: impl FnOnce(Diagnostic) -> Diagnostic,
) -> SessionDiagnosticDeriveError {
f(diag).emit();
SessionDiagnosticDeriveError::ErrorHandled
}
/// Returns an error diagnostic on span `span` with msg `msg`.
pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic { pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic {
Diagnostic::spanned(span, Level::Error, msg) Diagnostic::spanned(span, Level::Error, msg)
} }
/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`:
///
/// Emit a diagnostic on span `$span` with msg `$msg` (optionally performing additional decoration /// Emit a diagnostic on span `$span` with msg `$msg` (optionally performing additional decoration
/// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`. /// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
///
/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`:
macro_rules! throw_span_err { macro_rules! throw_span_err {
($span:expr, $msg:expr) => {{ throw_span_err!($span, $msg, |diag| diag) }}; ($span:expr, $msg:expr) => {{ throw_span_err!($span, $msg, |diag| diag) }};
($span:expr, $msg:expr, $f:expr) => {{ ($span:expr, $msg:expr, $f:expr) => {{
return Err(crate::diagnostics::error::_throw_span_err($span, $msg, $f)); let diag = span_err($span, $msg);
return Err(crate::diagnostics::error::_throw_err(diag, $f));
}}; }};
} }
pub(crate) use throw_span_err; pub(crate) use throw_span_err;
/// When possible, prefer using `throw_span_err!` over using this function directly. This only /// Returns an error diagnostic for an invalid attribute.
/// exists as a function to constrain `f` to an `impl FnOnce`. pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
pub(crate) fn _throw_span_err( let span = attr.span().unwrap();
span: impl MultiSpan, let name = attr.path.segments.last().unwrap().ident.to_string();
msg: &str, let name = name.as_str();
f: impl FnOnce(Diagnostic) -> Diagnostic,
) -> SessionDiagnosticDeriveError {
let diag = span_err(span, msg);
f(diag).emit();
SessionDiagnosticDeriveError::ErrorHandled
}
impl From<syn::Error> for SessionDiagnosticDeriveError { match meta {
fn from(e: syn::Error) -> Self { Meta::Path(_) => span_err(span, &format!("`#[{}]` is not a valid attribute", name)),
SessionDiagnosticDeriveError::SynError(e) Meta::NameValue(_) => {
span_err(span, &format!("`#[{} = ...]` is not a valid attribute", name))
}
Meta::List(_) => span_err(span, &format!("`#[{}(...)]` is not a valid attribute", name)),
} }
} }
/// Emit a error diagnostic for an invalid attribute (optionally performing additional decoration
/// using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
///
/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`:
macro_rules! throw_invalid_attr {
($attr:expr, $meta:expr) => {{ throw_invalid_attr!($attr, $meta, |diag| diag) }};
($attr:expr, $meta:expr, $f:expr) => {{
let diag = crate::diagnostics::error::invalid_attr($attr, $meta);
return Err(crate::diagnostics::error::_throw_err(diag, $f));
}};
}
pub(crate) use throw_invalid_attr;
/// Returns an error diagnostic for an invalid nested attribute.
pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diagnostic {
let name = attr.path.segments.last().unwrap().ident.to_string();
let name = name.as_str();
let span = nested.span().unwrap();
let meta = match nested {
syn::NestedMeta::Meta(meta) => meta,
syn::NestedMeta::Lit(_) => {
return span_err(span, &format!("`#[{}(\"...\")]` is not a valid attribute", name));
}
};
let span = meta.span().unwrap();
let nested_name = meta.path().segments.last().unwrap().ident.to_string();
let nested_name = nested_name.as_str();
match meta {
Meta::NameValue(..) => span_err(
span,
&format!("`#[{}({} = ...)]` is not a valid attribute", name, nested_name),
),
Meta::Path(..) => {
span_err(span, &format!("`#[{}({})]` is not a valid attribute", name, nested_name))
}
Meta::List(..) => {
span_err(span, &format!("`#[{}({}(...))]` is not a valid attribute", name, nested_name))
}
}
}
/// Emit a error diagnostic for an invalid nested attribute (optionally performing additional
/// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
///
/// For methods that return a `Result<_, SessionDiagnosticDeriveError>`:
macro_rules! throw_invalid_nested_attr {
($attr:expr, $nested_attr:expr) => {{ throw_invalid_nested_attr!($attr, $nested_attr, |diag| diag) }};
($attr:expr, $nested_attr:expr, $f:expr) => {{
let diag = crate::diagnostics::error::invalid_nested_attr($attr, $nested_attr);
return Err(crate::diagnostics::error::_throw_err(diag, $f));
}};
}
pub(crate) use throw_invalid_nested_attr;

View file

@ -1,6 +1,9 @@
#![deny(unused_must_use)] #![deny(unused_must_use)]
use crate::diagnostics::error::{span_err, throw_span_err, SessionDiagnosticDeriveError}; use crate::diagnostics::error::{
span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
SessionDiagnosticDeriveError,
};
use crate::diagnostics::utils::{ use crate::diagnostics::utils::{
option_inner_ty, report_error_if_not_applied_to_applicability, option_inner_ty, report_error_if_not_applied_to_applicability,
report_error_if_not_applied_to_span, FieldInfo, HasFieldMap, SetOnce, report_error_if_not_applied_to_span, FieldInfo, HasFieldMap, SetOnce,
@ -253,25 +256,11 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
let meta = attr.parse_meta()?; let meta = attr.parse_meta()?;
let kind = match meta { let kind = match meta {
Meta::Path(_) => throw_span_err!( Meta::List(MetaList { ref nested, .. }) => {
span, for nested_attr in nested {
&format!("`#[{}]` is not a valid `SessionSubdiagnostic` attribute", name) let meta = match nested_attr {
), syn::NestedMeta::Meta(ref meta) => meta,
Meta::NameValue(_) => throw_span_err!( _ => throw_invalid_nested_attr!(attr, &nested_attr),
span,
&format!("`#[{} = ...]` is not a valid `SessionSubdiagnostic` attribute", name)
),
Meta::List(MetaList { nested, .. }) => {
for attr in nested {
let meta = match attr {
syn::NestedMeta::Meta(meta) => meta,
syn::NestedMeta::Lit(_) => throw_span_err!(
span,
&format!(
"`#[{}(\"...\")]` is not a valid `SessionSubdiagnostic` attribute",
name
)
),
}; };
let span = meta.span().unwrap(); let span = meta.span().unwrap();
@ -296,51 +285,22 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
}; };
self.applicability.set_once((quote! { #value }, span)); self.applicability.set_once((quote! { #value }, span));
} }
other => throw_span_err!( _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
span, diag.help("only `code`, `slug` and `applicability` are valid nested attributes")
&format!( }),
"`#[{}({} = ...)]` is not a valid `SessionSubdiagnostic` attribute",
name, other
)
),
} }
} }
Meta::NameValue(..) => throw_span_err!( _ => throw_invalid_nested_attr!(attr, &nested_attr),
span,
&format!(
"`#[{}({} = ...)]` is not a valid `SessionSubdiagnostic` attribute",
name, nested_name
),
|diag| diag.help("value must be a string")
),
Meta::Path(..) => throw_span_err!(
span,
&format!(
"`#[{}({})]` is not a valid `SessionSubdiagnostic` attribute",
name, nested_name
)
),
Meta::List(..) => throw_span_err!(
span,
&format!(
"`#[{}({}(...))]` is not a valid `SessionSubdiagnostic` attribute",
name, nested_name
)
),
} }
} }
let Ok(kind) = SubdiagnosticKind::from_str(name) else { let Ok(kind) = SubdiagnosticKind::from_str(name) else {
throw_span_err!( throw_invalid_attr!(attr, &meta)
span,
&format!(
"`#[{}(...)]` is not a valid `SessionSubdiagnostic` attribute",
name
)
);
}; };
kind kind
} }
_ => throw_invalid_attr!(attr, &meta),
}; };
if matches!( if matches!(
@ -408,31 +368,11 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
"skip_arg" => { "skip_arg" => {
return Ok(quote! {}); return Ok(quote! {});
} }
other => span_err( _ => throw_invalid_attr!(attr, &meta, |diag| {
span, diag.help("only `primary_span`, `applicability` and `skip_arg` are valid field attributes")
&format!( }),
"`#[{}]` is not a valid `SessionSubdiagnostic` field attribute",
other
),
)
.emit(),
}, },
Meta::NameValue(_) => span_err( _ => throw_invalid_attr!(attr, &meta),
span,
&format!(
"`#[{} = ...]` is not a valid `SessionSubdiagnostic` field attribute",
name
),
)
.emit(),
Meta::List(_) => span_err(
span,
&format!(
"`#[{}(...)]` is not a valid `SessionSubdiagnostic` field attribute",
name
),
)
.emit(),
} }
} }

View file

@ -44,47 +44,47 @@ enum SessionDiagnosticOnEnum {
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[error(code = "E0123", slug = "foo")] #[error(code = "E0123", slug = "foo")]
#[error = "E0123"] #[error = "E0123"]
//~^ ERROR `#[error = ...]` is not a valid `SessionDiagnostic` struct attribute //~^ ERROR `#[error = ...]` is not a valid attribute
struct WrongStructAttrStyle {} struct WrongStructAttrStyle {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[nonsense(code = "E0123", slug = "foo")] #[nonsense(code = "E0123", slug = "foo")]
//~^ ERROR `#[nonsense(...)]` is not a valid `SessionDiagnostic` struct attribute //~^ ERROR `#[nonsense(...)]` is not a valid attribute
//~^^ ERROR diagnostic kind not specified //~^^ ERROR diagnostic kind not specified
//~^^^ ERROR cannot find attribute `nonsense` in this scope //~^^^ ERROR cannot find attribute `nonsense` in this scope
struct InvalidStructAttr {} struct InvalidStructAttr {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[error("E0123")] #[error("E0123")]
//~^ ERROR `#[error("...")]` is not a valid `SessionDiagnostic` struct attribute //~^ ERROR `#[error("...")]` is not a valid attribute
//~^^ ERROR `slug` not specified //~^^ ERROR `slug` not specified
struct InvalidLitNestedAttr {} struct InvalidLitNestedAttr {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[error(nonsense, code = "E0123", slug = "foo")] #[error(nonsense, code = "E0123", slug = "foo")]
//~^ ERROR `#[error(nonsense)]` is not a valid `SessionDiagnostic` struct attribute //~^ ERROR `#[error(nonsense)]` is not a valid attribute
struct InvalidNestedStructAttr {} struct InvalidNestedStructAttr {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[error(nonsense("foo"), code = "E0123", slug = "foo")] #[error(nonsense("foo"), code = "E0123", slug = "foo")]
//~^ ERROR `#[error(nonsense(...))]` is not a valid `SessionDiagnostic` struct attribute //~^ ERROR `#[error(nonsense(...))]` is not a valid attribute
struct InvalidNestedStructAttr1 {} struct InvalidNestedStructAttr1 {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[error(nonsense = "...", code = "E0123", slug = "foo")] #[error(nonsense = "...", code = "E0123", slug = "foo")]
//~^ ERROR `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute //~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute
struct InvalidNestedStructAttr2 {} struct InvalidNestedStructAttr2 {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[error(nonsense = 4, code = "E0123", slug = "foo")] #[error(nonsense = 4, code = "E0123", slug = "foo")]
//~^ ERROR `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute //~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute
struct InvalidNestedStructAttr3 {} struct InvalidNestedStructAttr3 {}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[error(code = "E0123", slug = "foo")] #[error(code = "E0123", slug = "foo")]
struct WrongPlaceField { struct WrongPlaceField {
#[suggestion = "bar"] #[suggestion = "bar"]
//~^ ERROR `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute //~^ ERROR `#[suggestion = ...]` is not a valid attribute
sp: Span, sp: Span,
} }
@ -130,7 +130,7 @@ struct MessageWrongType {
#[error(code = "E0123", slug = "foo")] #[error(code = "E0123", slug = "foo")]
struct InvalidPathFieldAttr { struct InvalidPathFieldAttr {
#[nonsense] #[nonsense]
//~^ ERROR `#[nonsense]` is not a valid `SessionDiagnostic` field attribute //~^ ERROR `#[nonsense]` is not a valid attribute
//~^^ ERROR cannot find attribute `nonsense` in this scope //~^^ ERROR cannot find attribute `nonsense` in this scope
foo: String, foo: String,
} }
@ -215,7 +215,7 @@ struct SuggestWithoutCode {
#[error(code = "E0123", slug = "foo")] #[error(code = "E0123", slug = "foo")]
struct SuggestWithBadKey { struct SuggestWithBadKey {
#[suggestion(nonsense = "bar")] #[suggestion(nonsense = "bar")]
//~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid `SessionDiagnostic` field attribute //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
suggestion: (Span, Applicability), suggestion: (Span, Applicability),
} }
@ -223,7 +223,7 @@ struct SuggestWithBadKey {
#[error(code = "E0123", slug = "foo")] #[error(code = "E0123", slug = "foo")]
struct SuggestWithShorthandMsg { struct SuggestWithShorthandMsg {
#[suggestion(msg = "bar")] #[suggestion(msg = "bar")]
//~^ ERROR `#[suggestion(msg = ...)]` is not a valid `SessionDiagnostic` field attribute //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
suggestion: (Span, Applicability), suggestion: (Span, Applicability),
} }
@ -276,7 +276,7 @@ struct SuggestWithDuplicateApplicabilityAndSpan {
#[error(code = "E0123", slug = "foo")] #[error(code = "E0123", slug = "foo")]
struct WrongKindOfAnnotation { struct WrongKindOfAnnotation {
#[label("bar")] #[label("bar")]
//~^ ERROR `#[label(...)]` is not a valid `SessionDiagnostic` field attribute //~^ ERROR `#[label(...)]` is not a valid attribute
z: Span, z: Span,
} }

View file

@ -9,17 +9,19 @@ LL | | Bar,
LL | | } LL | | }
| |_^ | |_^
error: `#[error = ...]` is not a valid `SessionDiagnostic` struct attribute error: `#[error = ...]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:46:1 --> $DIR/diagnostic-derive.rs:46:1
| |
LL | #[error = "E0123"] LL | #[error = "E0123"]
| ^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^
error: `#[nonsense(...)]` is not a valid `SessionDiagnostic` struct attribute error: `#[nonsense(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:51:1 --> $DIR/diagnostic-derive.rs:51:1
| |
LL | #[nonsense(code = "E0123", slug = "foo")] LL | #[nonsense(code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: only `error` and `warning` are valid attributes
error: diagnostic kind not specified error: diagnostic kind not specified
--> $DIR/diagnostic-derive.rs:51:1 --> $DIR/diagnostic-derive.rs:51:1
@ -33,7 +35,7 @@ LL | | struct InvalidStructAttr {}
| |
= help: use the `#[error(...)]` attribute to create an error = help: use the `#[error(...)]` attribute to create an error
error: `#[error("...")]` is not a valid `SessionDiagnostic` struct attribute error: `#[error("...")]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:58:9 --> $DIR/diagnostic-derive.rs:58:9
| |
LL | #[error("E0123")] LL | #[error("E0123")]
@ -50,37 +52,39 @@ LL | | struct InvalidLitNestedAttr {}
| |
= help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug = help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug
error: `#[error(nonsense)]` is not a valid `SessionDiagnostic` struct attribute error: `#[error(nonsense)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:64:9 --> $DIR/diagnostic-derive.rs:64:9
| |
LL | #[error(nonsense, code = "E0123", slug = "foo")] LL | #[error(nonsense, code = "E0123", slug = "foo")]
| ^^^^^^^^ | ^^^^^^^^
error: `#[error(nonsense(...))]` is not a valid `SessionDiagnostic` struct attribute error: `#[error(nonsense(...))]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:69:9 --> $DIR/diagnostic-derive.rs:69:9
| |
LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")] LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute error: `#[error(nonsense = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:74:9 --> $DIR/diagnostic-derive.rs:74:9
| |
LL | #[error(nonsense = "...", code = "E0123", slug = "foo")] LL | #[error(nonsense = "...", code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
|
= help: only `slug` and `code` are valid nested attributes
error: `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute error: `#[error(nonsense = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:79:9 --> $DIR/diagnostic-derive.rs:79:9
| |
LL | #[error(nonsense = 4, code = "E0123", slug = "foo")] LL | #[error(nonsense = 4, code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
|
= help: value must be a string
error: `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute error: `#[suggestion = ...]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:86:5 --> $DIR/diagnostic-derive.rs:86:5
| |
LL | #[suggestion = "bar"] LL | #[suggestion = "bar"]
| ^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^
|
= help: only `label`, `note` and `help` are valid field attributes
error: `error` specified multiple times error: `error` specified multiple times
--> $DIR/diagnostic-derive.rs:93:1 --> $DIR/diagnostic-derive.rs:93:1
@ -153,11 +157,13 @@ error: the `#[primary_span]` attribute can only be applied to fields of type `Sp
LL | #[primary_span] LL | #[primary_span]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: `#[nonsense]` is not a valid `SessionDiagnostic` field attribute error: `#[nonsense]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:132:5 --> $DIR/diagnostic-derive.rs:132:5
| |
LL | #[nonsense] LL | #[nonsense]
| ^^^^^^^^^^^ | ^^^^^^^^^^^
|
= help: only `skip_arg`, `primary_span`, `label`, `note` and `help` are valid field attributes
error: the `#[label = ...]` attribute can only be applied to fields of type `Span` error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
--> $DIR/diagnostic-derive.rs:149:5 --> $DIR/diagnostic-derive.rs:149:5
@ -197,17 +203,21 @@ error: the `#[label = ...]` attribute can only be applied to fields of type `Spa
LL | #[label = "bar"] LL | #[label = "bar"]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: `#[suggestion(nonsense = ...)]` is not a valid `SessionDiagnostic` field attribute error: `#[suggestion(nonsense = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:217:18 --> $DIR/diagnostic-derive.rs:217:18
| |
LL | #[suggestion(nonsense = "bar")] LL | #[suggestion(nonsense = "bar")]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
|
= help: only `message` and `code` are valid field attributes
error: `#[suggestion(msg = ...)]` is not a valid `SessionDiagnostic` field attribute error: `#[suggestion(msg = ...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:225:18 --> $DIR/diagnostic-derive.rs:225:18
| |
LL | #[suggestion(msg = "bar")] LL | #[suggestion(msg = "bar")]
| ^^^^^^^^^^^ | ^^^^^^^^^^^
|
= help: only `message` and `code` are valid field attributes
error: wrong field type for suggestion error: wrong field type for suggestion
--> $DIR/diagnostic-derive.rs:247:5 --> $DIR/diagnostic-derive.rs:247:5
@ -235,11 +245,13 @@ LL | |
LL | | suggestion: (Applicability, Applicability, Span), LL | | suggestion: (Applicability, Applicability, Span),
| |____________________________________________________^ | |____________________________________________________^
error: `#[label(...)]` is not a valid `SessionDiagnostic` field attribute error: `#[label(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:278:5 --> $DIR/diagnostic-derive.rs:278:5
| |
LL | #[label("bar")] LL | #[label("bar")]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
|
= help: only `suggestion{,_short,_hidden,_verbose}` are valid field attributes
error: `#[help]` must come after `#[error(..)]` or `#[warn(..)]` error: `#[help]` must come after `#[error(..)]` or `#[warn(..)]`
--> $DIR/diagnostic-derive.rs:399:1 --> $DIR/diagnostic-derive.rs:399:1

View file

@ -52,7 +52,7 @@ struct C {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
#[label] #[label]
//~^ ERROR `#[label]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[label]` is not a valid attribute
struct D { struct D {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -61,7 +61,7 @@ struct D {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
#[foo] #[foo]
//~^ ERROR `#[foo]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[foo]` is not a valid attribute
//~^^ ERROR cannot find attribute `foo` in this scope //~^^ ERROR cannot find attribute `foo` in this scope
struct E { struct E {
#[primary_span] #[primary_span]
@ -71,7 +71,7 @@ struct E {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
#[label = "..."] #[label = "..."]
//~^ ERROR `#[label = ...]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[label = ...]` is not a valid attribute
struct F { struct F {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -80,7 +80,7 @@ struct F {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
#[label(bug = "...")] #[label(bug = "...")]
//~^ ERROR `#[label(bug = ...)]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[label(bug = ...)]` is not a valid attribute
struct G { struct G {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -89,7 +89,7 @@ struct G {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
#[label("...")] #[label("...")]
//~^ ERROR `#[label("...")]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[label("...")]` is not a valid attribute
struct H { struct H {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -98,7 +98,7 @@ struct H {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
#[label(slug = 4)] #[label(slug = 4)]
//~^ ERROR `#[label(slug = ...)]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[label(slug = ...)]` is not a valid attribute
struct J { struct J {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -107,7 +107,7 @@ struct J {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
#[label(slug("..."))] #[label(slug("..."))]
//~^ ERROR `#[label(slug(...))]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[label(slug(...))]` is not a valid attribute
struct K { struct K {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -116,7 +116,7 @@ struct K {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
#[label(slug)] #[label(slug)]
//~^ ERROR `#[label(slug)]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[label(slug)]` is not a valid attribute
struct L { struct L {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -157,7 +157,7 @@ enum O {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
enum P { enum P {
#[bar] #[bar]
//~^ ERROR `#[bar]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[bar]` is not a valid attribute
//~^^ ERROR cannot find attribute `bar` in this scope //~^^ ERROR cannot find attribute `bar` in this scope
A { A {
#[primary_span] #[primary_span]
@ -169,7 +169,7 @@ enum P {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
enum Q { enum Q {
#[bar = "..."] #[bar = "..."]
//~^ ERROR `#[bar = ...]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[bar = ...]` is not a valid attribute
//~^^ ERROR cannot find attribute `bar` in this scope //~^^ ERROR cannot find attribute `bar` in this scope
A { A {
#[primary_span] #[primary_span]
@ -181,7 +181,7 @@ enum Q {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
enum R { enum R {
#[bar = 4] #[bar = 4]
//~^ ERROR `#[bar = ...]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[bar = ...]` is not a valid attribute
//~^^ ERROR cannot find attribute `bar` in this scope //~^^ ERROR cannot find attribute `bar` in this scope
A { A {
#[primary_span] #[primary_span]
@ -193,7 +193,7 @@ enum R {
#[derive(SessionSubdiagnostic)] #[derive(SessionSubdiagnostic)]
enum S { enum S {
#[bar("...")] #[bar("...")]
//~^ ERROR `#[bar("...")]` is not a valid `SessionSubdiagnostic` attribute //~^ ERROR `#[bar("...")]` is not a valid attribute
//~^^ ERROR cannot find attribute `bar` in this scope //~^^ ERROR cannot find attribute `bar` in this scope
A { A {
#[primary_span] #[primary_span]
@ -254,7 +254,7 @@ struct X {
#[primary_span] #[primary_span]
span: Span, span: Span,
#[bar] #[bar]
//~^ ERROR `#[bar]` is not a valid `SessionSubdiagnostic` field attribute //~^ ERROR `#[bar]` is not a valid attribute
//~^^ ERROR cannot find attribute `bar` in this scope //~^^ ERROR cannot find attribute `bar` in this scope
bar: String, bar: String,
} }
@ -265,7 +265,7 @@ struct Y {
#[primary_span] #[primary_span]
span: Span, span: Span,
#[bar = "..."] #[bar = "..."]
//~^ ERROR `#[bar = ...]` is not a valid `SessionSubdiagnostic` field attribute //~^ ERROR `#[bar = ...]` is not a valid attribute
//~^^ ERROR cannot find attribute `bar` in this scope //~^^ ERROR cannot find attribute `bar` in this scope
bar: String, bar: String,
} }
@ -276,7 +276,7 @@ struct Z {
#[primary_span] #[primary_span]
span: Span, span: Span,
#[bar("...")] #[bar("...")]
//~^ ERROR `#[bar(...)]` is not a valid `SessionSubdiagnostic` field attribute //~^ ERROR `#[bar(...)]` is not a valid attribute
//~^^ ERROR cannot find attribute `bar` in this scope //~^^ ERROR cannot find attribute `bar` in this scope
bar: String, bar: String,
} }

View file

@ -8,51 +8,51 @@ LL | | var: String,
LL | | } LL | | }
| |_^ | |_^
error: `#[label]` is not a valid `SessionSubdiagnostic` attribute error: `#[label]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:54:1 --> $DIR/subdiagnostic-derive.rs:54:1
| |
LL | #[label] LL | #[label]
| ^^^^^^^^ | ^^^^^^^^
error: `#[foo]` is not a valid `SessionSubdiagnostic` attribute error: `#[foo]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:63:1 --> $DIR/subdiagnostic-derive.rs:63:1
| |
LL | #[foo] LL | #[foo]
| ^^^^^^ | ^^^^^^
error: `#[label = ...]` is not a valid `SessionSubdiagnostic` attribute error: `#[label = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:73:1 --> $DIR/subdiagnostic-derive.rs:73:1
| |
LL | #[label = "..."] LL | #[label = "..."]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: `#[label(bug = ...)]` is not a valid `SessionSubdiagnostic` attribute error: `#[label(bug = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:82:9 --> $DIR/subdiagnostic-derive.rs:82:9
| |
LL | #[label(bug = "...")] LL | #[label(bug = "...")]
| ^^^^^^^^^^^ | ^^^^^^^^^^^
|
= help: only `code`, `slug` and `applicability` are valid nested attributes
error: `#[label("...")]` is not a valid `SessionSubdiagnostic` attribute error: `#[label("...")]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:91:1 --> $DIR/subdiagnostic-derive.rs:91:9
| |
LL | #[label("...")] LL | #[label("...")]
| ^^^^^^^^^^^^^^^ | ^^^^^
error: `#[label(slug = ...)]` is not a valid `SessionSubdiagnostic` attribute error: `#[label(slug = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:100:9 --> $DIR/subdiagnostic-derive.rs:100:9
| |
LL | #[label(slug = 4)] LL | #[label(slug = 4)]
| ^^^^^^^^ | ^^^^^^^^
|
= help: value must be a string
error: `#[label(slug(...))]` is not a valid `SessionSubdiagnostic` attribute error: `#[label(slug(...))]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:109:9 --> $DIR/subdiagnostic-derive.rs:109:9
| |
LL | #[label(slug("..."))] LL | #[label(slug("..."))]
| ^^^^^^^^^^^ | ^^^^^^^^^^^
error: `#[label(slug)]` is not a valid `SessionSubdiagnostic` attribute error: `#[label(slug)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:118:9 --> $DIR/subdiagnostic-derive.rs:118:9
| |
LL | #[label(slug)] LL | #[label(slug)]
@ -76,29 +76,29 @@ error: unsupported type attribute for subdiagnostic enum
LL | #[foo] LL | #[foo]
| ^^^^^^ | ^^^^^^
error: `#[bar]` is not a valid `SessionSubdiagnostic` attribute error: `#[bar]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:159:5 --> $DIR/subdiagnostic-derive.rs:159:5
| |
LL | #[bar] LL | #[bar]
| ^^^^^^ | ^^^^^^
error: `#[bar = ...]` is not a valid `SessionSubdiagnostic` attribute error: `#[bar = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:171:5 --> $DIR/subdiagnostic-derive.rs:171:5
| |
LL | #[bar = "..."] LL | #[bar = "..."]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: `#[bar = ...]` is not a valid `SessionSubdiagnostic` attribute error: `#[bar = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:183:5 --> $DIR/subdiagnostic-derive.rs:183:5
| |
LL | #[bar = 4] LL | #[bar = 4]
| ^^^^^^^^^^ | ^^^^^^^^^^
error: `#[bar("...")]` is not a valid `SessionSubdiagnostic` attribute error: `#[bar("...")]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:195:5 --> $DIR/subdiagnostic-derive.rs:195:11
| |
LL | #[bar("...")] LL | #[bar("...")]
| ^^^^^^^^^^^^^ | ^^^^^
error: `code` is not a valid nested attribute of a `label` attribute error: `code` is not a valid nested attribute of a `label` attribute
--> $DIR/subdiagnostic-derive.rs:207:5 --> $DIR/subdiagnostic-derive.rs:207:5
@ -136,19 +136,21 @@ error: `#[applicability]` is only valid on suggestions
LL | #[applicability] LL | #[applicability]
| ^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
error: `#[bar]` is not a valid `SessionSubdiagnostic` field attribute error: `#[bar]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:256:5 --> $DIR/subdiagnostic-derive.rs:256:5
| |
LL | #[bar] LL | #[bar]
| ^^^^^^ | ^^^^^^
|
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: `#[bar = ...]` is not a valid `SessionSubdiagnostic` field attribute error: `#[bar = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:267:5 --> $DIR/subdiagnostic-derive.rs:267:5
| |
LL | #[bar = "..."] LL | #[bar = "..."]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: `#[bar(...)]` is not a valid `SessionSubdiagnostic` field attribute error: `#[bar(...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:278:5 --> $DIR/subdiagnostic-derive.rs:278:5
| |
LL | #[bar("...")] LL | #[bar("...")]