mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Extract subdiagnostic attribute parsing
This commit is contained in:
parent
d4a1a6f698
commit
e7251cc441
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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`.
|
||||
|
Loading…
Reference in New Issue
Block a user