mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
macros: support diagnostic derive on enums
Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
72f4923979
commit
f20c882b8b
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind};
|
use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind};
|
||||||
use crate::diagnostics::error::{span_err, DiagnosticDeriveError};
|
use crate::diagnostics::error::{span_err, DiagnosticDeriveError};
|
||||||
use crate::diagnostics::utils::{build_field_mapping, SetOnce};
|
use crate::diagnostics::utils::SetOnce;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::spanned::Spanned;
|
|
||||||
use synstructure::Structure;
|
use synstructure::Structure;
|
||||||
|
|
||||||
/// The central struct for constructing the `into_diagnostic` method from an annotated struct.
|
/// The central struct for constructing the `into_diagnostic` method from an annotated struct.
|
||||||
@ -18,13 +17,7 @@ pub(crate) struct DiagnosticDerive<'a> {
|
|||||||
impl<'a> DiagnosticDerive<'a> {
|
impl<'a> DiagnosticDerive<'a> {
|
||||||
pub(crate) fn new(diag: syn::Ident, handler: syn::Ident, structure: Structure<'a>) -> Self {
|
pub(crate) fn new(diag: syn::Ident, handler: syn::Ident, structure: Structure<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: DiagnosticDeriveBuilder {
|
builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::Diagnostic },
|
||||||
diag,
|
|
||||||
fields: build_field_mapping(&structure),
|
|
||||||
kind: DiagnosticDeriveKind::Diagnostic,
|
|
||||||
code: None,
|
|
||||||
slug: None,
|
|
||||||
},
|
|
||||||
handler,
|
handler,
|
||||||
structure,
|
structure,
|
||||||
}
|
}
|
||||||
@ -33,20 +26,17 @@ impl<'a> DiagnosticDerive<'a> {
|
|||||||
pub(crate) fn into_tokens(self) -> TokenStream {
|
pub(crate) fn into_tokens(self) -> TokenStream {
|
||||||
let DiagnosticDerive { mut structure, handler, mut builder } = self;
|
let DiagnosticDerive { mut structure, handler, mut builder } = self;
|
||||||
|
|
||||||
let ast = structure.ast();
|
let implementation = builder.each_variant(&mut structure, |mut builder, variant| {
|
||||||
let implementation = {
|
let preamble = builder.preamble(&variant);
|
||||||
if let syn::Data::Struct(..) = ast.data {
|
let body = builder.body(&variant);
|
||||||
let preamble = builder.preamble(&structure);
|
|
||||||
let (attrs, args) = builder.body(&mut structure);
|
|
||||||
|
|
||||||
let span = ast.span().unwrap();
|
let diag = &builder.parent.diag;
|
||||||
let diag = &builder.diag;
|
let init = match builder.slug.value_ref() {
|
||||||
let init = match builder.slug.value() {
|
|
||||||
None => {
|
None => {
|
||||||
span_err(span, "diagnostic slug not specified")
|
span_err(builder.span, "diagnostic slug not specified")
|
||||||
.help(&format!(
|
.help(&format!(
|
||||||
"specify the slug as the first argument to the `#[diag(...)]` attribute, \
|
"specify the slug as the first argument to the `#[diag(...)]` \
|
||||||
such as `#[diag(typeck::example_error)]`",
|
attribute, such as `#[diag(typeck::example_error)]`",
|
||||||
))
|
))
|
||||||
.emit();
|
.emit();
|
||||||
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
|
return DiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||||
@ -61,24 +51,10 @@ impl<'a> DiagnosticDerive<'a> {
|
|||||||
quote! {
|
quote! {
|
||||||
#init
|
#init
|
||||||
#preamble
|
#preamble
|
||||||
match self {
|
#body
|
||||||
#attrs
|
|
||||||
}
|
|
||||||
match self {
|
|
||||||
#args
|
|
||||||
}
|
|
||||||
#diag
|
#diag
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
span_err(
|
|
||||||
ast.span().unwrap(),
|
|
||||||
"`#[derive(Diagnostic)]` can only be used on structs",
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
|
|
||||||
DiagnosticDeriveError::ErrorHandled.to_compile_error()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
structure.gen_impl(quote! {
|
structure.gen_impl(quote! {
|
||||||
gen impl<'__diagnostic_handler_sess, G>
|
gen impl<'__diagnostic_handler_sess, G>
|
||||||
@ -107,13 +83,7 @@ pub(crate) struct LintDiagnosticDerive<'a> {
|
|||||||
impl<'a> LintDiagnosticDerive<'a> {
|
impl<'a> LintDiagnosticDerive<'a> {
|
||||||
pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self {
|
pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
builder: DiagnosticDeriveBuilder {
|
builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::LintDiagnostic },
|
||||||
diag,
|
|
||||||
fields: build_field_mapping(&structure),
|
|
||||||
kind: DiagnosticDeriveKind::LintDiagnostic,
|
|
||||||
code: None,
|
|
||||||
slug: None,
|
|
||||||
},
|
|
||||||
structure,
|
structure,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,17 +91,14 @@ impl<'a> LintDiagnosticDerive<'a> {
|
|||||||
pub(crate) fn into_tokens(self) -> TokenStream {
|
pub(crate) fn into_tokens(self) -> TokenStream {
|
||||||
let LintDiagnosticDerive { mut structure, mut builder } = self;
|
let LintDiagnosticDerive { mut structure, mut builder } = self;
|
||||||
|
|
||||||
let ast = structure.ast();
|
let implementation = builder.each_variant(&mut structure, |mut builder, variant| {
|
||||||
let implementation = {
|
let preamble = builder.preamble(&variant);
|
||||||
if let syn::Data::Struct(..) = ast.data {
|
let body = builder.body(&variant);
|
||||||
let preamble = builder.preamble(&structure);
|
|
||||||
let (attrs, args) = builder.body(&mut structure);
|
|
||||||
|
|
||||||
let diag = &builder.diag;
|
let diag = &builder.parent.diag;
|
||||||
let span = ast.span().unwrap();
|
let init = match builder.slug.value_ref() {
|
||||||
let init = match builder.slug.value() {
|
|
||||||
None => {
|
None => {
|
||||||
span_err(span, "diagnostic slug not specified")
|
span_err(builder.span, "diagnostic slug not specified")
|
||||||
.help(&format!(
|
.help(&format!(
|
||||||
"specify the slug as the first argument to the attribute, such as \
|
"specify the slug as the first argument to the attribute, such as \
|
||||||
`#[diag(typeck::example_error)]`",
|
`#[diag(typeck::example_error)]`",
|
||||||
@ -146,29 +113,13 @@ impl<'a> LintDiagnosticDerive<'a> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let implementation = quote! {
|
quote! {
|
||||||
#init
|
#init
|
||||||
#preamble
|
#preamble
|
||||||
match self {
|
#body
|
||||||
#attrs
|
|
||||||
}
|
|
||||||
match self {
|
|
||||||
#args
|
|
||||||
}
|
|
||||||
#diag.emit();
|
#diag.emit();
|
||||||
};
|
|
||||||
|
|
||||||
implementation
|
|
||||||
} else {
|
|
||||||
span_err(
|
|
||||||
ast.span().unwrap(),
|
|
||||||
"`#[derive(LintDiagnostic)]` can only be used on structs",
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
|
|
||||||
DiagnosticDeriveError::ErrorHandled.to_compile_error()
|
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
let diag = &builder.diag;
|
let diag = &builder.diag;
|
||||||
structure.gen_impl(quote! {
|
structure.gen_impl(quote! {
|
||||||
|
@ -1,22 +1,20 @@
|
|||||||
#![deny(unused_must_use)]
|
#![deny(unused_must_use)]
|
||||||
|
|
||||||
use super::error::throw_invalid_nested_attr;
|
|
||||||
use super::utils::{SpannedOption, SubdiagnosticKind};
|
|
||||||
use crate::diagnostics::error::{
|
use crate::diagnostics::error::{
|
||||||
invalid_nested_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
|
invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
|
||||||
|
DiagnosticDeriveError,
|
||||||
};
|
};
|
||||||
use crate::diagnostics::utils::{
|
use crate::diagnostics::utils::{
|
||||||
report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path,
|
bind_style_of_field, build_field_mapping, report_error_if_not_applied_to_span,
|
||||||
FieldInfo, FieldInnerTy, HasFieldMap, SetOnce,
|
report_type_error, should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo,
|
||||||
|
FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, Span, TokenStream};
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use std::collections::HashMap;
|
|
||||||
use syn::{
|
use syn::{
|
||||||
parse_quote, spanned::Spanned, Attribute, Field, Meta, MetaList, MetaNameValue, NestedMeta,
|
parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type,
|
||||||
Path, Type,
|
|
||||||
};
|
};
|
||||||
use synstructure::{BindingInfo, Structure};
|
use synstructure::{BindingInfo, Structure, VariantInfo};
|
||||||
|
|
||||||
/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
|
/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
@ -25,19 +23,30 @@ pub(crate) enum DiagnosticDeriveKind {
|
|||||||
LintDiagnostic,
|
LintDiagnostic,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tracks persistent information required for building up individual calls to diagnostic methods
|
/// Tracks persistent information required for the entire type when building up individual calls to
|
||||||
/// for generated diagnostic derives - both `Diagnostic` for fatal/errors/warnings and
|
/// diagnostic methods for generated diagnostic derives - both `Diagnostic` for
|
||||||
/// `LintDiagnostic` for lints.
|
/// fatal/errors/warnings and `LintDiagnostic` for lints.
|
||||||
pub(crate) struct DiagnosticDeriveBuilder {
|
pub(crate) struct DiagnosticDeriveBuilder {
|
||||||
/// The identifier to use for the generated `DiagnosticBuilder` instance.
|
/// The identifier to use for the generated `DiagnosticBuilder` instance.
|
||||||
pub diag: syn::Ident,
|
pub diag: syn::Ident,
|
||||||
|
/// Kind of diagnostic that should be derived.
|
||||||
|
pub kind: DiagnosticDeriveKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tracks persistent information required for a specific variant when building up individual calls
|
||||||
|
/// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for
|
||||||
|
/// fatal/errors/warnings and `LintDiagnostic` for lints.
|
||||||
|
pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> {
|
||||||
|
/// The parent builder for the entire type.
|
||||||
|
pub parent: &'parent DiagnosticDeriveBuilder,
|
||||||
|
|
||||||
|
/// Span of the struct or the enum variant.
|
||||||
|
pub span: proc_macro::Span,
|
||||||
|
|
||||||
/// Store a map of field name to its corresponding field. This is built on construction of the
|
/// Store a map of field name to its corresponding field. This is built on construction of the
|
||||||
/// derive builder.
|
/// derive builder.
|
||||||
pub fields: HashMap<String, TokenStream>,
|
pub field_map: FieldMap,
|
||||||
|
|
||||||
/// Kind of diagnostic that should be derived.
|
|
||||||
pub kind: DiagnosticDeriveKind,
|
|
||||||
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
|
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
|
||||||
/// has the actual diagnostic message.
|
/// has the actual diagnostic message.
|
||||||
pub slug: SpannedOption<Path>,
|
pub slug: SpannedOption<Path>,
|
||||||
@ -46,15 +55,82 @@ pub(crate) struct DiagnosticDeriveBuilder {
|
|||||||
pub code: SpannedOption<()>,
|
pub code: SpannedOption<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasFieldMap for DiagnosticDeriveBuilder {
|
impl<'a> HasFieldMap for DiagnosticDeriveVariantBuilder<'a> {
|
||||||
fn get_field_binding(&self, field: &String) -> Option<&TokenStream> {
|
fn get_field_binding(&self, field: &String) -> Option<&TokenStream> {
|
||||||
self.fields.get(field)
|
self.field_map.get(field)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiagnosticDeriveBuilder {
|
impl DiagnosticDeriveBuilder {
|
||||||
pub fn preamble<'s>(&mut self, structure: &Structure<'s>) -> TokenStream {
|
/// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the
|
||||||
|
/// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions
|
||||||
|
/// or attributes on the type itself when input is an enum.
|
||||||
|
pub fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream
|
||||||
|
where
|
||||||
|
F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream,
|
||||||
|
{
|
||||||
let ast = structure.ast();
|
let ast = structure.ast();
|
||||||
|
let span = ast.span().unwrap();
|
||||||
|
match ast.data {
|
||||||
|
syn::Data::Struct(..) | syn::Data::Enum(..) => (),
|
||||||
|
syn::Data::Union(..) => {
|
||||||
|
span_err(span, "diagnostic derives can only be used on structs and enums");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches!(ast.data, syn::Data::Enum(..)) {
|
||||||
|
for attr in &ast.attrs {
|
||||||
|
span_err(
|
||||||
|
attr.span().unwrap(),
|
||||||
|
"unsupported type attribute for diagnostic derive enum",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for variant in structure.variants_mut() {
|
||||||
|
// First, change the binding style of each field based on the code that will be
|
||||||
|
// generated for the field - e.g. `set_arg` calls needs by-move bindings, whereas
|
||||||
|
// `set_primary_span` only needs by-ref.
|
||||||
|
variant.bind_with(|bi| bind_style_of_field(bi.ast()).0);
|
||||||
|
|
||||||
|
// Then, perform a stable sort on bindings which generates code for by-ref bindings
|
||||||
|
// before code generated for by-move bindings. Any code generated for the by-ref
|
||||||
|
// bindings which creates a reference to the by-move fields will happen before the
|
||||||
|
// by-move bindings move those fields and make them inaccessible.
|
||||||
|
variant.bindings_mut().sort_by_cached_key(|bi| bind_style_of_field(bi.ast()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let variants = structure.each_variant(|variant| {
|
||||||
|
let span = match structure.ast().data {
|
||||||
|
syn::Data::Struct(..) => span,
|
||||||
|
// There isn't a good way to get the span of the variant, so the variant's
|
||||||
|
// name will need to do.
|
||||||
|
_ => variant.ast().ident.span().unwrap(),
|
||||||
|
};
|
||||||
|
let builder = DiagnosticDeriveVariantBuilder {
|
||||||
|
parent: &self,
|
||||||
|
span,
|
||||||
|
field_map: build_field_mapping(variant),
|
||||||
|
slug: None,
|
||||||
|
code: None,
|
||||||
|
};
|
||||||
|
f(builder, variant)
|
||||||
|
});
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
match self {
|
||||||
|
#variants
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
||||||
|
/// Generates calls to `code` and similar functions based on the attributes on the type or
|
||||||
|
/// variant.
|
||||||
|
pub fn preamble<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream {
|
||||||
|
let ast = variant.ast();
|
||||||
let attrs = &ast.attrs;
|
let attrs = &ast.attrs;
|
||||||
let preamble = attrs.iter().map(|attr| {
|
let preamble = attrs.iter().map(|attr| {
|
||||||
self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error())
|
self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error())
|
||||||
@ -65,68 +141,24 @@ impl DiagnosticDeriveBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn body<'s>(&mut self, structure: &mut Structure<'s>) -> (TokenStream, TokenStream) {
|
/// Generates calls to `span_label` and similar functions based on the attributes on fields or
|
||||||
// Keep track of which fields need to be handled with a by-move binding.
|
/// calls to `set_arg` when no attributes are present.
|
||||||
let mut needs_moved = std::collections::HashSet::new();
|
///
|
||||||
|
/// Expects use of `Self::each_variant` which will have sorted bindings so that by-ref bindings
|
||||||
// Generates calls to `span_label` and similar functions based on the attributes
|
/// (which may create references to by-move bindings) have their code generated first -
|
||||||
// on fields. Code for suggestions uses formatting machinery and the value of
|
/// necessary as code for suggestions uses formatting machinery and the value of other fields
|
||||||
// other fields - because any given field can be referenced multiple times, it
|
/// (any given field can be referenced multiple times, so must be accessed through a borrow);
|
||||||
// should be accessed through a borrow. When passing fields to `add_subdiagnostic`
|
/// and when passing fields to `add_subdiagnostic` or `set_arg` for Fluent, fields must be
|
||||||
// or `set_arg` (which happens below) for Fluent, we want to move the data, so that
|
/// accessed by-move.
|
||||||
// has to happen in a separate pass over the fields.
|
pub fn body<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream {
|
||||||
let attrs = structure
|
let mut body = quote! {};
|
||||||
.clone()
|
for binding in variant.bindings() {
|
||||||
.filter(|field_binding| {
|
body.extend(self.generate_field_attrs_code(binding));
|
||||||
let ast = &field_binding.ast();
|
|
||||||
!self.needs_move(ast) || {
|
|
||||||
needs_moved.insert(field_binding.binding.clone());
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
})
|
body
|
||||||
.each(|field_binding| self.generate_field_attrs_code(field_binding));
|
|
||||||
|
|
||||||
structure.bind_with(|_| synstructure::BindStyle::Move);
|
|
||||||
// When a field has attributes like `#[label]` or `#[note]` then it doesn't
|
|
||||||
// need to be passed as an argument to the diagnostic. But when a field has no
|
|
||||||
// attributes or a `#[subdiagnostic]` attribute then it must be passed as an
|
|
||||||
// argument to the diagnostic so that it can be referred to by Fluent messages.
|
|
||||||
let args = structure
|
|
||||||
.filter(|field_binding| needs_moved.contains(&field_binding.binding))
|
|
||||||
.each(|field_binding| self.generate_field_attrs_code(field_binding));
|
|
||||||
|
|
||||||
(attrs, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic
|
|
||||||
/// call (like `span_label`).
|
|
||||||
fn should_generate_set_arg(&self, field: &Field) -> bool {
|
|
||||||
field.attrs.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if `field` needs to have code generated in the by-move branch of the
|
|
||||||
/// generated derive rather than the by-ref branch.
|
|
||||||
fn needs_move(&self, field: &Field) -> bool {
|
|
||||||
let generates_set_arg = self.should_generate_set_arg(field);
|
|
||||||
let is_multispan = type_matches_path(&field.ty, &["rustc_errors", "MultiSpan"]);
|
|
||||||
// FIXME(davidtwco): better support for one field needing to be in the by-move and
|
|
||||||
// by-ref branches.
|
|
||||||
let is_subdiagnostic = field
|
|
||||||
.attrs
|
|
||||||
.iter()
|
|
||||||
.map(|attr| attr.path.segments.last().unwrap().ident.to_string())
|
|
||||||
.any(|attr| attr == "subdiagnostic");
|
|
||||||
|
|
||||||
// `set_arg` calls take their argument by-move..
|
|
||||||
generates_set_arg
|
|
||||||
// If this is a `MultiSpan` field then it needs to be moved to be used by any
|
|
||||||
// attribute..
|
|
||||||
|| is_multispan
|
|
||||||
// If this a `#[subdiagnostic]` then it needs to be moved as the other diagnostic is
|
|
||||||
// unlikely to be `Copy`..
|
|
||||||
|| is_subdiagnostic
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a `SubdiagnosticKind` from an `Attribute`.
|
||||||
fn parse_subdiag_attribute(
|
fn parse_subdiag_attribute(
|
||||||
&self,
|
&self,
|
||||||
attr: &Attribute,
|
attr: &Attribute,
|
||||||
@ -158,7 +190,7 @@ impl DiagnosticDeriveBuilder {
|
|||||||
&mut self,
|
&mut self,
|
||||||
attr: &Attribute,
|
attr: &Attribute,
|
||||||
) -> Result<TokenStream, DiagnosticDeriveError> {
|
) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||||
let diag = &self.diag;
|
let diag = &self.parent.diag;
|
||||||
|
|
||||||
let name = attr.path.segments.last().unwrap().ident.to_string();
|
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||||
let name = name.as_str();
|
let name = name.as_str();
|
||||||
@ -246,8 +278,8 @@ impl DiagnosticDeriveBuilder {
|
|||||||
let field = binding_info.ast();
|
let field = binding_info.ast();
|
||||||
let field_binding = &binding_info.binding;
|
let field_binding = &binding_info.binding;
|
||||||
|
|
||||||
if self.should_generate_set_arg(&field) {
|
if should_generate_set_arg(&field) {
|
||||||
let diag = &self.diag;
|
let diag = &self.parent.diag;
|
||||||
let ident = field.ident.as_ref().unwrap();
|
let ident = field.ident.as_ref().unwrap();
|
||||||
return quote! {
|
return quote! {
|
||||||
#diag.set_arg(
|
#diag.set_arg(
|
||||||
@ -257,7 +289,7 @@ impl DiagnosticDeriveBuilder {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let needs_move = self.needs_move(&field);
|
let needs_move = bind_style_of_field(&field).is_move();
|
||||||
let inner_ty = FieldInnerTy::from_type(&field.ty);
|
let inner_ty = FieldInnerTy::from_type(&field.ty);
|
||||||
|
|
||||||
field
|
field
|
||||||
@ -303,7 +335,7 @@ impl DiagnosticDeriveBuilder {
|
|||||||
info: FieldInfo<'_>,
|
info: FieldInfo<'_>,
|
||||||
binding: TokenStream,
|
binding: TokenStream,
|
||||||
) -> Result<TokenStream, DiagnosticDeriveError> {
|
) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||||
let diag = &self.diag;
|
let diag = &self.parent.diag;
|
||||||
let meta = attr.parse_meta()?;
|
let meta = attr.parse_meta()?;
|
||||||
|
|
||||||
if let Meta::Path(_) = meta {
|
if let Meta::Path(_) = meta {
|
||||||
@ -316,7 +348,7 @@ impl DiagnosticDeriveBuilder {
|
|||||||
// `set_arg` call will not be generated.
|
// `set_arg` call will not be generated.
|
||||||
return Ok(quote! {});
|
return Ok(quote! {});
|
||||||
}
|
}
|
||||||
"primary_span" => match self.kind {
|
"primary_span" => match self.parent.kind {
|
||||||
DiagnosticDeriveKind::Diagnostic => {
|
DiagnosticDeriveKind::Diagnostic => {
|
||||||
report_error_if_not_applied_to_span(attr, &info)?;
|
report_error_if_not_applied_to_span(attr, &info)?;
|
||||||
|
|
||||||
@ -390,7 +422,7 @@ impl DiagnosticDeriveBuilder {
|
|||||||
kind: &Ident,
|
kind: &Ident,
|
||||||
fluent_attr_identifier: Path,
|
fluent_attr_identifier: Path,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let diag = &self.diag;
|
let diag = &self.parent.diag;
|
||||||
let fn_name = format_ident!("span_{}", kind);
|
let fn_name = format_ident!("span_{}", kind);
|
||||||
quote! {
|
quote! {
|
||||||
#diag.#fn_name(
|
#diag.#fn_name(
|
||||||
@ -403,7 +435,7 @@ impl DiagnosticDeriveBuilder {
|
|||||||
/// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug
|
/// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug
|
||||||
/// and `fluent_attr_identifier`.
|
/// and `fluent_attr_identifier`.
|
||||||
fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream {
|
fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream {
|
||||||
let diag = &self.diag;
|
let diag = &self.parent.diag;
|
||||||
quote! {
|
quote! {
|
||||||
#diag.#kind(rustc_errors::fluent::#fluent_attr_identifier);
|
#diag.#kind(rustc_errors::fluent::#fluent_attr_identifier);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
#![deny(unused_must_use)]
|
#![deny(unused_must_use)]
|
||||||
|
|
||||||
use crate::diagnostics::error::{
|
use crate::diagnostics::error::{
|
||||||
span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError,
|
invalid_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
|
||||||
|
DiagnosticDeriveError,
|
||||||
};
|
};
|
||||||
use crate::diagnostics::utils::{
|
use crate::diagnostics::utils::{
|
||||||
report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo,
|
build_field_mapping, report_error_if_not_applied_to_applicability,
|
||||||
FieldInnerTy, HasFieldMap, SetOnce,
|
report_error_if_not_applied_to_span, FieldInfo, FieldInnerTy, FieldMap, HasFieldMap, SetOnce,
|
||||||
|
SpannedOption, SubdiagnosticKind,
|
||||||
};
|
};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use std::collections::HashMap;
|
|
||||||
use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path};
|
use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path};
|
||||||
use synstructure::{BindingInfo, Structure, VariantInfo};
|
use synstructure::{BindingInfo, Structure, VariantInfo};
|
||||||
|
|
||||||
use super::error::invalid_attr;
|
|
||||||
use super::utils::{SpannedOption, SubdiagnosticKind};
|
|
||||||
|
|
||||||
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
|
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
|
||||||
pub(crate) struct SubdiagnosticDerive<'a> {
|
pub(crate) struct SubdiagnosticDerive<'a> {
|
||||||
structure: Structure<'a>,
|
structure: Structure<'a>,
|
||||||
@ -55,21 +53,11 @@ impl<'a> SubdiagnosticDerive<'a> {
|
|||||||
|
|
||||||
structure.bind_with(|_| synstructure::BindStyle::Move);
|
structure.bind_with(|_| synstructure::BindStyle::Move);
|
||||||
let variants_ = structure.each_variant(|variant| {
|
let variants_ = structure.each_variant(|variant| {
|
||||||
// Build the mapping of field names to fields. This allows attributes to peek
|
|
||||||
// values from other fields.
|
|
||||||
let mut fields_map = HashMap::new();
|
|
||||||
for binding in variant.bindings() {
|
|
||||||
let field = binding.ast();
|
|
||||||
if let Some(ident) = &field.ident {
|
|
||||||
fields_map.insert(ident.to_string(), quote! { #binding });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut builder = SubdiagnosticDeriveBuilder {
|
let mut builder = SubdiagnosticDeriveBuilder {
|
||||||
diag: &diag,
|
diag: &diag,
|
||||||
variant,
|
variant,
|
||||||
span,
|
span,
|
||||||
fields: fields_map,
|
fields: build_field_mapping(variant),
|
||||||
span_field: None,
|
span_field: None,
|
||||||
applicability: None,
|
applicability: None,
|
||||||
has_suggestion_parts: false,
|
has_suggestion_parts: false,
|
||||||
@ -111,7 +99,7 @@ struct SubdiagnosticDeriveBuilder<'a> {
|
|||||||
|
|
||||||
/// Store a map of field name to its corresponding field. This is built on construction of the
|
/// Store a map of field name to its corresponding field. This is built on construction of the
|
||||||
/// derive builder.
|
/// derive builder.
|
||||||
fields: HashMap<String, TokenStream>,
|
fields: FieldMap,
|
||||||
|
|
||||||
/// Identifier for the binding to the `#[primary_span]` field.
|
/// Identifier for the binding to the `#[primary_span]` field.
|
||||||
span_field: SpannedOption<proc_macro2::Ident>,
|
span_field: SpannedOption<proc_macro2::Ident>,
|
||||||
|
@ -4,12 +4,13 @@ use crate::diagnostics::error::{
|
|||||||
use proc_macro::Span;
|
use proc_macro::Span;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote, ToTokens};
|
use quote::{format_ident, quote, ToTokens};
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::collections::{BTreeSet, HashMap};
|
use std::collections::{BTreeSet, HashMap};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple};
|
use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple};
|
||||||
use syn::{MetaList, MetaNameValue, NestedMeta, Path};
|
use syn::{MetaList, MetaNameValue, NestedMeta, Path};
|
||||||
use synstructure::{BindingInfo, Structure};
|
use synstructure::{BindStyle, BindingInfo, VariantInfo};
|
||||||
|
|
||||||
use super::error::invalid_nested_attr;
|
use super::error::invalid_nested_attr;
|
||||||
|
|
||||||
@ -210,6 +211,8 @@ impl<T> SetOnce<T> for SpannedOption<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) type FieldMap = HashMap<String, TokenStream>;
|
||||||
|
|
||||||
pub(crate) trait HasFieldMap {
|
pub(crate) trait HasFieldMap {
|
||||||
/// Returns the binding for the field with the given name, if it exists on the type.
|
/// Returns the binding for the field with the given name, if it exists on the type.
|
||||||
fn get_field_binding(&self, field: &String) -> Option<&TokenStream>;
|
fn get_field_binding(&self, field: &String) -> Option<&TokenStream>;
|
||||||
@ -360,18 +363,13 @@ impl quote::ToTokens for Applicability {
|
|||||||
|
|
||||||
/// Build the mapping of field names to fields. This allows attributes to peek values from
|
/// Build the mapping of field names to fields. This allows attributes to peek values from
|
||||||
/// other fields.
|
/// other fields.
|
||||||
pub(crate) fn build_field_mapping<'a>(structure: &Structure<'a>) -> HashMap<String, TokenStream> {
|
pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap<String, TokenStream> {
|
||||||
let mut fields_map = HashMap::new();
|
let mut fields_map = FieldMap::new();
|
||||||
|
for binding in variant.bindings() {
|
||||||
let ast = structure.ast();
|
if let Some(ident) = &binding.ast().ident {
|
||||||
if let syn::Data::Struct(syn::DataStruct { fields, .. }) = &ast.data {
|
fields_map.insert(ident.to_string(), quote! { #binding });
|
||||||
for field in fields.iter() {
|
|
||||||
if let Some(ident) = &field.ident {
|
|
||||||
fields_map.insert(ident.to_string(), quote! { &self.#ident });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fields_map
|
fields_map
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,3 +619,66 @@ impl quote::IdentFragment for SubdiagnosticKind {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrapper around `synstructure::BindStyle` which implements `Ord`.
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
pub(super) struct OrderedBindStyle(pub(super) BindStyle);
|
||||||
|
|
||||||
|
impl OrderedBindStyle {
|
||||||
|
/// Is `BindStyle::Move` or `BindStyle::MoveMut`?
|
||||||
|
pub(super) fn is_move(&self) -> bool {
|
||||||
|
matches!(self.0, BindStyle::Move | BindStyle::MoveMut)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for OrderedBindStyle {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
match (self.is_move(), other.is_move()) {
|
||||||
|
// If both `self` and `other` are the same, then ordering is equal.
|
||||||
|
(true, true) | (false, false) => Ordering::Equal,
|
||||||
|
// If `self` is not a move then it should be considered less than `other` (so that
|
||||||
|
// references are sorted first).
|
||||||
|
(false, _) => Ordering::Less,
|
||||||
|
// If `self` is a move then it must be greater than `other` (again, so that references
|
||||||
|
// are sorted first).
|
||||||
|
(true, _) => Ordering::Greater,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for OrderedBindStyle {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic
|
||||||
|
/// call (like `span_label`).
|
||||||
|
pub(super) fn should_generate_set_arg(field: &Field) -> bool {
|
||||||
|
field.attrs.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `field` needs to have code generated in the by-move branch of the
|
||||||
|
/// generated derive rather than the by-ref branch.
|
||||||
|
pub(super) fn bind_style_of_field(field: &Field) -> OrderedBindStyle {
|
||||||
|
let generates_set_arg = should_generate_set_arg(field);
|
||||||
|
let is_multispan = type_matches_path(&field.ty, &["rustc_errors", "MultiSpan"]);
|
||||||
|
// FIXME(davidtwco): better support for one field needing to be in the by-move and
|
||||||
|
// by-ref branches.
|
||||||
|
let is_subdiagnostic = field
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.map(|attr| attr.path.segments.last().unwrap().ident.to_string())
|
||||||
|
.any(|attr| attr == "subdiagnostic");
|
||||||
|
|
||||||
|
// `set_arg` calls take their argument by-move..
|
||||||
|
let needs_move = generates_set_arg
|
||||||
|
// If this is a `MultiSpan` field then it needs to be moved to be used by any
|
||||||
|
// attribute..
|
||||||
|
|| is_multispan
|
||||||
|
// If this a `#[subdiagnostic]` then it needs to be moved as the other diagnostic is
|
||||||
|
// unlikely to be `Copy`..
|
||||||
|
|| is_subdiagnostic;
|
||||||
|
|
||||||
|
OrderedBindStyle(if needs_move { BindStyle::Move } else { BindStyle::Ref })
|
||||||
|
}
|
||||||
|
@ -37,10 +37,12 @@ struct HelloWarn {}
|
|||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
//~^ ERROR `#[derive(Diagnostic)]` can only be used on structs
|
//~^ ERROR unsupported type attribute for diagnostic derive enum
|
||||||
enum DiagnosticOnEnum {
|
enum DiagnosticOnEnum {
|
||||||
Foo,
|
Foo,
|
||||||
|
//~^ ERROR diagnostic slug not specified
|
||||||
Bar,
|
Bar,
|
||||||
|
//~^ ERROR diagnostic slug not specified
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
@ -651,3 +653,21 @@ struct LabelOnStruct {
|
|||||||
#[primary_span]
|
#[primary_span]
|
||||||
suggestion: Span,
|
suggestion: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
enum ExampleEnum {
|
||||||
|
#[diag(typeck::ambiguous_lifetime_bound)]
|
||||||
|
Foo {
|
||||||
|
#[primary_span]
|
||||||
|
sp: Span,
|
||||||
|
#[note]
|
||||||
|
note_sp: Span,
|
||||||
|
},
|
||||||
|
#[diag(typeck::ambiguous_lifetime_bound)]
|
||||||
|
Bar {
|
||||||
|
#[primary_span]
|
||||||
|
sp: Span,
|
||||||
|
},
|
||||||
|
#[diag(typeck::ambiguous_lifetime_bound)]
|
||||||
|
Baz,
|
||||||
|
}
|
||||||
|
@ -1,28 +1,39 @@
|
|||||||
error: `#[derive(Diagnostic)]` can only be used on structs
|
error: unsupported type attribute for diagnostic derive enum
|
||||||
--> $DIR/diagnostic-derive.rs:39:1
|
--> $DIR/diagnostic-derive.rs:39:1
|
||||||
|
|
|
|
||||||
LL | / #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
LL | |
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
LL | | enum DiagnosticOnEnum {
|
|
||||||
LL | | Foo,
|
error: diagnostic slug not specified
|
||||||
LL | | Bar,
|
--> $DIR/diagnostic-derive.rs:42:5
|
||||||
LL | | }
|
|
|
||||||
| |_^
|
LL | Foo,
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
|
error: diagnostic slug not specified
|
||||||
|
--> $DIR/diagnostic-derive.rs:44:5
|
||||||
|
|
|
||||||
|
LL | Bar,
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[diag = ...]` is not a valid attribute
|
error: `#[diag = ...]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:48:1
|
--> $DIR/diagnostic-derive.rs:50:1
|
||||||
|
|
|
|
||||||
LL | #[diag = "E0123"]
|
LL | #[diag = "E0123"]
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[nonsense(...)]` is not a valid attribute
|
error: `#[nonsense(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:53:1
|
--> $DIR/diagnostic-derive.rs:55:1
|
||||||
|
|
|
|
||||||
LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:53:1
|
--> $DIR/diagnostic-derive.rs:55:1
|
||||||
|
|
|
|
||||||
LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -34,7 +45,7 @@ LL | | struct InvalidStructAttr {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[diag("...")]` is not a valid attribute
|
error: `#[diag("...")]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:60:8
|
--> $DIR/diagnostic-derive.rs:62:8
|
||||||
|
|
|
|
||||||
LL | #[diag("E0123")]
|
LL | #[diag("E0123")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@ -42,7 +53,7 @@ LL | #[diag("E0123")]
|
|||||||
= help: a diagnostic slug is required as the first argument
|
= help: a diagnostic slug is required as the first argument
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:60:1
|
--> $DIR/diagnostic-derive.rs:62:1
|
||||||
|
|
|
|
||||||
LL | / #[diag("E0123")]
|
LL | / #[diag("E0123")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -53,7 +64,7 @@ LL | | struct InvalidLitNestedAttr {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[diag(nonsense(...))]` is not a valid attribute
|
error: `#[diag(nonsense(...))]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:71:8
|
--> $DIR/diagnostic-derive.rs:73:8
|
||||||
|
|
|
|
||||||
LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
|
LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
@ -61,7 +72,7 @@ LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
|
|||||||
= help: a diagnostic slug is required as the first argument
|
= help: a diagnostic slug is required as the first argument
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:71:1
|
--> $DIR/diagnostic-derive.rs:73:1
|
||||||
|
|
|
|
||||||
LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
|
LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -72,7 +83,7 @@ LL | | struct InvalidNestedStructAttr1 {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[diag(nonsense = ...)]` is not a valid attribute
|
error: `#[diag(nonsense = ...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:77:8
|
--> $DIR/diagnostic-derive.rs:79:8
|
||||||
|
|
|
|
||||||
LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
|
LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
@ -80,7 +91,7 @@ LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
|
|||||||
= help: only `code` is a valid nested attributes following the slug
|
= help: only `code` is a valid nested attributes following the slug
|
||||||
|
|
||||||
error: `#[diag(slug = ...)]` is not a valid attribute
|
error: `#[diag(slug = ...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:77:42
|
--> $DIR/diagnostic-derive.rs:79:42
|
||||||
|
|
|
|
||||||
LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
|
LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
@ -88,7 +99,7 @@ LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
|
|||||||
= help: only `code` is a valid nested attributes following the slug
|
= help: only `code` is a valid nested attributes following the slug
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:77:1
|
--> $DIR/diagnostic-derive.rs:79:1
|
||||||
|
|
|
|
||||||
LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
|
LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -100,13 +111,13 @@ LL | | struct InvalidNestedStructAttr2 {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[diag(nonsense = ...)]` is not a valid attribute
|
error: `#[diag(nonsense = ...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:84:8
|
--> $DIR/diagnostic-derive.rs:86:8
|
||||||
|
|
|
|
||||||
LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
|
LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[diag(slug = ...)]` is not a valid attribute
|
error: `#[diag(slug = ...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:84:38
|
--> $DIR/diagnostic-derive.rs:86:38
|
||||||
|
|
|
|
||||||
LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
|
LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
@ -114,7 +125,7 @@ LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
|
|||||||
= help: only `code` is a valid nested attributes following the slug
|
= help: only `code` is a valid nested attributes following the slug
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:84:1
|
--> $DIR/diagnostic-derive.rs:86:1
|
||||||
|
|
|
|
||||||
LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
|
LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -126,7 +137,7 @@ LL | | struct InvalidNestedStructAttr3 {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[diag(slug = ...)]` is not a valid attribute
|
error: `#[diag(slug = ...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:91:58
|
--> $DIR/diagnostic-derive.rs:93:58
|
||||||
|
|
|
|
||||||
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
@ -134,49 +145,49 @@ LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
|
|||||||
= help: only `code` is a valid nested attributes following the slug
|
= help: only `code` is a valid nested attributes following the slug
|
||||||
|
|
||||||
error: `#[suggestion = ...]` is not a valid attribute
|
error: `#[suggestion = ...]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:98:5
|
--> $DIR/diagnostic-derive.rs:100:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion = "bar"]
|
LL | #[suggestion = "bar"]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/diagnostic-derive.rs:105:8
|
--> $DIR/diagnostic-derive.rs:107:8
|
||||||
|
|
|
|
||||||
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/diagnostic-derive.rs:104:8
|
--> $DIR/diagnostic-derive.rs:106:8
|
||||||
|
|
|
|
||||||
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/diagnostic-derive.rs:105:49
|
--> $DIR/diagnostic-derive.rs:107:49
|
||||||
|
|
|
|
||||||
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/diagnostic-derive.rs:104:49
|
--> $DIR/diagnostic-derive.rs:106:49
|
||||||
|
|
|
|
||||||
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/diagnostic-derive.rs:111:65
|
--> $DIR/diagnostic-derive.rs:113:65
|
||||||
|
|
|
|
||||||
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/diagnostic-derive.rs:111:49
|
--> $DIR/diagnostic-derive.rs:113:49
|
||||||
|
|
|
|
||||||
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
|
error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:116:42
|
--> $DIR/diagnostic-derive.rs:118:42
|
||||||
|
|
|
|
||||||
LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
|
LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -184,7 +195,7 @@ LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound,
|
|||||||
= help: diagnostic slug must be the first argument
|
= help: diagnostic slug must be the first argument
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:121:1
|
--> $DIR/diagnostic-derive.rs:123:1
|
||||||
|
|
|
|
||||||
LL | struct KindNotProvided {}
|
LL | struct KindNotProvided {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -192,7 +203,7 @@ LL | struct KindNotProvided {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:124:1
|
--> $DIR/diagnostic-derive.rs:126:1
|
||||||
|
|
|
|
||||||
LL | / #[diag(code = "E0456")]
|
LL | / #[diag(code = "E0456")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -202,31 +213,31 @@ LL | | struct SlugNotProvided {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
||||||
--> $DIR/diagnostic-derive.rs:135:5
|
--> $DIR/diagnostic-derive.rs:137:5
|
||||||
|
|
|
|
||||||
LL | #[primary_span]
|
LL | #[primary_span]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[nonsense]` is not a valid attribute
|
error: `#[nonsense]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:143:5
|
--> $DIR/diagnostic-derive.rs:145:5
|
||||||
|
|
|
|
||||||
LL | #[nonsense]
|
LL | #[nonsense]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
||||||
--> $DIR/diagnostic-derive.rs:160:5
|
--> $DIR/diagnostic-derive.rs:162:5
|
||||||
|
|
|
|
||||||
LL | #[label(typeck::label)]
|
LL | #[label(typeck::label)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `name` doesn't refer to a field on this type
|
error: `name` doesn't refer to a field on this type
|
||||||
--> $DIR/diagnostic-derive.rs:168:45
|
--> $DIR/diagnostic-derive.rs:170:45
|
||||||
|
|
|
|
||||||
LL | #[suggestion(typeck::suggestion, code = "{name}")]
|
LL | #[suggestion(typeck::suggestion, code = "{name}")]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: invalid format string: expected `'}'` but string was terminated
|
error: invalid format string: expected `'}'` but string was terminated
|
||||||
--> $DIR/diagnostic-derive.rs:173:16
|
--> $DIR/diagnostic-derive.rs:175:16
|
||||||
|
|
|
|
||||||
LL | #[derive(Diagnostic)]
|
LL | #[derive(Diagnostic)]
|
||||||
| - ^ expected `'}'` in format string
|
| - ^ expected `'}'` in format string
|
||||||
@ -237,7 +248,7 @@ LL | #[derive(Diagnostic)]
|
|||||||
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: invalid format string: unmatched `}` found
|
error: invalid format string: unmatched `}` found
|
||||||
--> $DIR/diagnostic-derive.rs:183:15
|
--> $DIR/diagnostic-derive.rs:185:15
|
||||||
|
|
|
|
||||||
LL | #[derive(Diagnostic)]
|
LL | #[derive(Diagnostic)]
|
||||||
| ^ unmatched `}` in format string
|
| ^ unmatched `}` in format string
|
||||||
@ -246,19 +257,19 @@ LL | #[derive(Diagnostic)]
|
|||||||
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
|
||||||
--> $DIR/diagnostic-derive.rs:203:5
|
--> $DIR/diagnostic-derive.rs:205:5
|
||||||
|
|
|
|
||||||
LL | #[label(typeck::label)]
|
LL | #[label(typeck::label)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: suggestion without `code = "..."`
|
error: suggestion without `code = "..."`
|
||||||
--> $DIR/diagnostic-derive.rs:221:5
|
--> $DIR/diagnostic-derive.rs:223:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion(typeck::suggestion)]
|
LL | #[suggestion(typeck::suggestion)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[suggestion(nonsense = ...)]` is not a valid attribute
|
error: `#[suggestion(nonsense = ...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:229:18
|
--> $DIR/diagnostic-derive.rs:231:18
|
||||||
|
|
|
|
||||||
LL | #[suggestion(nonsense = "bar")]
|
LL | #[suggestion(nonsense = "bar")]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
@ -266,13 +277,13 @@ LL | #[suggestion(nonsense = "bar")]
|
|||||||
= help: only `code` and `applicability` are valid nested attributes
|
= help: only `code` and `applicability` are valid nested attributes
|
||||||
|
|
||||||
error: suggestion without `code = "..."`
|
error: suggestion without `code = "..."`
|
||||||
--> $DIR/diagnostic-derive.rs:229:5
|
--> $DIR/diagnostic-derive.rs:231:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion(nonsense = "bar")]
|
LL | #[suggestion(nonsense = "bar")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[suggestion(msg = ...)]` is not a valid attribute
|
error: `#[suggestion(msg = ...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:238:18
|
--> $DIR/diagnostic-derive.rs:240:18
|
||||||
|
|
|
|
||||||
LL | #[suggestion(msg = "bar")]
|
LL | #[suggestion(msg = "bar")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
@ -280,13 +291,13 @@ LL | #[suggestion(msg = "bar")]
|
|||||||
= help: only `code` and `applicability` are valid nested attributes
|
= help: only `code` and `applicability` are valid nested attributes
|
||||||
|
|
||||||
error: suggestion without `code = "..."`
|
error: suggestion without `code = "..."`
|
||||||
--> $DIR/diagnostic-derive.rs:238:5
|
--> $DIR/diagnostic-derive.rs:240:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion(msg = "bar")]
|
LL | #[suggestion(msg = "bar")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: wrong field type for suggestion
|
error: wrong field type for suggestion
|
||||||
--> $DIR/diagnostic-derive.rs:261:5
|
--> $DIR/diagnostic-derive.rs:263:5
|
||||||
|
|
|
|
||||||
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
|
LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -296,55 +307,55 @@ LL | | suggestion: Applicability,
|
|||||||
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
|
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/diagnostic-derive.rs:277:24
|
--> $DIR/diagnostic-derive.rs:279:24
|
||||||
|
|
|
|
||||||
LL | suggestion: (Span, Span, Applicability),
|
LL | suggestion: (Span, Span, Applicability),
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/diagnostic-derive.rs:277:18
|
--> $DIR/diagnostic-derive.rs:279:18
|
||||||
|
|
|
|
||||||
LL | suggestion: (Span, Span, Applicability),
|
LL | suggestion: (Span, Span, Applicability),
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/diagnostic-derive.rs:285:33
|
--> $DIR/diagnostic-derive.rs:287:33
|
||||||
|
|
|
|
||||||
LL | suggestion: (Applicability, Applicability, Span),
|
LL | suggestion: (Applicability, Applicability, Span),
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/diagnostic-derive.rs:285:18
|
--> $DIR/diagnostic-derive.rs:287:18
|
||||||
|
|
|
|
||||||
LL | suggestion: (Applicability, Applicability, Span),
|
LL | suggestion: (Applicability, Applicability, Span),
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[label = ...]` is not a valid attribute
|
error: `#[label = ...]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:292:5
|
--> $DIR/diagnostic-derive.rs:294:5
|
||||||
|
|
|
|
||||||
LL | #[label = "bar"]
|
LL | #[label = "bar"]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/diagnostic-derive.rs:443:52
|
--> $DIR/diagnostic-derive.rs:445:52
|
||||||
|
|
|
|
||||||
LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
|
LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/diagnostic-derive.rs:445:24
|
--> $DIR/diagnostic-derive.rs:447:24
|
||||||
|
|
|
|
||||||
LL | suggestion: (Span, Applicability),
|
LL | suggestion: (Span, Applicability),
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: invalid applicability
|
error: invalid applicability
|
||||||
--> $DIR/diagnostic-derive.rs:451:52
|
--> $DIR/diagnostic-derive.rs:453:52
|
||||||
|
|
|
|
||||||
LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
|
LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[label(foo)]` is not a valid attribute
|
error: `#[label(foo)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:514:28
|
--> $DIR/diagnostic-derive.rs:516:28
|
||||||
|
|
|
|
||||||
LL | #[label(typeck::label, foo)]
|
LL | #[label(typeck::label, foo)]
|
||||||
| ^^^
|
| ^^^
|
||||||
@ -352,19 +363,19 @@ LL | #[label(typeck::label, foo)]
|
|||||||
= help: a diagnostic slug must be the first argument to the attribute
|
= help: a diagnostic slug must be the first argument to the attribute
|
||||||
|
|
||||||
error: `#[label(foo = ...)]` is not a valid attribute
|
error: `#[label(foo = ...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:522:28
|
--> $DIR/diagnostic-derive.rs:524:28
|
||||||
|
|
|
|
||||||
LL | #[label(typeck::label, foo = "...")]
|
LL | #[label(typeck::label, foo = "...")]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[label(foo(...))]` is not a valid attribute
|
error: `#[label(foo(...))]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:530:28
|
--> $DIR/diagnostic-derive.rs:532:28
|
||||||
|
|
|
|
||||||
LL | #[label(typeck::label, foo("..."))]
|
LL | #[label(typeck::label, foo("..."))]
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[primary_span]` is not a valid attribute
|
error: `#[primary_span]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:543:5
|
--> $DIR/diagnostic-derive.rs:545:5
|
||||||
|
|
|
|
||||||
LL | #[primary_span]
|
LL | #[primary_span]
|
||||||
| ^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
@ -372,13 +383,13 @@ LL | #[primary_span]
|
|||||||
= help: the `primary_span` field attribute is not valid for lint diagnostics
|
= help: the `primary_span` field attribute is not valid for lint diagnostics
|
||||||
|
|
||||||
error: `#[error(...)]` is not a valid attribute
|
error: `#[error(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:563:1
|
--> $DIR/diagnostic-derive.rs:565:1
|
||||||
|
|
|
|
||||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:563:1
|
--> $DIR/diagnostic-derive.rs:565:1
|
||||||
|
|
|
|
||||||
LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -390,13 +401,13 @@ LL | | struct ErrorAttribute {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[warn_(...)]` is not a valid attribute
|
error: `#[warn_(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:570:1
|
--> $DIR/diagnostic-derive.rs:572:1
|
||||||
|
|
|
|
||||||
LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:570:1
|
--> $DIR/diagnostic-derive.rs:572:1
|
||||||
|
|
|
|
||||||
LL | / #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | / #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -408,13 +419,13 @@ LL | | struct WarnAttribute {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[lint(...)]` is not a valid attribute
|
error: `#[lint(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:577:1
|
--> $DIR/diagnostic-derive.rs:579:1
|
||||||
|
|
|
|
||||||
LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:577:1
|
--> $DIR/diagnostic-derive.rs:579:1
|
||||||
|
|
|
|
||||||
LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -426,13 +437,13 @@ LL | | struct LintAttributeOnSessionDiag {}
|
|||||||
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: `#[lint(...)]` is not a valid attribute
|
error: `#[lint(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:584:1
|
--> $DIR/diagnostic-derive.rs:586:1
|
||||||
|
|
|
|
||||||
LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: diagnostic slug not specified
|
error: diagnostic slug not specified
|
||||||
--> $DIR/diagnostic-derive.rs:584:1
|
--> $DIR/diagnostic-derive.rs:586:1
|
||||||
|
|
|
|
||||||
LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
LL | |
|
LL | |
|
||||||
@ -444,19 +455,19 @@ LL | | struct LintAttributeOnLintDiag {}
|
|||||||
= help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]`
|
= help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]`
|
||||||
|
|
||||||
error: specified multiple times
|
error: specified multiple times
|
||||||
--> $DIR/diagnostic-derive.rs:593:52
|
--> $DIR/diagnostic-derive.rs:595:52
|
||||||
|
|
|
|
||||||
LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")]
|
LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: previously specified here
|
note: previously specified here
|
||||||
--> $DIR/diagnostic-derive.rs:593:38
|
--> $DIR/diagnostic-derive.rs:595:38
|
||||||
|
|
|
|
||||||
LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")]
|
LL | #[suggestion(typeck::suggestion, code = "...", code = ",,,")]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: wrong types for suggestion
|
error: wrong types for suggestion
|
||||||
--> $DIR/diagnostic-derive.rs:602:24
|
--> $DIR/diagnostic-derive.rs:604:24
|
||||||
|
|
|
|
||||||
LL | suggestion: (Span, usize),
|
LL | suggestion: (Span, usize),
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
@ -464,7 +475,7 @@ LL | suggestion: (Span, usize),
|
|||||||
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
|
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
|
||||||
|
|
||||||
error: wrong types for suggestion
|
error: wrong types for suggestion
|
||||||
--> $DIR/diagnostic-derive.rs:610:17
|
--> $DIR/diagnostic-derive.rs:612:17
|
||||||
|
|
|
|
||||||
LL | suggestion: (Span,),
|
LL | suggestion: (Span,),
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
@ -472,13 +483,13 @@ LL | suggestion: (Span,),
|
|||||||
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
|
= help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
|
||||||
|
|
||||||
error: suggestion without `code = "..."`
|
error: suggestion without `code = "..."`
|
||||||
--> $DIR/diagnostic-derive.rs:617:5
|
--> $DIR/diagnostic-derive.rs:619:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion(typeck::suggestion)]
|
LL | #[suggestion(typeck::suggestion)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `#[multipart_suggestion(...)]` is not a valid attribute
|
error: `#[multipart_suggestion(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:624:1
|
--> $DIR/diagnostic-derive.rs:626:1
|
||||||
|
|
|
|
||||||
LL | #[multipart_suggestion(typeck::suggestion)]
|
LL | #[multipart_suggestion(typeck::suggestion)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -486,7 +497,7 @@ LL | #[multipart_suggestion(typeck::suggestion)]
|
|||||||
= help: consider creating a `Subdiagnostic` instead
|
= help: consider creating a `Subdiagnostic` instead
|
||||||
|
|
||||||
error: `#[multipart_suggestion(...)]` is not a valid attribute
|
error: `#[multipart_suggestion(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:627:1
|
--> $DIR/diagnostic-derive.rs:629:1
|
||||||
|
|
|
|
||||||
LL | #[multipart_suggestion()]
|
LL | #[multipart_suggestion()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -494,7 +505,7 @@ LL | #[multipart_suggestion()]
|
|||||||
= help: consider creating a `Subdiagnostic` instead
|
= help: consider creating a `Subdiagnostic` instead
|
||||||
|
|
||||||
error: `#[multipart_suggestion(...)]` is not a valid attribute
|
error: `#[multipart_suggestion(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:631:5
|
--> $DIR/diagnostic-derive.rs:633:5
|
||||||
|
|
|
|
||||||
LL | #[multipart_suggestion(typeck::suggestion)]
|
LL | #[multipart_suggestion(typeck::suggestion)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -502,7 +513,7 @@ LL | #[multipart_suggestion(typeck::suggestion)]
|
|||||||
= help: consider creating a `Subdiagnostic` instead
|
= help: consider creating a `Subdiagnostic` instead
|
||||||
|
|
||||||
error: `#[suggestion(...)]` is not a valid attribute
|
error: `#[suggestion(...)]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:639:1
|
--> $DIR/diagnostic-derive.rs:641:1
|
||||||
|
|
|
|
||||||
LL | #[suggestion(typeck::suggestion, code = "...")]
|
LL | #[suggestion(typeck::suggestion, code = "...")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -510,7 +521,7 @@ LL | #[suggestion(typeck::suggestion, code = "...")]
|
|||||||
= help: `#[label]` and `#[suggestion]` can only be applied to fields
|
= help: `#[label]` and `#[suggestion]` can only be applied to fields
|
||||||
|
|
||||||
error: `#[label]` is not a valid attribute
|
error: `#[label]` is not a valid attribute
|
||||||
--> $DIR/diagnostic-derive.rs:648:1
|
--> $DIR/diagnostic-derive.rs:650:1
|
||||||
|
|
|
|
||||||
LL | #[label]
|
LL | #[label]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
@ -518,67 +529,67 @@ LL | #[label]
|
|||||||
= help: `#[label]` and `#[suggestion]` can only be applied to fields
|
= help: `#[label]` and `#[suggestion]` can only be applied to fields
|
||||||
|
|
||||||
error: cannot find attribute `nonsense` in this scope
|
error: cannot find attribute `nonsense` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:53:3
|
--> $DIR/diagnostic-derive.rs:55:3
|
||||||
|
|
|
|
||||||
LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: cannot find attribute `nonsense` in this scope
|
error: cannot find attribute `nonsense` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:143:7
|
--> $DIR/diagnostic-derive.rs:145:7
|
||||||
|
|
|
|
||||||
LL | #[nonsense]
|
LL | #[nonsense]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: cannot find attribute `error` in this scope
|
error: cannot find attribute `error` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:563:3
|
--> $DIR/diagnostic-derive.rs:565:3
|
||||||
|
|
|
|
||||||
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: cannot find attribute `warn_` in this scope
|
error: cannot find attribute `warn_` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:570:3
|
--> $DIR/diagnostic-derive.rs:572:3
|
||||||
|
|
|
|
||||||
LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^^ help: a built-in attribute with a similar name exists: `warn`
|
| ^^^^^ help: a built-in attribute with a similar name exists: `warn`
|
||||||
|
|
||||||
error: cannot find attribute `lint` in this scope
|
error: cannot find attribute `lint` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:577:3
|
--> $DIR/diagnostic-derive.rs:579:3
|
||||||
|
|
|
|
||||||
LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^ help: a built-in attribute with a similar name exists: `link`
|
| ^^^^ help: a built-in attribute with a similar name exists: `link`
|
||||||
|
|
||||||
error: cannot find attribute `lint` in this scope
|
error: cannot find attribute `lint` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:584:3
|
--> $DIR/diagnostic-derive.rs:586:3
|
||||||
|
|
|
|
||||||
LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
|
||||||
| ^^^^ help: a built-in attribute with a similar name exists: `link`
|
| ^^^^ help: a built-in attribute with a similar name exists: `link`
|
||||||
|
|
||||||
error: cannot find attribute `multipart_suggestion` in this scope
|
error: cannot find attribute `multipart_suggestion` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:624:3
|
--> $DIR/diagnostic-derive.rs:626:3
|
||||||
|
|
|
|
||||||
LL | #[multipart_suggestion(typeck::suggestion)]
|
LL | #[multipart_suggestion(typeck::suggestion)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: cannot find attribute `multipart_suggestion` in this scope
|
error: cannot find attribute `multipart_suggestion` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:627:3
|
--> $DIR/diagnostic-derive.rs:629:3
|
||||||
|
|
|
|
||||||
LL | #[multipart_suggestion()]
|
LL | #[multipart_suggestion()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: cannot find attribute `multipart_suggestion` in this scope
|
error: cannot find attribute `multipart_suggestion` in this scope
|
||||||
--> $DIR/diagnostic-derive.rs:631:7
|
--> $DIR/diagnostic-derive.rs:633:7
|
||||||
|
|
|
|
||||||
LL | #[multipart_suggestion(typeck::suggestion)]
|
LL | #[multipart_suggestion(typeck::suggestion)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
|
error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
|
||||||
--> $DIR/diagnostic-derive.rs:66:8
|
--> $DIR/diagnostic-derive.rs:68:8
|
||||||
|
|
|
|
||||||
LL | #[diag(nonsense, code = "E0123")]
|
LL | #[diag(nonsense, code = "E0123")]
|
||||||
| ^^^^^^^^ not found in `rustc_errors::fluent`
|
| ^^^^^^^^ not found in `rustc_errors::fluent`
|
||||||
|
|
||||||
error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
|
error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
|
||||||
--> $DIR/diagnostic-derive.rs:336:10
|
--> $DIR/diagnostic-derive.rs:338:10
|
||||||
|
|
|
|
||||||
LL | #[derive(Diagnostic)]
|
LL | #[derive(Diagnostic)]
|
||||||
| ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
|
| ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
|
||||||
@ -591,7 +602,7 @@ LL | arg: impl IntoDiagnosticArg,
|
|||||||
| ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
| ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
||||||
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 72 previous errors
|
error: aborting due to 74 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0425.
|
Some errors have detailed explanations: E0277, E0425.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
Loading…
Reference in New Issue
Block a user