Extract subdiagnostic attribute parsing

This commit is contained in:
Xiretza 2022-09-12 20:44:28 +02:00
parent d4a1a6f698
commit e7251cc441
4 changed files with 403 additions and 316 deletions

View File

@ -4,100 +4,16 @@ use crate::diagnostics::error::{
span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError,
};
use crate::diagnostics::utils::{
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span,
Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce,
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo,
FieldInnerTy, HasFieldMap, SetOnce,
};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use std::collections::HashMap;
use std::fmt;
use std::str::FromStr;
use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path};
use synstructure::{BindingInfo, Structure, VariantInfo};
use super::utils::SpannedOption;
/// Which kind of suggestion is being created?
#[derive(Clone, Copy)]
enum SubdiagnosticSuggestionKind {
/// `#[suggestion]`
Normal,
/// `#[suggestion_short]`
Short,
/// `#[suggestion_hidden]`
Hidden,
/// `#[suggestion_verbose]`
Verbose,
}
impl FromStr for SubdiagnosticSuggestionKind {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"" => Ok(SubdiagnosticSuggestionKind::Normal),
"_short" => Ok(SubdiagnosticSuggestionKind::Short),
"_hidden" => Ok(SubdiagnosticSuggestionKind::Hidden),
"_verbose" => Ok(SubdiagnosticSuggestionKind::Verbose),
_ => Err(()),
}
}
}
impl SubdiagnosticSuggestionKind {
pub fn to_suggestion_style(&self) -> TokenStream {
match self {
SubdiagnosticSuggestionKind::Normal => {
quote! { rustc_errors::SuggestionStyle::ShowCode }
}
SubdiagnosticSuggestionKind::Short => {
quote! { rustc_errors::SuggestionStyle::HideCodeInline }
}
SubdiagnosticSuggestionKind::Hidden => {
quote! { rustc_errors::SuggestionStyle::HideCodeAlways }
}
SubdiagnosticSuggestionKind::Verbose => {
quote! { rustc_errors::SuggestionStyle::ShowAlways }
}
}
}
}
/// Which kind of subdiagnostic is being created from a variant?
#[derive(Clone)]
enum SubdiagnosticKind {
/// `#[label(...)]`
Label,
/// `#[note(...)]`
Note,
/// `#[help(...)]`
Help,
/// `#[warning(...)]`
Warn,
/// `#[suggestion{,_short,_hidden,_verbose}]`
Suggestion { suggestion_kind: SubdiagnosticSuggestionKind, code: TokenStream },
/// `#[multipart_suggestion{,_short,_hidden,_verbose}]`
MultipartSuggestion { suggestion_kind: SubdiagnosticSuggestionKind },
}
impl quote::IdentFragment for SubdiagnosticKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SubdiagnosticKind::Label => write!(f, "label"),
SubdiagnosticKind::Note => write!(f, "note"),
SubdiagnosticKind::Help => write!(f, "help"),
SubdiagnosticKind::Warn => write!(f, "warn"),
SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"),
SubdiagnosticKind::MultipartSuggestion { .. } => {
write!(f, "multipart_suggestion_with_style")
}
}
}
fn span(&self) -> Option<proc_macro2::Span> {
None
}
}
use super::utils::{SpannedOption, SubdiagnosticKind};
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
pub(crate) struct SubdiagnosticDerive<'a> {
@ -198,8 +114,8 @@ struct SubdiagnosticDeriveBuilder<'a> {
/// Identifier for the binding to the `#[primary_span]` field.
span_field: SpannedOption<proc_macro2::Ident>,
/// If a suggestion, the identifier for the binding to the `#[applicability]` field or a
/// `rustc_errors::Applicability::*` variant directly.
/// The binding to the `#[applicability]` field, if present.
applicability: SpannedOption<TokenStream>,
/// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
@ -219,6 +135,7 @@ struct KindsStatistics {
has_multipart_suggestion: bool,
all_multipart_suggestions: bool,
has_normal_suggestion: bool,
all_applicabilities_static: bool,
}
impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
@ -227,8 +144,15 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
has_multipart_suggestion: false,
all_multipart_suggestions: true,
has_normal_suggestion: false,
all_applicabilities_static: true,
};
for kind in kinds {
if let SubdiagnosticKind::MultipartSuggestion { applicability: None, .. }
| SubdiagnosticKind::Suggestion { applicability: None, .. } = kind
{
ret.all_applicabilities_static = false;
}
if let SubdiagnosticKind::MultipartSuggestion { .. } = kind {
ret.has_multipart_suggestion = true;
} else {
@ -248,129 +172,14 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
let mut kind_slugs = vec![];
for attr in self.variant.ast().attrs {
let span = attr.span().unwrap();
let (kind, slug) = SubdiagnosticKind::from_attr(attr, self)?;
let name = attr.path.segments.last().unwrap().ident.to_string();
let name = name.as_str();
let Some(slug) = slug else {
let name = attr.path.segments.last().unwrap().ident.to_string();
let name = name.as_str();
let meta = attr.parse_meta()?;
let Meta::List(MetaList { ref nested, .. }) = meta else {
throw_invalid_attr!(attr, &meta);
};
let mut kind = match name {
"label" => SubdiagnosticKind::Label,
"note" => SubdiagnosticKind::Note,
"help" => SubdiagnosticKind::Help,
"warning" => SubdiagnosticKind::Warn,
_ => {
if let Some(suggestion_kind) =
name.strip_prefix("suggestion").and_then(|s| s.parse().ok())
{
SubdiagnosticKind::Suggestion { suggestion_kind, code: TokenStream::new() }
} else if let Some(suggestion_kind) =
name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok())
{
SubdiagnosticKind::MultipartSuggestion { suggestion_kind }
} else {
throw_invalid_attr!(attr, &meta);
}
}
};
let mut slug = None;
let mut code = None;
let mut nested_iter = nested.into_iter();
if let Some(nested_attr) = nested_iter.next() {
match nested_attr {
NestedMeta::Meta(Meta::Path(path)) => {
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 {
NestedMeta::Meta(ref meta) => meta,
_ => throw_invalid_nested_attr!(attr, &nested_attr),
};
let span = meta.span().unwrap();
let nested_name = meta.path().segments.last().unwrap().ident.to_string();
let nested_name = nested_name.as_str();
let value = match meta {
Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value,
Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
diag.help("a diagnostic slug must be the first argument to the attribute")
}),
_ => throw_invalid_nested_attr!(attr, &nested_attr),
};
match nested_name {
"code" => {
if matches!(kind, SubdiagnosticKind::Suggestion { .. }) {
let formatted_str = self.build_format(&value.value(), value.span());
code.set_once(formatted_str, span);
} else {
span_err(
span,
&format!(
"`code` is not a valid nested attribute of a `{}` attribute",
name
),
)
.emit();
}
}
"applicability" => {
if matches!(
kind,
SubdiagnosticKind::Suggestion { .. }
| SubdiagnosticKind::MultipartSuggestion { .. }
) {
let value =
Applicability::from_str(&value.value()).unwrap_or_else(|()| {
span_err(span, "invalid applicability").emit();
Applicability::Unspecified
});
self.applicability.set_once(quote! { #value }, span);
} else {
span_err(
span,
&format!(
"`applicability` is not a valid nested attribute of a `{}` attribute",
name
)
).emit();
}
}
_ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
diag.help("only `code` and `applicability` are valid nested attributes")
}),
}
}
let Some((slug, _)) = slug else {
throw_span_err!(
span,
attr.span().unwrap(),
&format!(
"diagnostic slug must be first argument of a `#[{}(...)]` attribute",
name
@ -378,21 +187,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
);
};
match kind {
SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => {
let Some((code, _)) = code else {
throw_span_err!(span, "suggestion without `code = \"...\"`");
};
*code_field = code;
}
SubdiagnosticKind::Label
| SubdiagnosticKind::Note
| SubdiagnosticKind::Help
| SubdiagnosticKind::Warn
| SubdiagnosticKind::MultipartSuggestion { .. } => {}
}
kind_slugs.push((kind, slug))
kind_slugs.push((kind, slug));
}
Ok(kind_slugs)
@ -510,6 +305,15 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
if kind_stats.has_multipart_suggestion || kind_stats.has_normal_suggestion {
report_error_if_not_applied_to_applicability(attr, &info)?;
if kind_stats.all_applicabilities_static {
span_err(
span,
"`#[applicability]` has no effect if all `#[suggestion]`/\
`#[multipart_suggestion]` attributes have a static \
`applicability = \"...\"`",
)
.emit();
}
let binding = info.binding.binding.clone();
self.applicability.set_once(quote! { #binding }, span);
} else {
@ -638,11 +442,6 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
.collect();
let span_field = self.span_field.value_ref();
let applicability = self
.applicability
.take()
.value()
.unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
let diag = &self.diag;
let mut calls = TokenStream::new();
@ -650,7 +449,13 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
let message = quote! { rustc_errors::fluent::#slug };
let call = match kind {
SubdiagnosticKind::Suggestion { suggestion_kind, code } => {
SubdiagnosticKind::Suggestion { suggestion_kind, applicability, code } => {
let applicability = applicability
.value()
.map(|a| quote! { #a })
.or_else(|| self.applicability.take().value())
.unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
if let Some(span) = span_field {
let style = suggestion_kind.to_suggestion_style();
@ -660,7 +465,13 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
quote! { unreachable!(); }
}
}
SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => {
SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability } => {
let applicability = applicability
.value()
.map(|a| quote! { #a })
.or_else(|| self.applicability.take().value())
.unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
if !self.has_suggestion_parts {
span_err(
self.span,

View File

@ -1,12 +1,18 @@
use crate::diagnostics::error::{span_err, throw_span_err, DiagnosticDeriveError};
use crate::diagnostics::error::{
span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError,
};
use proc_macro::Span;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, ToTokens};
use std::collections::{BTreeSet, HashMap};
use std::fmt;
use std::str::FromStr;
use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple};
use syn::{MetaList, MetaNameValue, NestedMeta, Path};
use synstructure::{BindingInfo, Structure};
use super::error::invalid_nested_attr;
/// Checks whether the type name of `ty` matches `name`.
///
/// Given some struct at `a::b::c::Foo`, this will return true for `c::Foo`, `b::c::Foo`, or
@ -311,6 +317,7 @@ pub(crate) trait HasFieldMap {
/// `Applicability` of a suggestion - mirrors `rustc_errors::Applicability` - and used to represent
/// the user's selection of applicability if specified in an attribute.
#[derive(Clone, Copy)]
pub(crate) enum Applicability {
MachineApplicable,
MaybeIncorrect,
@ -367,3 +374,250 @@ pub(crate) fn build_field_mapping<'a>(structure: &Structure<'a>) -> HashMap<Stri
fields_map
}
/// Possible styles for suggestion subdiagnostics.
#[derive(Clone, Copy)]
pub(super) enum SuggestionKind {
/// `#[suggestion]`
Normal,
/// `#[suggestion_short]`
Short,
/// `#[suggestion_hidden]`
Hidden,
/// `#[suggestion_verbose]`
Verbose,
}
impl FromStr for SuggestionKind {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"" => Ok(SuggestionKind::Normal),
"_short" => Ok(SuggestionKind::Short),
"_hidden" => Ok(SuggestionKind::Hidden),
"_verbose" => Ok(SuggestionKind::Verbose),
_ => Err(()),
}
}
}
impl SuggestionKind {
pub fn to_suggestion_style(&self) -> TokenStream {
match self {
SuggestionKind::Normal => {
quote! { rustc_errors::SuggestionStyle::ShowCode }
}
SuggestionKind::Short => {
quote! { rustc_errors::SuggestionStyle::HideCodeInline }
}
SuggestionKind::Hidden => {
quote! { rustc_errors::SuggestionStyle::HideCodeAlways }
}
SuggestionKind::Verbose => {
quote! { rustc_errors::SuggestionStyle::ShowAlways }
}
}
}
}
/// Types of subdiagnostics that can be created using attributes
#[derive(Clone)]
pub(super) enum SubdiagnosticKind {
/// `#[label(...)]`
Label,
/// `#[note(...)]`
Note,
/// `#[help(...)]`
Help,
/// `#[warning(...)]`
Warn,
/// `#[suggestion{,_short,_hidden,_verbose}]`
Suggestion {
suggestion_kind: SuggestionKind,
applicability: SpannedOption<Applicability>,
code: TokenStream,
},
/// `#[multipart_suggestion{,_short,_hidden,_verbose}]`
MultipartSuggestion {
suggestion_kind: SuggestionKind,
applicability: SpannedOption<Applicability>,
},
}
impl SubdiagnosticKind {
/// Constructs a `SubdiagnosticKind` from a field or type attribute such as `#[note]`,
/// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the
/// `SubdiagnosticKind` and the diagnostic slug, if specified.
pub(super) fn from_attr(
attr: &Attribute,
fields: &impl HasFieldMap,
) -> Result<(SubdiagnosticKind, Option<Path>), DiagnosticDeriveError> {
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()?;
let mut kind = match name {
"label" => SubdiagnosticKind::Label,
"note" => SubdiagnosticKind::Note,
"help" => SubdiagnosticKind::Help,
"warning" => SubdiagnosticKind::Warn,
_ => {
if let Some(suggestion_kind) =
name.strip_prefix("suggestion").and_then(|s| s.parse().ok())
{
SubdiagnosticKind::Suggestion {
suggestion_kind,
applicability: None,
code: TokenStream::new(),
}
} else if let Some(suggestion_kind) =
name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok())
{
SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability: None }
} else {
throw_invalid_attr!(attr, &meta);
}
}
};
let nested = match meta {
Meta::List(MetaList { ref nested, .. }) => {
// An attribute with properties, such as `#[suggestion(code = "...")]` or
// `#[error(some::slug)]`
nested
}
Meta::Path(_) => {
// An attribute without a slug or other properties, such as `#[note]` - return
// without further processing.
//
// Only allow this if there are no mandatory properties, such as `code = "..."` in
// `#[suggestion(...)]`
match kind {
SubdiagnosticKind::Label
| SubdiagnosticKind::Note
| SubdiagnosticKind::Help
| SubdiagnosticKind::Warn
| SubdiagnosticKind::MultipartSuggestion { .. } => return Ok((kind, None)),
SubdiagnosticKind::Suggestion { .. } => {
throw_span_err!(span, "suggestion without `code = \"...\"`")
}
}
}
_ => {
throw_invalid_attr!(attr, &meta)
}
};
let mut code = None;
let mut nested_iter = nested.into_iter().peekable();
// Peek at the first nested attribute: if it's a slug path, consume it.
let slug = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() {
let path = path.clone();
// Advance the iterator.
nested_iter.next();
Some(path)
} else {
None
};
for nested_attr in nested_iter {
let meta = match nested_attr {
NestedMeta::Meta(ref meta) => meta,
NestedMeta::Lit(_) => {
invalid_nested_attr(attr, &nested_attr).emit();
continue;
}
};
let span = meta.span().unwrap();
let nested_name = meta.path().segments.last().unwrap().ident.to_string();
let nested_name = nested_name.as_str();
let value = match meta {
Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value,
Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
diag.help("a diagnostic slug must be the first argument to the attribute")
}),
_ => {
invalid_nested_attr(attr, &nested_attr).emit();
continue;
}
};
match (nested_name, &mut kind) {
("code", SubdiagnosticKind::Suggestion { .. }) => {
let formatted_str = fields.build_format(&value.value(), value.span());
code.set_once(formatted_str, span);
}
(
"applicability",
SubdiagnosticKind::Suggestion { ref mut applicability, .. }
| SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. },
) => {
let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| {
span_err(span, "invalid applicability").emit();
Applicability::Unspecified
});
applicability.set_once(value, span);
}
// Invalid nested attribute
(_, SubdiagnosticKind::Suggestion { .. }) => {
invalid_nested_attr(attr, &nested_attr)
.help("only `code` and `applicability` are valid nested attributes")
.emit();
}
(_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
invalid_nested_attr(attr, &nested_attr)
.help("only `applicability` is a valid nested attributes")
.emit()
}
_ => {
invalid_nested_attr(attr, &nested_attr).emit();
}
}
}
match kind {
SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => {
*code_field = if let Some((code, _)) = code {
code
} else {
span_err(span, "suggestion without `code = \"...\"`").emit();
quote! { "" }
}
}
SubdiagnosticKind::Label
| SubdiagnosticKind::Note
| SubdiagnosticKind::Help
| SubdiagnosticKind::Warn
| SubdiagnosticKind::MultipartSuggestion { .. } => {}
}
Ok((kind, slug))
}
}
impl quote::IdentFragment for SubdiagnosticKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SubdiagnosticKind::Label => write!(f, "label"),
SubdiagnosticKind::Note => write!(f, "note"),
SubdiagnosticKind::Help => write!(f, "help"),
SubdiagnosticKind::Warn => write!(f, "warn"),
SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"),
SubdiagnosticKind::MultipartSuggestion { .. } => {
write!(f, "multipart_suggestion_with_style")
}
}
}
fn span(&self) -> Option<proc_macro2::Span> {
None
}
}

View File

@ -52,7 +52,7 @@ struct C {
#[derive(Subdiagnostic)]
#[label]
//~^ ERROR `#[label]` is not a valid attribute
//~^ ERROR diagnostic slug must be first argument
struct D {
#[primary_span]
span: Span,
@ -81,6 +81,7 @@ struct F {
#[derive(Subdiagnostic)]
#[label(bug = "...")]
//~^ ERROR `#[label(bug = ...)]` is not a valid attribute
//~| ERROR diagnostic slug must be first argument
struct G {
#[primary_span]
span: Span,
@ -90,6 +91,7 @@ struct G {
#[derive(Subdiagnostic)]
#[label("...")]
//~^ ERROR `#[label("...")]` is not a valid attribute
//~| ERROR diagnostic slug must be first argument
struct H {
#[primary_span]
span: Span,
@ -99,6 +101,7 @@ struct H {
#[derive(Subdiagnostic)]
#[label(slug = 4)]
//~^ ERROR `#[label(slug = ...)]` is not a valid attribute
//~| ERROR diagnostic slug must be first argument
struct J {
#[primary_span]
span: Span,
@ -108,6 +111,7 @@ struct J {
#[derive(Subdiagnostic)]
#[label(slug("..."))]
//~^ ERROR `#[label(slug(...))]` is not a valid attribute
//~| ERROR diagnostic slug must be first argument
struct K {
#[primary_span]
span: Span,
@ -135,7 +139,7 @@ struct M {
#[derive(Subdiagnostic)]
#[label(parser::add_paren, code = "...")]
//~^ ERROR `code` is not a valid nested attribute of a `label` attribute
//~^ ERROR `#[label(code = ...)]` is not a valid attribute
struct N {
#[primary_span]
span: Span,
@ -144,7 +148,7 @@ struct N {
#[derive(Subdiagnostic)]
#[label(parser::add_paren, applicability = "machine-applicable")]
//~^ ERROR `applicability` is not a valid nested attribute of a `label` attribute
//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute
struct O {
#[primary_span]
span: Span,
@ -216,6 +220,7 @@ enum T {
enum U {
#[label(code = "...")]
//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
//~| ERROR `#[label(code = ...)]` is not a valid attribute
A {
#[primary_span]
span: Span,
@ -531,7 +536,7 @@ struct BA {
#[derive(Subdiagnostic)]
#[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
//~| ERROR `code` is not a valid nested attribute of a `multipart_suggestion` attribute
//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute
struct BBa {
var: String,
}
@ -612,10 +617,9 @@ struct BG {
#[derive(Subdiagnostic)]
#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
//~^ NOTE previously specified here
struct BH {
#[applicability]
//~^ ERROR specified multiple times
//~^ ERROR `#[applicability]` has no effect
appl: Applicability,
#[suggestion_part(code = "(")]
first: Span,

View File

@ -8,7 +8,7 @@ LL | | var: String,
LL | | }
| |_^
error: `#[label]` is not a valid attribute
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:54:1
|
LL | #[label]
@ -31,101 +31,123 @@ error: `#[label(bug = ...)]` is not a valid attribute
|
LL | #[label(bug = "...")]
| ^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:82:1
|
= help: first argument of the attribute should be the diagnostic slug
LL | #[label(bug = "...")]
| ^^^^^^^^^^^^^^^^^^^^^
error: `#[label("...")]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:91:9
--> $DIR/subdiagnostic-derive.rs:92:9
|
LL | #[label("...")]
| ^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:92:1
|
= help: first argument of the attribute should be the diagnostic slug
LL | #[label("...")]
| ^^^^^^^^^^^^^^^
error: `#[label(slug = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:100:9
--> $DIR/subdiagnostic-derive.rs:102:9
|
LL | #[label(slug = 4)]
| ^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:102:1
|
= help: first argument of the attribute should be the diagnostic slug
LL | #[label(slug = 4)]
| ^^^^^^^^^^^^^^^^^^
error: `#[label(slug(...))]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:109:9
--> $DIR/subdiagnostic-derive.rs:112:9
|
LL | #[label(slug("..."))]
| ^^^^^^^^^^^
|
= help: first argument of the attribute should be the diagnostic slug
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:128:1
--> $DIR/subdiagnostic-derive.rs:112:1
|
LL | #[label(slug("..."))]
| ^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:132:1
|
LL | #[label()]
| ^^^^^^^^^^
error: `code` is not a valid nested attribute of a `label` attribute
--> $DIR/subdiagnostic-derive.rs:137:28
error: `#[label(code = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:141:28
|
LL | #[label(parser::add_paren, code = "...")]
| ^^^^^^^^^^^^
error: `applicability` is not a valid nested attribute of a `label` attribute
--> $DIR/subdiagnostic-derive.rs:146:28
error: `#[label(applicability = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:150:28
|
LL | #[label(parser::add_paren, applicability = "machine-applicable")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: unsupported type attribute for subdiagnostic enum
--> $DIR/subdiagnostic-derive.rs:155:1
--> $DIR/subdiagnostic-derive.rs:159:1
|
LL | #[foo]
| ^^^^^^
error: `#[bar]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:169:5
--> $DIR/subdiagnostic-derive.rs:173:5
|
LL | #[bar]
| ^^^^^^
error: `#[bar = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:181:5
--> $DIR/subdiagnostic-derive.rs:185:5
|
LL | #[bar = "..."]
| ^^^^^^^^^^^^^^
error: `#[bar = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:193:5
--> $DIR/subdiagnostic-derive.rs:197:5
|
LL | #[bar = 4]
| ^^^^^^^^^^
error: `#[bar(...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:205:5
--> $DIR/subdiagnostic-derive.rs:209:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
error: `#[label(code = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:221:13
|
LL | #[label(code = "...")]
| ^^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:217:5
--> $DIR/subdiagnostic-derive.rs:221:5
|
LL | #[label(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^
error: subdiagnostic kind not specified
--> $DIR/subdiagnostic-derive.rs:234:5
--> $DIR/subdiagnostic-derive.rs:239:5
|
LL | B {
| ^
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/subdiagnostic-derive.rs:246:5
--> $DIR/subdiagnostic-derive.rs:251:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: label without `#[primary_span]` field
--> $DIR/subdiagnostic-derive.rs:243:1
--> $DIR/subdiagnostic-derive.rs:248:1
|
LL | / #[label(parser::add_paren)]
LL | |
@ -137,13 +159,13 @@ LL | | }
| |_^
error: `#[applicability]` is only valid on suggestions
--> $DIR/subdiagnostic-derive.rs:256:5
--> $DIR/subdiagnostic-derive.rs:261:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: `#[bar]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:266:5
--> $DIR/subdiagnostic-derive.rs:271:5
|
LL | #[bar]
| ^^^^^^
@ -151,13 +173,13 @@ LL | #[bar]
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: `#[bar = ...]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:277:5
--> $DIR/subdiagnostic-derive.rs:282:5
|
LL | #[bar = "..."]
| ^^^^^^^^^^^^^^
error: `#[bar(...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:288:5
--> $DIR/subdiagnostic-derive.rs:293:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
@ -165,7 +187,7 @@ LL | #[bar("...")]
= help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
error: unexpected unsupported untagged union
--> $DIR/subdiagnostic-derive.rs:304:1
--> $DIR/subdiagnostic-derive.rs:309:1
|
LL | / union AC {
LL | |
@ -175,7 +197,7 @@ LL | | }
| |_^
error: `#[label(parser::add_paren)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:319:28
--> $DIR/subdiagnostic-derive.rs:324:28
|
LL | #[label(parser::add_paren, parser::add_paren)]
| ^^^^^^^^^^^^^^^^^
@ -183,67 +205,67 @@ LL | #[label(parser::add_paren, parser::add_paren)]
= help: a diagnostic slug must be the first argument to the attribute
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:332:5
--> $DIR/subdiagnostic-derive.rs:337:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:329:5
--> $DIR/subdiagnostic-derive.rs:334:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: subdiagnostic kind not specified
--> $DIR/subdiagnostic-derive.rs:338:8
--> $DIR/subdiagnostic-derive.rs:343:8
|
LL | struct AG {
| ^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:375:47
--> $DIR/subdiagnostic-derive.rs:380:47
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
| ^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:375:33
--> $DIR/subdiagnostic-derive.rs:380:33
|
LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
| ^^^^^^^^^^^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:393:5
--> $DIR/subdiagnostic-derive.rs:398:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:390:5
--> $DIR/subdiagnostic-derive.rs:395:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
--> $DIR/subdiagnostic-derive.rs:403:5
--> $DIR/subdiagnostic-derive.rs:408:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: suggestion without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:416:1
--> $DIR/subdiagnostic-derive.rs:421:1
|
LL | #[suggestion(parser::add_paren)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: invalid applicability
--> $DIR/subdiagnostic-derive.rs:426:46
--> $DIR/subdiagnostic-derive.rs:431:46
|
LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
| ^^^^^^^^^^^^^^^^^^^^^
error: suggestion without `#[primary_span]` field
--> $DIR/subdiagnostic-derive.rs:444:1
--> $DIR/subdiagnostic-derive.rs:449:1
|
LL | / #[suggestion(parser::add_paren, code = "...")]
LL | |
@ -253,25 +275,25 @@ LL | | }
| |_^
error: unsupported type attribute for subdiagnostic enum
--> $DIR/subdiagnostic-derive.rs:458:1
--> $DIR/subdiagnostic-derive.rs:463:1
|
LL | #[label]
| ^^^^^^^^
error: `var` doesn't refer to a field on this type
--> $DIR/subdiagnostic-derive.rs:478:39
--> $DIR/subdiagnostic-derive.rs:483:39
|
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:497:43
--> $DIR/subdiagnostic-derive.rs:502:43
|
LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
| ^^^^^^^
error: `#[suggestion_part]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:520:5
--> $DIR/subdiagnostic-derive.rs:525:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
@ -279,7 +301,7 @@ LL | #[suggestion_part]
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
error: `#[suggestion_part(...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:523:5
--> $DIR/subdiagnostic-derive.rs:528:5
|
LL | #[suggestion_part(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -287,7 +309,7 @@ LL | #[suggestion_part(code = "...")]
= help: `#[suggestion_part(...)]` is only valid in multipart suggestions
error: suggestion without `#[primary_span]` field
--> $DIR/subdiagnostic-derive.rs:517:1
--> $DIR/subdiagnostic-derive.rs:522:1
|
LL | / #[suggestion(parser::add_paren, code = "...")]
LL | |
@ -298,14 +320,16 @@ LL | | var: String,
LL | | }
| |_^
error: `code` is not a valid nested attribute of a `multipart_suggestion` attribute
--> $DIR/subdiagnostic-derive.rs:532:43
error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:537:43
|
LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
| ^^^^^^^^^^^^
|
= help: only `applicability` is a valid nested attributes
error: multipart suggestion without any `#[suggestion_part(...)]` fields
--> $DIR/subdiagnostic-derive.rs:532:1
--> $DIR/subdiagnostic-derive.rs:537:1
|
LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
LL | |
@ -316,19 +340,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:542:5
--> $DIR/subdiagnostic-derive.rs:547:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:550:5
--> $DIR/subdiagnostic-derive.rs:555:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[primary_span]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:559:5
--> $DIR/subdiagnostic-derive.rs:564:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
@ -336,7 +360,7 @@ LL | #[primary_span]
= help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
error: multipart suggestion without any `#[suggestion_part(...)]` fields
--> $DIR/subdiagnostic-derive.rs:556:1
--> $DIR/subdiagnostic-derive.rs:561:1
|
LL | / #[multipart_suggestion(parser::add_paren)]
LL | |
@ -348,19 +372,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:567:5
--> $DIR/subdiagnostic-derive.rs:572:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
--> $DIR/subdiagnostic-derive.rs:570:5
--> $DIR/subdiagnostic-derive.rs:575:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(foo = ...)]` is not a valid attribute
--> $DIR/subdiagnostic-derive.rs:573:23
--> $DIR/subdiagnostic-derive.rs:578:23
|
LL | #[suggestion_part(foo = "bar")]
| ^^^^^^^^^^^
@ -368,40 +392,34 @@ LL | #[suggestion_part(foo = "bar")]
= help: `code` is the only valid nested attribute
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/subdiagnostic-derive.rs:576:5
--> $DIR/subdiagnostic-derive.rs:581:5
|
LL | #[suggestion_part(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
--> $DIR/subdiagnostic-derive.rs:579:5
--> $DIR/subdiagnostic-derive.rs:584:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:587:37
--> $DIR/subdiagnostic-derive.rs:592:37
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:587:23
--> $DIR/subdiagnostic-derive.rs:592:23
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
error: specified multiple times
--> $DIR/subdiagnostic-derive.rs:617:5
error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
--> $DIR/subdiagnostic-derive.rs:621:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
|
note: previously specified here
--> $DIR/subdiagnostic-derive.rs:614:43
|
LL | #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: cannot find attribute `foo` in this scope
--> $DIR/subdiagnostic-derive.rs:63:3
@ -410,59 +428,59 @@ LL | #[foo]
| ^^^
error: cannot find attribute `foo` in this scope
--> $DIR/subdiagnostic-derive.rs:155:3
--> $DIR/subdiagnostic-derive.rs:159:3
|
LL | #[foo]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:169:7
--> $DIR/subdiagnostic-derive.rs:173:7
|
LL | #[bar]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:181:7
--> $DIR/subdiagnostic-derive.rs:185:7
|
LL | #[bar = "..."]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:193:7
--> $DIR/subdiagnostic-derive.rs:197:7
|
LL | #[bar = 4]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:205:7
--> $DIR/subdiagnostic-derive.rs:209:7
|
LL | #[bar("...")]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:266:7
--> $DIR/subdiagnostic-derive.rs:271:7
|
LL | #[bar]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:277:7
--> $DIR/subdiagnostic-derive.rs:282:7
|
LL | #[bar = "..."]
| ^^^
error: cannot find attribute `bar` in this scope
--> $DIR/subdiagnostic-derive.rs:288:7
--> $DIR/subdiagnostic-derive.rs:293:7
|
LL | #[bar("...")]
| ^^^
error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
--> $DIR/subdiagnostic-derive.rs:118:9
--> $DIR/subdiagnostic-derive.rs:122:9
|
LL | #[label(slug)]
| ^^^^ not found in `rustc_errors::fluent`
error: aborting due to 63 previous errors
error: aborting due to 68 previous errors
For more information about this error, try `rustc --explain E0425`.