macros: translatable struct attrs and warnings
Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
f0de7df204
commit
d0fd8d7880
9 changed files with 729 additions and 276 deletions
|
@ -1,2 +1,87 @@
|
||||||
parser-struct-literal-body-without-path = struct literal body without path
|
parser-struct-literal-body-without-path =
|
||||||
|
struct literal body without path
|
||||||
.suggestion = you might have forgotten to add the struct literal inside the block
|
.suggestion = you might have forgotten to add the struct literal inside the block
|
||||||
|
|
||||||
|
typeck-field-multiply-specified-in-initializer =
|
||||||
|
field `{$ident}` specified more than once
|
||||||
|
.label = used more than once
|
||||||
|
.previous-use-label = first use of `{$ident}`
|
||||||
|
|
||||||
|
typeck-unrecognized-atomic-operation =
|
||||||
|
unrecognized atomic operation function: `{$op}`
|
||||||
|
.label = unrecognized atomic operation
|
||||||
|
|
||||||
|
typeck-wrong-number-of-generic-arguments-to-intrinsic =
|
||||||
|
intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
|
||||||
|
.label = expected {$expected} {$descr} {$expected ->
|
||||||
|
[one] parameter
|
||||||
|
*[other] parameters
|
||||||
|
}
|
||||||
|
|
||||||
|
typeck-unrecognized-intrinsic-function =
|
||||||
|
unrecognized intrinsic function: `{$name}`
|
||||||
|
.label = unrecognized intrinsic
|
||||||
|
|
||||||
|
typeck-lifetimes-or-bounds-mismatch-on-trait =
|
||||||
|
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
|
||||||
|
.label = lifetimes do not match {$item_kind} in trait
|
||||||
|
.generics-label = lifetimes in impl do not match this {$item_kind} in trait
|
||||||
|
|
||||||
|
typeck-drop-impl-on-wrong-item =
|
||||||
|
the `Drop` trait may only be implemented for structs, enums, and unions
|
||||||
|
.label = must be a struct, enum, or union
|
||||||
|
|
||||||
|
typeck-field-already-declared =
|
||||||
|
field `{$field_name}` is already declared
|
||||||
|
.label = field already declared
|
||||||
|
.previous-decl-label = `{$field_name}` first declared here
|
||||||
|
|
||||||
|
typeck-copy-impl-on-type-with-dtor =
|
||||||
|
the trait `Copy` may not be implemented for this type; the type has a destructor
|
||||||
|
.label = `Copy` not allowed on types with destructors
|
||||||
|
|
||||||
|
typeck-multiple-relaxed-default-bounds =
|
||||||
|
type parameter has more than one relaxed default bound, only one is supported
|
||||||
|
|
||||||
|
typeck-copy-impl-on-non-adt =
|
||||||
|
the trait `Copy` may not be implemented for this type
|
||||||
|
.label = type is not a structure or enumeration
|
||||||
|
|
||||||
|
typeck-trait-object-declared-with-no-traits =
|
||||||
|
at least one trait is required for an object type
|
||||||
|
|
||||||
|
typeck-ambiguous-lifetime-bound =
|
||||||
|
ambiguous lifetime bound, explicit lifetime bound required
|
||||||
|
|
||||||
|
typeck-assoc-type-binding-not-allowed =
|
||||||
|
associated type bindings are not allowed here
|
||||||
|
.label = associated type not allowed here
|
||||||
|
|
||||||
|
typeck-functional-record-update-on-non-struct =
|
||||||
|
functional record update syntax requires a struct
|
||||||
|
|
||||||
|
typeck-typeof-reserved-keyword-used =
|
||||||
|
`typeof` is a reserved keyword but unimplemented
|
||||||
|
.label = reserved keyword
|
||||||
|
|
||||||
|
typeck-return-stmt-outside-of-fn-body =
|
||||||
|
return statement outside of function body
|
||||||
|
.encl-body-label = the return is part of this body...
|
||||||
|
.encl-fn-label = ...not the enclosing function body
|
||||||
|
|
||||||
|
typeck-yield-expr-outside-of-generator =
|
||||||
|
yield expression outside of generator literal
|
||||||
|
|
||||||
|
typeck-struct-expr-non-exhaustive =
|
||||||
|
cannot create non-exhaustive {$what} using struct expression
|
||||||
|
|
||||||
|
typeck-method-call-on-unknown-type =
|
||||||
|
the type of this value must be known to call a method on a raw pointer on it
|
||||||
|
|
||||||
|
typeck-value-of-associated-struct-already-specified =
|
||||||
|
the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
|
||||||
|
.label = re-bound here
|
||||||
|
.previous-bound-label = `{$item_name}` bound here first
|
||||||
|
|
||||||
|
typeck-address-of-temporary-taken = cannot take address of a temporary
|
||||||
|
.label = temporary value
|
||||||
|
|
|
@ -261,7 +261,7 @@ pub trait Emitter {
|
||||||
message: &'a DiagnosticMessage,
|
message: &'a DiagnosticMessage,
|
||||||
args: &'a FluentArgs<'_>,
|
args: &'a FluentArgs<'_>,
|
||||||
) -> Cow<'_, str> {
|
) -> Cow<'_, str> {
|
||||||
trace!(?message);
|
trace!(?message, ?args);
|
||||||
let (identifier, attr) = match message {
|
let (identifier, attr) = match message {
|
||||||
DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
|
DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
|
||||||
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||||
|
@ -283,7 +283,13 @@ pub trait Emitter {
|
||||||
let mut err = vec![];
|
let mut err = vec![];
|
||||||
let translated = bundle.format_pattern(value, Some(&args), &mut err);
|
let translated = bundle.format_pattern(value, Some(&args), &mut err);
|
||||||
trace!(?translated, ?err);
|
trace!(?translated, ?err);
|
||||||
debug_assert!(err.is_empty());
|
debug_assert!(
|
||||||
|
err.is_empty(),
|
||||||
|
"identifier: {:?}, args: {:?}, errors: {:?}",
|
||||||
|
identifier,
|
||||||
|
args,
|
||||||
|
err
|
||||||
|
);
|
||||||
translated
|
translated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -777,6 +777,17 @@ impl Handler {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct a builder at the `Warn` level with the `msg` and the `code`.
|
||||||
|
pub fn struct_warn_with_code(
|
||||||
|
&self,
|
||||||
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
code: DiagnosticId,
|
||||||
|
) -> DiagnosticBuilder<'_, ()> {
|
||||||
|
let mut result = self.struct_warn(msg);
|
||||||
|
result.code(code);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct a builder at the `Fatal` level at the given `span` and with the `msg`.
|
/// Construct a builder at the `Fatal` level at the given `span` and with the `msg`.
|
||||||
pub fn struct_span_fatal(
|
pub fn struct_span_fatal(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -63,9 +63,14 @@ decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_fo
|
||||||
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
|
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
|
||||||
decl_derive!(
|
decl_derive!(
|
||||||
[SessionDiagnostic, attributes(
|
[SessionDiagnostic, attributes(
|
||||||
message,
|
// struct attributes
|
||||||
lint,
|
warning,
|
||||||
error,
|
error,
|
||||||
|
// nested parts of struct attributes
|
||||||
|
code,
|
||||||
|
slug,
|
||||||
|
// field attributes
|
||||||
|
message,
|
||||||
label,
|
label,
|
||||||
suggestion,
|
suggestion,
|
||||||
suggestion_short,
|
suggestion_short,
|
||||||
|
|
|
@ -16,11 +16,11 @@ use std::collections::{BTreeSet, HashMap};
|
||||||
/// # extern crate rust_middle;
|
/// # extern crate rust_middle;
|
||||||
/// # use rustc_middle::ty::Ty;
|
/// # use rustc_middle::ty::Ty;
|
||||||
/// #[derive(SessionDiagnostic)]
|
/// #[derive(SessionDiagnostic)]
|
||||||
/// #[code = "E0505"]
|
/// #[error(code = "E0505", slug = "move-out-of-borrow-error")]
|
||||||
/// #[error = "cannot move out of {name} because it is borrowed"]
|
|
||||||
/// pub struct MoveOutOfBorrowError<'tcx> {
|
/// pub struct MoveOutOfBorrowError<'tcx> {
|
||||||
/// pub name: Ident,
|
/// pub name: Ident,
|
||||||
/// pub ty: Ty<'tcx>,
|
/// pub ty: Ty<'tcx>,
|
||||||
|
/// #[message]
|
||||||
/// #[label = "cannot move out of borrow"]
|
/// #[label = "cannot move out of borrow"]
|
||||||
/// pub span: Span,
|
/// pub span: Span,
|
||||||
/// #[label = "`{ty}` first borrowed here"]
|
/// #[label = "`{ty}` first borrowed here"]
|
||||||
|
@ -79,13 +79,6 @@ impl std::convert::From<syn::Error> for SessionDiagnosticDeriveError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent to `rustc:errors::diagnostic::DiagnosticId`, except stores the quoted expression to
|
|
||||||
/// initialise the code with.
|
|
||||||
enum DiagnosticId {
|
|
||||||
Error(proc_macro2::TokenStream),
|
|
||||||
Lint(proc_macro2::TokenStream),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum SessionDiagnosticDeriveError {
|
enum SessionDiagnosticDeriveError {
|
||||||
SynError(syn::Error),
|
SynError(syn::Error),
|
||||||
|
@ -100,7 +93,7 @@ impl SessionDiagnosticDeriveError {
|
||||||
// Return ! to avoid having to create a blank DiagnosticBuilder to return when an
|
// Return ! to avoid having to create a blank DiagnosticBuilder to return when an
|
||||||
// error has already been emitted to the compiler.
|
// error has already been emitted to the compiler.
|
||||||
quote! {
|
quote! {
|
||||||
unreachable!()
|
{ unreachable!(); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,17 +145,25 @@ impl<'a> SessionDiagnosticDerive<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
builder: SessionDiagnosticDeriveBuilder { diag, sess, fields: fields_map, kind: None },
|
builder: SessionDiagnosticDeriveBuilder {
|
||||||
|
diag,
|
||||||
|
sess,
|
||||||
|
fields: fields_map,
|
||||||
|
kind: None,
|
||||||
|
code: None,
|
||||||
|
slug: None,
|
||||||
|
},
|
||||||
structure,
|
structure,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_tokens(self) -> proc_macro2::TokenStream {
|
fn into_tokens(self) -> proc_macro2::TokenStream {
|
||||||
let SessionDiagnosticDerive { mut structure, mut builder } = self;
|
let SessionDiagnosticDerive { mut structure, mut builder } = self;
|
||||||
|
|
||||||
let ast = structure.ast();
|
let ast = structure.ast();
|
||||||
let attrs = &ast.attrs;
|
let attrs = &ast.attrs;
|
||||||
|
|
||||||
let implementation = {
|
let (implementation, param_ty) = {
|
||||||
if let syn::Data::Struct(..) = ast.data {
|
if let syn::Data::Struct(..) = ast.data {
|
||||||
let preamble = {
|
let preamble = {
|
||||||
let preamble = attrs.iter().map(|attr| {
|
let preamble = attrs.iter().map(|attr| {
|
||||||
|
@ -170,6 +171,7 @@ impl<'a> SessionDiagnosticDerive<'a> {
|
||||||
.generate_structure_code(attr)
|
.generate_structure_code(attr)
|
||||||
.unwrap_or_else(|v| v.to_compile_error())
|
.unwrap_or_else(|v| v.to_compile_error())
|
||||||
});
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#(#preamble)*;
|
#(#preamble)*;
|
||||||
}
|
}
|
||||||
|
@ -213,27 +215,54 @@ impl<'a> SessionDiagnosticDerive<'a> {
|
||||||
// it can be referred to by Fluent messages.
|
// it can be referred to by Fluent messages.
|
||||||
if field.attrs.is_empty() {
|
if field.attrs.is_empty() {
|
||||||
let diag = &builder.diag;
|
let diag = &builder.diag;
|
||||||
let ident = &field_binding.binding;
|
let ident = field_binding.ast().ident.as_ref().unwrap();
|
||||||
quote! { #diag.set_arg(stringify!(#ident), #field_binding.into_diagnostic_arg()); }
|
quote! { #diag.set_arg(stringify!(#ident), #field_binding.into_diagnostic_arg()); }
|
||||||
} else {
|
} else {
|
||||||
quote! {}
|
quote! {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Finally, putting it altogether.
|
let span = ast.span().unwrap();
|
||||||
match builder.kind {
|
|
||||||
None => {
|
|
||||||
span_err(ast.span().unwrap(), "`code` not specified")
|
|
||||||
.help("use the `#[code = \"...\"]` attribute to set this diagnostic's error code ")
|
|
||||||
.emit();
|
|
||||||
SessionDiagnosticDeriveError::ErrorHandled.to_compile_error()
|
|
||||||
}
|
|
||||||
Some((kind, _)) => match kind {
|
|
||||||
DiagnosticId::Lint(_lint) => todo!(),
|
|
||||||
DiagnosticId::Error(code) => {
|
|
||||||
let (diag, sess) = (&builder.diag, &builder.sess);
|
let (diag, sess) = (&builder.diag, &builder.sess);
|
||||||
|
let init = match (builder.kind, builder.slug, builder.code) {
|
||||||
|
(None, _, _) => {
|
||||||
|
span_err(span, "diagnostic kind not specified")
|
||||||
|
.help("use the `#[error(...)]` attribute to create an error")
|
||||||
|
.emit();
|
||||||
|
return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||||
|
}
|
||||||
|
(Some((kind, _)), None, _) => {
|
||||||
|
span_err(span, "`slug` not specified")
|
||||||
|
.help(&format!("use the `#[{}(slug = \"...\")]` attribute to set this diagnostic's slug", kind.descr()))
|
||||||
|
.emit();
|
||||||
|
return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||||
|
}
|
||||||
|
(Some((kind, _)), _, None) => {
|
||||||
|
span_err(span, "`code` not specified")
|
||||||
|
.help(&format!("use the `#[{}(code = \"...\")]` attribute to set this diagnostic's error code", kind.descr()))
|
||||||
|
.emit();
|
||||||
|
return SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||||
|
}
|
||||||
|
(Some((SessionDiagnosticKind::Error, _)), Some((slug, _)), Some((code, _))) => {
|
||||||
quote! {
|
quote! {
|
||||||
let mut #diag = #sess.struct_err_with_code("", rustc_errors::DiagnosticId::Error(#code));
|
let mut #diag = #sess.struct_err_with_code(
|
||||||
|
rustc_errors::DiagnosticMessage::fluent(#slug),
|
||||||
|
rustc_errors::DiagnosticId::Error(#code.to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some((SessionDiagnosticKind::Warn, _)), Some((slug, _)), Some((code, _))) => {
|
||||||
|
quote! {
|
||||||
|
let mut #diag = #sess.struct_warn_with_code(
|
||||||
|
rustc_errors::DiagnosticMessage::fluent(#slug),
|
||||||
|
rustc_errors::DiagnosticId::Error(#code.to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let implementation = quote! {
|
||||||
|
#init
|
||||||
#preamble
|
#preamble
|
||||||
match self {
|
match self {
|
||||||
#attrs
|
#attrs
|
||||||
|
@ -242,29 +271,38 @@ impl<'a> SessionDiagnosticDerive<'a> {
|
||||||
#args
|
#args
|
||||||
}
|
}
|
||||||
#diag
|
#diag
|
||||||
|
};
|
||||||
|
let param_ty = match builder.kind {
|
||||||
|
Some((SessionDiagnosticKind::Error, _)) => {
|
||||||
|
quote! { rustc_errors::ErrorGuaranteed }
|
||||||
}
|
}
|
||||||
}
|
Some((SessionDiagnosticKind::Warn, _)) => quote! { () },
|
||||||
},
|
_ => unreachable!(),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
(implementation, param_ty)
|
||||||
} else {
|
} else {
|
||||||
span_err(
|
span_err(
|
||||||
ast.span().unwrap(),
|
ast.span().unwrap(),
|
||||||
"`#[derive(SessionDiagnostic)]` can only be used on structs",
|
"`#[derive(SessionDiagnostic)]` can only be used on structs",
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
SessionDiagnosticDeriveError::ErrorHandled.to_compile_error()
|
|
||||||
|
let implementation = SessionDiagnosticDeriveError::ErrorHandled.to_compile_error();
|
||||||
|
let param_ty = quote! { rustc_errors::ErrorGuaranteed };
|
||||||
|
(implementation, param_ty)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let sess = &builder.sess;
|
let sess = &builder.sess;
|
||||||
structure.gen_impl(quote! {
|
structure.gen_impl(quote! {
|
||||||
gen impl<'__session_diagnostic_sess> rustc_session::SessionDiagnostic<'__session_diagnostic_sess>
|
gen impl<'__session_diagnostic_sess> rustc_session::SessionDiagnostic<'__session_diagnostic_sess, #param_ty>
|
||||||
for @Self
|
for @Self
|
||||||
{
|
{
|
||||||
fn into_diagnostic(
|
fn into_diagnostic(
|
||||||
self,
|
self,
|
||||||
#sess: &'__session_diagnostic_sess rustc_session::Session
|
#sess: &'__session_diagnostic_sess rustc_session::Session
|
||||||
) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, rustc_errors::ErrorGuaranteed> {
|
) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, #param_ty> {
|
||||||
use rustc_errors::IntoDiagnosticArg;
|
use rustc_errors::IntoDiagnosticArg;
|
||||||
#implementation
|
#implementation
|
||||||
}
|
}
|
||||||
|
@ -282,6 +320,25 @@ struct FieldInfo<'a> {
|
||||||
span: &'a proc_macro2::Span,
|
span: &'a proc_macro2::Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// What kind of session diagnostic is being derived - an error or a warning?
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
enum SessionDiagnosticKind {
|
||||||
|
/// `#[error(..)]`
|
||||||
|
Error,
|
||||||
|
/// `#[warn(..)]`
|
||||||
|
Warn,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SessionDiagnosticKind {
|
||||||
|
/// Returns human-readable string corresponding to the kind.
|
||||||
|
fn descr(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
SessionDiagnosticKind::Error => "error",
|
||||||
|
SessionDiagnosticKind::Warn => "warning",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Tracks persistent information required for building up the individual calls to diagnostic
|
/// Tracks persistent information required for building up the individual calls to diagnostic
|
||||||
/// methods for the final generated method. This is a separate struct to `SessionDiagnosticDerive`
|
/// methods for the final generated method. This is a separate struct to `SessionDiagnosticDerive`
|
||||||
/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a
|
/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a
|
||||||
|
@ -289,89 +346,182 @@ struct FieldInfo<'a> {
|
||||||
struct SessionDiagnosticDeriveBuilder<'a> {
|
struct SessionDiagnosticDeriveBuilder<'a> {
|
||||||
/// Name of the session parameter that's passed in to the `as_error` method.
|
/// Name of the session parameter that's passed in to the `as_error` method.
|
||||||
sess: syn::Ident,
|
sess: syn::Ident,
|
||||||
|
/// The identifier to use for the generated `DiagnosticBuilder` instance.
|
||||||
|
diag: syn::Ident,
|
||||||
|
|
||||||
/// 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, &'a syn::Field>,
|
fields: HashMap<String, &'a syn::Field>,
|
||||||
|
|
||||||
/// The identifier to use for the generated `DiagnosticBuilder` instance.
|
/// Kind of diagnostic requested via the struct attribute.
|
||||||
diag: syn::Ident,
|
kind: Option<(SessionDiagnosticKind, proc_macro::Span)>,
|
||||||
|
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
|
||||||
/// Whether this is a lint or an error. This dictates how the diag will be initialised. `Span`
|
/// has the actual diagnostic message.
|
||||||
/// stores at what `Span` the kind was first set at (for error reporting purposes, if the kind
|
slug: Option<(String, proc_macro::Span)>,
|
||||||
/// was multiply specified).
|
/// Error codes are a mandatory part of the struct attribute. Slugs may replace error codes
|
||||||
kind: Option<(DiagnosticId, proc_macro2::Span)>,
|
/// in future but it is desirable to mandate error codes until such a time.
|
||||||
|
code: Option<(String, proc_macro::Span)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
|
/// Establishes state in the `SessionDiagnosticDeriveBuilder` resulting from the struct
|
||||||
|
/// attributes like `#[error(..)#`, such as the diagnostic kind, slug and code.
|
||||||
|
///
|
||||||
|
/// Returns a `proc_macro2::TokenStream` so that the `Err(..)` variant can be transformed into
|
||||||
|
/// the same type via `to_compile_error`.
|
||||||
fn generate_structure_code(
|
fn generate_structure_code(
|
||||||
&mut self,
|
&mut self,
|
||||||
attr: &syn::Attribute,
|
attr: &syn::Attribute,
|
||||||
) -> Result<proc_macro2::TokenStream, SessionDiagnosticDeriveError> {
|
) -> Result<proc_macro2::TokenStream, SessionDiagnosticDeriveError> {
|
||||||
Ok(match attr.parse_meta()? {
|
let span = attr.span().unwrap();
|
||||||
syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
|
|
||||||
let formatted_str = self.build_format(&s.value(), attr.span());
|
|
||||||
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();
|
|
||||||
match name {
|
let nested = match attr.parse_meta()? {
|
||||||
"message" => {
|
syn::Meta::List(syn::MetaList { nested, .. }) => nested,
|
||||||
let diag = &self.diag;
|
syn::Meta::Path(..) => throw_span_err!(
|
||||||
quote! {
|
span,
|
||||||
#diag.set_primary_message(#formatted_str);
|
&format!("`#[{}]` is not a valid `SessionDiagnostic` struct attribute", name)
|
||||||
}
|
),
|
||||||
}
|
syn::Meta::NameValue(..) => throw_span_err!(
|
||||||
attr @ "error" | attr @ "lint" => {
|
span,
|
||||||
self.set_kind_once(
|
&format!("`#[{} = ...]` is not a valid `SessionDiagnostic` struct attribute", name)
|
||||||
if attr == "error" {
|
),
|
||||||
DiagnosticId::Error(formatted_str)
|
};
|
||||||
} else if attr == "lint" {
|
|
||||||
DiagnosticId::Lint(formatted_str)
|
let kind = match name.as_str() {
|
||||||
} else {
|
"error" => SessionDiagnosticKind::Error,
|
||||||
unreachable!()
|
"warning" => SessionDiagnosticKind::Warn,
|
||||||
},
|
|
||||||
s.span(),
|
|
||||||
)?;
|
|
||||||
// This attribute is only allowed to be applied once, and the attribute
|
|
||||||
// will be set in the initialisation code.
|
|
||||||
quote! {}
|
|
||||||
}
|
|
||||||
other => throw_span_err!(
|
other => throw_span_err!(
|
||||||
attr.span().unwrap(),
|
span,
|
||||||
|
&format!("`#[{}(...)]` is not a valid `SessionDiagnostic` struct attribute", other)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
self.set_kind_once(kind, span)?;
|
||||||
|
|
||||||
|
for attr in nested {
|
||||||
|
let span = attr.span().unwrap();
|
||||||
|
let meta = match attr {
|
||||||
|
syn::NestedMeta::Meta(meta) => meta,
|
||||||
|
syn::NestedMeta::Lit(_) => throw_span_err!(
|
||||||
|
span,
|
||||||
&format!(
|
&format!(
|
||||||
"`#[{} = ...]` is not a valid `SessionDiagnostic` struct attribute",
|
"`#[{}(\"...\")]` is not a valid `SessionDiagnostic` struct attribute",
|
||||||
other
|
name
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let path = meta.path();
|
||||||
|
let nested_name = path.segments.last().unwrap().ident.to_string();
|
||||||
|
match &meta {
|
||||||
|
// Struct attributes are only allowed to be applied once, and the diagnostic
|
||||||
|
// changes will be set in the initialisation code.
|
||||||
|
syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
|
||||||
|
match nested_name.as_str() {
|
||||||
|
"slug" => {
|
||||||
|
self.set_slug_once(s.value(), s.span().unwrap());
|
||||||
|
}
|
||||||
|
"code" => {
|
||||||
|
self.set_code_once(s.value(), s.span().unwrap());
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
let diag = span_err(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"`#[{}({} = ...)]` is not a valid `SessionDiagnostic` struct attribute",
|
||||||
|
name, other
|
||||||
|
),
|
||||||
|
);
|
||||||
|
diag.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => todo!("unhandled meta kind"),
|
}
|
||||||
})
|
syn::Meta::NameValue(..) => {
|
||||||
|
span_err(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"`#[{}({} = ...)]` is not a valid `SessionDiagnostic` struct attribute",
|
||||||
|
name, nested_name
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.help("value must be a string")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
syn::Meta::Path(..) => {
|
||||||
|
span_err(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"`#[{}({})]` is not a valid `SessionDiagnostic` struct attribute",
|
||||||
|
name, nested_name
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
syn::Meta::List(..) => {
|
||||||
|
span_err(
|
||||||
|
span,
|
||||||
|
&format!(
|
||||||
|
"`#[{}({}(...))]` is not a valid `SessionDiagnostic` struct attribute",
|
||||||
|
name, nested_name
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(quote! {})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn set_kind_once(
|
fn set_kind_once(
|
||||||
&mut self,
|
&mut self,
|
||||||
kind: DiagnosticId,
|
kind: SessionDiagnosticKind,
|
||||||
span: proc_macro2::Span,
|
span: proc_macro::Span,
|
||||||
) -> Result<(), SessionDiagnosticDeriveError> {
|
) -> Result<(), SessionDiagnosticDeriveError> {
|
||||||
if self.kind.is_none() {
|
match self.kind {
|
||||||
|
None => {
|
||||||
self.kind = Some((kind, span));
|
self.kind = Some((kind, span));
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
}
|
||||||
let kind_str = |kind: &DiagnosticId| match kind {
|
Some((prev_kind, prev_span)) => {
|
||||||
DiagnosticId::Lint(..) => "lint",
|
let existing = prev_kind.descr();
|
||||||
DiagnosticId::Error(..) => "error",
|
let current = kind.descr();
|
||||||
};
|
|
||||||
|
|
||||||
let existing_kind = kind_str(&self.kind.as_ref().unwrap().0);
|
let msg = if current == existing {
|
||||||
let this_kind = kind_str(&kind);
|
format!("`{}` specified multiple times", existing)
|
||||||
|
|
||||||
let msg = if this_kind == existing_kind {
|
|
||||||
format!("`{}` specified multiple times", existing_kind)
|
|
||||||
} else {
|
} else {
|
||||||
format!("`{}` specified when `{}` was already specified", this_kind, existing_kind)
|
format!("`{}` specified when `{}` was already specified", current, existing)
|
||||||
};
|
};
|
||||||
throw_span_err!(span.unwrap(), &msg);
|
throw_span_err!(span, &msg, |diag| diag
|
||||||
|
.span_note(prev_span, "previously specified here"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_code_once(&mut self, code: String, span: proc_macro::Span) {
|
||||||
|
match self.code {
|
||||||
|
None => {
|
||||||
|
self.code = Some((code, span));
|
||||||
|
}
|
||||||
|
Some((_, prev_span)) => {
|
||||||
|
span_err(span, "`code` specified multiple times")
|
||||||
|
.span_note(prev_span, "previously specified here")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_slug_once(&mut self, slug: String, span: proc_macro::Span) {
|
||||||
|
match self.slug {
|
||||||
|
None => {
|
||||||
|
self.slug = Some((slug, span));
|
||||||
|
}
|
||||||
|
Some((_, prev_span)) => {
|
||||||
|
span_err(span, "`slug` specified multiple times")
|
||||||
|
.span_note(prev_span, "previously specified here")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,26 +563,29 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
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();
|
||||||
|
|
||||||
// At this point, we need to dispatch based on the attribute key + the
|
|
||||||
// type.
|
|
||||||
let meta = attr.parse_meta()?;
|
let meta = attr.parse_meta()?;
|
||||||
match meta {
|
match meta {
|
||||||
syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
|
syn::Meta::Path(_) => match name {
|
||||||
let formatted_str = self.build_format(&s.value(), attr.span());
|
|
||||||
match name {
|
|
||||||
"message" => {
|
"message" => {
|
||||||
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
||||||
return Ok(quote! {
|
return Ok(quote! {
|
||||||
#diag.set_span(*#field_binding);
|
#diag.set_span(*#field_binding);
|
||||||
#diag.set_primary_message(#formatted_str);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw_span_err!(
|
throw_span_err!(
|
||||||
attr.span().unwrap(),
|
attr.span().unwrap(),
|
||||||
"the `#[message = \"...\"]` attribute can only be applied to fields of type `Span`"
|
"the `#[message]` attribute can only be applied to fields of type `Span`"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
other => throw_span_err!(
|
||||||
|
attr.span().unwrap(),
|
||||||
|
&format!("`#[{}]` is not a valid `SessionDiagnostic` field attribute", other)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
|
||||||
|
let formatted_str = self.build_format(&s.value(), attr.span());
|
||||||
|
match name {
|
||||||
"label" => {
|
"label" => {
|
||||||
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
||||||
return Ok(quote! {
|
return Ok(quote! {
|
||||||
|
@ -441,7 +594,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
} else {
|
} else {
|
||||||
throw_span_err!(
|
throw_span_err!(
|
||||||
attr.span().unwrap(),
|
attr.span().unwrap(),
|
||||||
"The `#[label = ...]` attribute can only be applied to fields of type `Span`"
|
"the `#[label = ...]` attribute can only be applied to fields of type `Span`"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ use rustc_errors::json::JsonEmitter;
|
||||||
use rustc_errors::registry::Registry;
|
use rustc_errors::registry::Registry;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
fallback_fluent_bundle, fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
|
fallback_fluent_bundle, fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
|
||||||
ErrorGuaranteed, FluentBundle, MultiSpan,
|
EmissionGuarantee, ErrorGuaranteed, FluentBundle, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_macros::HashStable_Generic;
|
use rustc_macros::HashStable_Generic;
|
||||||
pub use rustc_span::def_id::StableCrateId;
|
pub use rustc_span::def_id::StableCrateId;
|
||||||
|
@ -209,10 +209,10 @@ pub struct PerfStats {
|
||||||
|
|
||||||
/// Trait implemented by error types. This should not be implemented manually. Instead, use
|
/// Trait implemented by error types. This should not be implemented manually. Instead, use
|
||||||
/// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic].
|
/// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic].
|
||||||
pub trait SessionDiagnostic<'a> {
|
pub trait SessionDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> {
|
||||||
/// Write out as a diagnostic out of `sess`.
|
/// Write out as a diagnostic out of `sess`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, ErrorGuaranteed>;
|
fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
|
@ -343,6 +343,13 @@ impl Session {
|
||||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||||
self.diagnostic().struct_err_with_code(msg, code)
|
self.diagnostic().struct_err_with_code(msg, code)
|
||||||
}
|
}
|
||||||
|
pub fn struct_warn_with_code(
|
||||||
|
&self,
|
||||||
|
msg: impl Into<DiagnosticMessage>,
|
||||||
|
code: DiagnosticId,
|
||||||
|
) -> DiagnosticBuilder<'_, ()> {
|
||||||
|
self.diagnostic().struct_warn_with_code(msg, code)
|
||||||
|
}
|
||||||
pub fn struct_span_fatal<S: Into<MultiSpan>>(
|
pub fn struct_span_fatal<S: Into<MultiSpan>>(
|
||||||
&self,
|
&self,
|
||||||
sp: S,
|
sp: S,
|
||||||
|
@ -409,6 +416,9 @@ impl Session {
|
||||||
pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
|
pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
|
||||||
err.into_diagnostic(self).emit()
|
err.into_diagnostic(self).emit()
|
||||||
}
|
}
|
||||||
|
pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) {
|
||||||
|
warning.into_diagnostic(self).emit()
|
||||||
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn err_count(&self) -> usize {
|
pub fn err_count(&self) -> usize {
|
||||||
self.diagnostic().err_count()
|
self.diagnostic().err_count()
|
||||||
|
|
|
@ -3,9 +3,9 @@ use rustc_macros::SessionDiagnostic;
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0062"]
|
#[error(code = "E0062", slug = "typeck-field-multiply-specified-in-initializer")]
|
||||||
pub struct FieldMultiplySpecifiedInInitializer {
|
pub struct FieldMultiplySpecifiedInInitializer {
|
||||||
#[message = "field `{ident}` specified more than once"]
|
#[message]
|
||||||
#[label = "used more than once"]
|
#[label = "used more than once"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "first use of `{ident}`"]
|
#[label = "first use of `{ident}`"]
|
||||||
|
@ -14,19 +14,18 @@ pub struct FieldMultiplySpecifiedInInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0092"]
|
#[error(code = "E0092", slug = "typeck-unrecognized-atomic-operation")]
|
||||||
pub struct UnrecognizedAtomicOperation<'a> {
|
pub struct UnrecognizedAtomicOperation<'a> {
|
||||||
#[message = "unrecognized atomic operation function: `{op}`"]
|
#[message]
|
||||||
#[label = "unrecognized atomic operation"]
|
#[label = "unrecognized atomic operation"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub op: &'a str,
|
pub op: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0094"]
|
#[error(code = "E0094", slug = "typeck-wrong-number-of-generic-arguments-to-intrinsic")]
|
||||||
pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
||||||
#[message = "intrinsic has wrong number of {descr} \
|
#[message]
|
||||||
parameters: found {found}, expected {expected}"]
|
|
||||||
#[label = "expected {expected} {descr} parameter{expected_pluralize}"]
|
#[label = "expected {expected} {descr} parameter{expected_pluralize}"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub found: usize,
|
pub found: usize,
|
||||||
|
@ -36,18 +35,18 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0093"]
|
#[error(code = "E0093", slug = "typeck-unrecognized-intrinsic-function")]
|
||||||
pub struct UnrecognizedIntrinsicFunction {
|
pub struct UnrecognizedIntrinsicFunction {
|
||||||
#[message = "unrecognized intrinsic function: `{name}`"]
|
#[message]
|
||||||
#[label = "unrecognized intrinsic"]
|
#[label = "unrecognized intrinsic"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0195"]
|
#[error(code = "E0195", slug = "typeck-lifetimes-or-bounds-mismatch-on-trait")]
|
||||||
pub struct LifetimesOrBoundsMismatchOnTrait {
|
pub struct LifetimesOrBoundsMismatchOnTrait {
|
||||||
#[message = "lifetime parameters or bounds on {item_kind} `{ident}` do not match the trait declaration"]
|
#[message]
|
||||||
#[label = "lifetimes do not match {item_kind} in trait"]
|
#[label = "lifetimes do not match {item_kind} in trait"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "lifetimes in impl do not match this {item_kind} in trait"]
|
#[label = "lifetimes in impl do not match this {item_kind} in trait"]
|
||||||
|
@ -57,18 +56,18 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0120"]
|
#[error(code = "E0120", slug = "typeck-drop-impl-on-wrong-item")]
|
||||||
pub struct DropImplOnWrongItem {
|
pub struct DropImplOnWrongItem {
|
||||||
#[message = "the `Drop` trait may only be implemented for structs, enums, and unions"]
|
#[message]
|
||||||
#[label = "must be a struct, enum, or union"]
|
#[label = "must be a struct, enum, or union"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0124"]
|
#[error(code = "E0124", slug = "typeck-field-already-declared")]
|
||||||
pub struct FieldAlreadyDeclared {
|
pub struct FieldAlreadyDeclared {
|
||||||
pub field_name: Ident,
|
pub field_name: Ident,
|
||||||
#[message = "field `{field_name}` is already declared"]
|
#[message]
|
||||||
#[label = "field already declared"]
|
#[label = "field already declared"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "`{field_name}` first declared here"]
|
#[label = "`{field_name}` first declared here"]
|
||||||
|
@ -76,70 +75,69 @@ pub struct FieldAlreadyDeclared {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0184"]
|
#[error(code = "E0184", slug = "typeck-copy-impl-on-type-with-dtor")]
|
||||||
pub struct CopyImplOnTypeWithDtor {
|
pub struct CopyImplOnTypeWithDtor {
|
||||||
#[message = "the trait `Copy` may not be implemented for this type; the \
|
#[message]
|
||||||
type has a destructor"]
|
|
||||||
#[label = "Copy not allowed on types with destructors"]
|
#[label = "Copy not allowed on types with destructors"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0203"]
|
#[error(code = "E0203", slug = "typeck-multiple-relaxed-default-bounds")]
|
||||||
pub struct MultipleRelaxedDefaultBounds {
|
pub struct MultipleRelaxedDefaultBounds {
|
||||||
#[message = "type parameter has more than one relaxed default bound, only one is supported"]
|
#[message]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0206"]
|
#[error(code = "E0206", slug = "typeck-copy-impl-on-non-adt")]
|
||||||
pub struct CopyImplOnNonAdt {
|
pub struct CopyImplOnNonAdt {
|
||||||
#[message = "the trait `Copy` may not be implemented for this type"]
|
#[message]
|
||||||
#[label = "type is not a structure or enumeration"]
|
#[label = "type is not a structure or enumeration"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0224"]
|
#[error(code = "E0224", slug = "typeck-trait-object-declared-with-no-traits")]
|
||||||
pub struct TraitObjectDeclaredWithNoTraits {
|
pub struct TraitObjectDeclaredWithNoTraits {
|
||||||
#[message = "at least one trait is required for an object type"]
|
#[message]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0227"]
|
#[error(code = "E0227", slug = "typeck-ambiguous-lifetime-bound")]
|
||||||
pub struct AmbiguousLifetimeBound {
|
pub struct AmbiguousLifetimeBound {
|
||||||
#[message = "ambiguous lifetime bound, explicit lifetime bound required"]
|
#[message]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0229"]
|
#[error(code = "E0229", slug = "typeck-assoc-type-binding-not-allowed")]
|
||||||
pub struct AssocTypeBindingNotAllowed {
|
pub struct AssocTypeBindingNotAllowed {
|
||||||
#[message = "associated type bindings are not allowed here"]
|
#[message]
|
||||||
#[label = "associated type not allowed here"]
|
#[label = "associated type not allowed here"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0436"]
|
#[error(code = "E0436", slug = "typeck-functional-record-update-on-non-struct")]
|
||||||
pub struct FunctionalRecordUpdateOnNonStruct {
|
pub struct FunctionalRecordUpdateOnNonStruct {
|
||||||
#[message = "functional record update syntax requires a struct"]
|
#[message]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0516"]
|
#[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")]
|
||||||
pub struct TypeofReservedKeywordUsed {
|
pub struct TypeofReservedKeywordUsed {
|
||||||
#[message = "`typeof` is a reserved keyword but unimplemented"]
|
#[message]
|
||||||
#[label = "reserved keyword"]
|
#[label = "reserved keyword"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0572"]
|
#[error(code = "E0572", slug = "typeck-return-stmt-outside-of-fn-body")]
|
||||||
pub struct ReturnStmtOutsideOfFnBody {
|
pub struct ReturnStmtOutsideOfFnBody {
|
||||||
#[message = "return statement outside of function body"]
|
#[message]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "the return is part of this body..."]
|
#[label = "the return is part of this body..."]
|
||||||
pub encl_body_span: Option<Span>,
|
pub encl_body_span: Option<Span>,
|
||||||
|
@ -148,31 +146,31 @@ pub struct ReturnStmtOutsideOfFnBody {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0627"]
|
#[error(code = "E0627", slug = "typeck-yield-expr-outside-of-generator")]
|
||||||
pub struct YieldExprOutsideOfGenerator {
|
pub struct YieldExprOutsideOfGenerator {
|
||||||
#[message = "yield expression outside of generator literal"]
|
#[message]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0639"]
|
#[error(code = "E0639", slug = "typeck-struct-expr-non-exhaustive")]
|
||||||
pub struct StructExprNonExhaustive {
|
pub struct StructExprNonExhaustive {
|
||||||
#[message = "cannot create non-exhaustive {what} using struct expression"]
|
#[message]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub what: &'static str,
|
pub what: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0699"]
|
#[error(code = "E0699", slug = "typeck-method-call-on-unknown-type")]
|
||||||
pub struct MethodCallOnUnknownType {
|
pub struct MethodCallOnUnknownType {
|
||||||
#[message = "the type of this value must be known to call a method on a raw pointer on it"]
|
#[message]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0719"]
|
#[error(code = "E0719", slug = "typeck-value-of-associated-struct-already-specified")]
|
||||||
pub struct ValueOfAssociatedStructAlreadySpecified {
|
pub struct ValueOfAssociatedStructAlreadySpecified {
|
||||||
#[message = "the value of the associated type `{item_name}` (from trait `{def_path}`) is already specified"]
|
#[message]
|
||||||
#[label = "re-bound here"]
|
#[label = "re-bound here"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "`{item_name}` bound here first"]
|
#[label = "`{item_name}` bound here first"]
|
||||||
|
@ -182,9 +180,9 @@ pub struct ValueOfAssociatedStructAlreadySpecified {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0745"]
|
#[error(code = "E0745", slug = "typeck-address-of-temporary-taken")]
|
||||||
pub struct AddressOfTemporaryTaken {
|
pub struct AddressOfTemporaryTaken {
|
||||||
#[message = "cannot take address of a temporary"]
|
#[message]
|
||||||
#[label = "temporary value"]
|
#[label = "temporary value"]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,15 @@ use rustc_errors::Applicability;
|
||||||
extern crate rustc_session;
|
extern crate rustc_session;
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[message = "Hello, world!"]
|
#[error(code = "E0123", slug = "hello-world")]
|
||||||
#[error = "E0123"]
|
|
||||||
struct Hello {}
|
struct Hello {}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[warning(code = "E0123", slug = "hello-world")]
|
||||||
|
struct HelloWarn {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
//~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs
|
//~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs
|
||||||
enum SessionDiagnosticOnEnum {
|
enum SessionDiagnosticOnEnum {
|
||||||
Foo,
|
Foo,
|
||||||
|
@ -39,13 +42,46 @@ enum SessionDiagnosticOnEnum {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[error = "E0123"]
|
#[error = "E0123"]
|
||||||
#[label = "This is in the wrong place"]
|
//~^ ERROR `#[error = ...]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
//~^ ERROR `#[label = ...]` is not a valid `SessionDiagnostic` struct attribute
|
struct WrongStructAttrStyle {}
|
||||||
struct WrongPlace {}
|
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[nonsense(code = "E0123", slug = "foo")]
|
||||||
|
//~^ ERROR `#[nonsense(...)]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
//~^^ ERROR diagnostic kind not specified
|
||||||
|
//~^^^ ERROR cannot find attribute `nonsense` in this scope
|
||||||
|
struct InvalidStructAttr {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error("E0123")]
|
||||||
|
//~^ ERROR `#[error("...")]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
//~^^ ERROR `slug` not specified
|
||||||
|
struct InvalidLitNestedAttr {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(nonsense, code = "E0123", slug = "foo")]
|
||||||
|
//~^ ERROR `#[error(nonsense)]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
struct InvalidNestedStructAttr {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(nonsense("foo"), code = "E0123", slug = "foo")]
|
||||||
|
//~^ ERROR `#[error(nonsense(...))]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
struct InvalidNestedStructAttr1 {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(nonsense = "...", code = "E0123", slug = "foo")]
|
||||||
|
//~^ ERROR `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
struct InvalidNestedStructAttr2 {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(nonsense = 4, code = "E0123", slug = "foo")]
|
||||||
|
//~^ ERROR `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
struct InvalidNestedStructAttr3 {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct WrongPlaceField {
|
struct WrongPlaceField {
|
||||||
#[suggestion = "this is the wrong kind of attribute"]
|
#[suggestion = "this is the wrong kind of attribute"]
|
||||||
//~^ ERROR `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute
|
//~^ ERROR `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute
|
||||||
|
@ -53,101 +89,113 @@ struct WrongPlaceField {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[message = "Hello, world!"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0456", slug = "bar")] //~ ERROR `error` specified multiple times
|
||||||
#[error = "E0456"] //~ ERROR `error` specified multiple times
|
|
||||||
struct ErrorSpecifiedTwice {}
|
struct ErrorSpecifiedTwice {}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[message = "Hello, world!"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[error = "E0123"]
|
#[warning(code = "E0293", slug = "bar")]
|
||||||
#[lint = "some_useful_lint"] //~ ERROR `lint` specified when `error` was already specified
|
//~^ ERROR `warning` specified when `error` was already specified
|
||||||
struct LintSpecifiedAfterError {}
|
struct WarnSpecifiedAfterError {}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[message = "Some lint message"]
|
#[error(code = "E0456", code = "E0457", slug = "bar")] //~ ERROR `code` specified multiple times
|
||||||
#[error = "E0123"]
|
struct CodeSpecifiedTwice {}
|
||||||
struct LintButHasErrorCode {}
|
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
struct ErrorCodeNotProvided {} //~ ERROR `code` not specified
|
#[error(code = "E0456", slug = "foo", slug = "bar")] //~ ERROR `slug` specified multiple times
|
||||||
|
struct SlugSpecifiedTwice {}
|
||||||
// FIXME: Uncomment when emitting lints is supported.
|
|
||||||
/*
|
|
||||||
#[derive(SessionDiagnostic)]
|
|
||||||
#[message = "Hello, world!"]
|
|
||||||
#[lint = "clashing_extern_declarations"]
|
|
||||||
#[lint = "improper_ctypes"] // FIXME: ERROR `lint` specified multiple times
|
|
||||||
struct LintSpecifiedTwice {}
|
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[lint = "Some lint message"]
|
struct KindNotProvided {} //~ ERROR diagnostic kind not specified
|
||||||
#[message = "Some error message"]
|
|
||||||
#[error = "E0123"] // ERROR `error` specified when `lint` was already specified
|
|
||||||
struct ErrorSpecifiedAfterLint {}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0456")] //~ ERROR `slug` not specified
|
||||||
|
struct SlugNotProvided {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(slug = "foo")] //~ ERROR `code` not specified
|
||||||
|
struct CodeNotProvided {}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
|
struct MessageWrongType {
|
||||||
|
#[message]
|
||||||
|
//~^ ERROR `#[message]` attribute can only be applied to fields of type `Span`
|
||||||
|
foo: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
|
struct InvalidPathFieldAttr {
|
||||||
|
#[nonsense]
|
||||||
|
//~^ ERROR `#[nonsense]` is not a valid `SessionDiagnostic` field attribute
|
||||||
|
//~^^ ERROR cannot find attribute `nonsense` in this scope
|
||||||
|
foo: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorWithField {
|
struct ErrorWithField {
|
||||||
name: String,
|
name: String,
|
||||||
#[message = "This error has a field, and references {name}"]
|
#[label = "This error has a field, and references {name}"]
|
||||||
span: Span,
|
span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorWithMessageAppliedToField {
|
struct ErrorWithMessageAppliedToField {
|
||||||
#[message = "this message is applied to a String field"]
|
#[label = "this message is applied to a String field"]
|
||||||
//~^ ERROR the `#[message = "..."]` attribute can only be applied to fields of type `Span`
|
//~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[message = "This error has a field, and references {name}"]
|
|
||||||
//~^ ERROR `name` doesn't refer to a field on this type
|
|
||||||
struct ErrorWithNonexistentField {
|
struct ErrorWithNonexistentField {
|
||||||
descr: String,
|
#[label = "This error has a field, and references {name}"]
|
||||||
|
//~^ ERROR `name` doesn't refer to a field on this type
|
||||||
|
foo: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[message = "This is missing a closing brace: {name"]
|
|
||||||
//~^ ERROR invalid format string: expected `'}'`
|
//~^ ERROR invalid format string: expected `'}'`
|
||||||
struct ErrorMissingClosingBrace {
|
struct ErrorMissingClosingBrace {
|
||||||
|
#[label = "This is missing a closing brace: {name"]
|
||||||
|
foo: Span,
|
||||||
name: String,
|
name: String,
|
||||||
val: usize,
|
val: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[message = "This is missing an opening brace: name}"]
|
|
||||||
//~^ ERROR invalid format string: unmatched `}`
|
//~^ ERROR invalid format string: unmatched `}`
|
||||||
struct ErrorMissingOpeningBrace {
|
struct ErrorMissingOpeningBrace {
|
||||||
|
#[label = "This is missing an opening brace: name}"]
|
||||||
|
foo: Span,
|
||||||
name: String,
|
name: String,
|
||||||
val: usize,
|
val: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[message = "Something something"]
|
|
||||||
struct LabelOnSpan {
|
struct LabelOnSpan {
|
||||||
#[label = "See here"]
|
#[label = "See here"]
|
||||||
sp: Span,
|
sp: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[message = "Something something"]
|
|
||||||
struct LabelOnNonSpan {
|
struct LabelOnNonSpan {
|
||||||
#[label = "See here"]
|
#[label = "See here"]
|
||||||
//~^ ERROR The `#[label = ...]` attribute can only be applied to fields of type `Span`
|
//~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||||
id: u32,
|
id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct Suggest {
|
struct Suggest {
|
||||||
#[suggestion(message = "This is a suggestion", code = "This is the suggested code")]
|
#[suggestion(message = "This is a suggestion", code = "This is the suggested code")]
|
||||||
#[suggestion_short(message = "This is a suggestion", code = "This is the suggested code")]
|
#[suggestion_short(message = "This is a suggestion", code = "This is the suggested code")]
|
||||||
|
@ -157,14 +205,14 @@ struct Suggest {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithoutCode {
|
struct SuggestWithoutCode {
|
||||||
#[suggestion(message = "This is a suggestion")]
|
#[suggestion(message = "This is a suggestion")]
|
||||||
suggestion: (Span, Applicability),
|
suggestion: (Span, Applicability),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithBadKey {
|
struct SuggestWithBadKey {
|
||||||
#[suggestion(nonsense = "This is nonsense")]
|
#[suggestion(nonsense = "This is nonsense")]
|
||||||
//~^ ERROR `nonsense` is not a valid key for `#[suggestion(...)]`
|
//~^ ERROR `nonsense` is not a valid key for `#[suggestion(...)]`
|
||||||
|
@ -172,7 +220,7 @@ struct SuggestWithBadKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithShorthandMsg {
|
struct SuggestWithShorthandMsg {
|
||||||
#[suggestion(msg = "This is a suggestion")]
|
#[suggestion(msg = "This is a suggestion")]
|
||||||
//~^ ERROR `msg` is not a valid key for `#[suggestion(...)]`
|
//~^ ERROR `msg` is not a valid key for `#[suggestion(...)]`
|
||||||
|
@ -180,7 +228,7 @@ struct SuggestWithShorthandMsg {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithoutMsg {
|
struct SuggestWithoutMsg {
|
||||||
#[suggestion(code = "This is suggested code")]
|
#[suggestion(code = "This is suggested code")]
|
||||||
//~^ ERROR missing suggestion message
|
//~^ ERROR missing suggestion message
|
||||||
|
@ -188,14 +236,14 @@ struct SuggestWithoutMsg {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithTypesSwapped {
|
struct SuggestWithTypesSwapped {
|
||||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||||
suggestion: (Applicability, Span),
|
suggestion: (Applicability, Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithWrongTypeApplicabilityOnly {
|
struct SuggestWithWrongTypeApplicabilityOnly {
|
||||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||||
//~^ ERROR wrong field type for suggestion
|
//~^ ERROR wrong field type for suggestion
|
||||||
|
@ -203,14 +251,14 @@ struct SuggestWithWrongTypeApplicabilityOnly {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithSpanOnly {
|
struct SuggestWithSpanOnly {
|
||||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||||
suggestion: Span,
|
suggestion: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithDuplicateSpanAndApplicability {
|
struct SuggestWithDuplicateSpanAndApplicability {
|
||||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||||
//~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
|
//~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
|
||||||
|
@ -218,7 +266,7 @@ struct SuggestWithDuplicateSpanAndApplicability {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct SuggestWithDuplicateApplicabilityAndSpan {
|
struct SuggestWithDuplicateApplicabilityAndSpan {
|
||||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||||
//~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one
|
//~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one
|
||||||
|
@ -226,7 +274,7 @@ struct SuggestWithDuplicateApplicabilityAndSpan {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct WrongKindOfAnnotation {
|
struct WrongKindOfAnnotation {
|
||||||
#[label("wrong kind of annotation for label")]
|
#[label("wrong kind of annotation for label")]
|
||||||
//~^ ERROR invalid annotation list `#[label(...)]`
|
//~^ ERROR invalid annotation list `#[label(...)]`
|
||||||
|
@ -234,8 +282,7 @@ struct WrongKindOfAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
#[message = "Something something else"]
|
|
||||||
struct OptionsInErrors {
|
struct OptionsInErrors {
|
||||||
#[label = "Label message"]
|
#[label = "Label message"]
|
||||||
label: Option<Span>,
|
label: Option<Span>,
|
||||||
|
@ -244,11 +291,11 @@ struct OptionsInErrors {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0456"]
|
#[error(code = "E0456", slug = "foo")]
|
||||||
struct MoveOutOfBorrowError<'tcx> {
|
struct MoveOutOfBorrowError<'tcx> {
|
||||||
name: Ident,
|
name: Ident,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
#[message = "cannot move {ty} out of borrow"]
|
#[message]
|
||||||
#[label = "cannot move out of borrow"]
|
#[label = "cannot move out of borrow"]
|
||||||
span: Span,
|
span: Span,
|
||||||
#[label = "`{ty}` first borrowed here"]
|
#[label = "`{ty}` first borrowed here"]
|
||||||
|
@ -258,9 +305,9 @@ struct MoveOutOfBorrowError<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error = "E0123"]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorWithLifetime<'a> {
|
struct ErrorWithLifetime<'a> {
|
||||||
#[message = "Some message that references {name}"]
|
#[label = "Some message that references {name}"]
|
||||||
span: Span,
|
span: Span,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
error: `#[derive(SessionDiagnostic)]` can only be used on structs
|
error: `#[derive(SessionDiagnostic)]` can only be used on structs
|
||||||
--> $DIR/session-derive-errors.rs:34:1
|
--> $DIR/session-derive-errors.rs:37:1
|
||||||
|
|
|
|
||||||
LL | / #[error = "E0123"]
|
LL | / #[error(code = "E0123", slug = "foo")]
|
||||||
LL | |
|
LL | |
|
||||||
LL | | enum SessionDiagnosticOnEnum {
|
LL | | enum SessionDiagnosticOnEnum {
|
||||||
LL | | Foo,
|
LL | | Foo,
|
||||||
|
@ -9,95 +9,221 @@ LL | | Bar,
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_^
|
| |_^
|
||||||
|
|
||||||
error: `#[label = ...]` is not a valid `SessionDiagnostic` struct attribute
|
error: `#[error = ...]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
--> $DIR/session-derive-errors.rs:43:1
|
--> $DIR/session-derive-errors.rs:46:1
|
||||||
|
|
|
|
||||||
LL | #[label = "This is in the wrong place"]
|
LL | #[error = "E0123"]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[nonsense(...)]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
--> $DIR/session-derive-errors.rs:51:1
|
||||||
|
|
|
||||||
|
LL | #[nonsense(code = "E0123", slug = "foo")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: diagnostic kind not specified
|
||||||
|
--> $DIR/session-derive-errors.rs:51:1
|
||||||
|
|
|
||||||
|
LL | / #[nonsense(code = "E0123", slug = "foo")]
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | struct InvalidStructAttr {}
|
||||||
|
| |___________________________^
|
||||||
|
|
|
||||||
|
= help: use the `#[error(...)]` attribute to create an error
|
||||||
|
|
||||||
|
error: `#[error("...")]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
--> $DIR/session-derive-errors.rs:58:9
|
||||||
|
|
|
||||||
|
LL | #[error("E0123")]
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: `slug` not specified
|
||||||
|
--> $DIR/session-derive-errors.rs:58:1
|
||||||
|
|
|
||||||
|
LL | / #[error("E0123")]
|
||||||
|
LL | |
|
||||||
|
LL | |
|
||||||
|
LL | | struct InvalidLitNestedAttr {}
|
||||||
|
| |______________________________^
|
||||||
|
|
|
||||||
|
= help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug
|
||||||
|
|
||||||
|
error: `#[error(nonsense)]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
--> $DIR/session-derive-errors.rs:64:9
|
||||||
|
|
|
||||||
|
LL | #[error(nonsense, code = "E0123", slug = "foo")]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[error(nonsense(...))]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
--> $DIR/session-derive-errors.rs:69:9
|
||||||
|
|
|
||||||
|
LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
--> $DIR/session-derive-errors.rs:74:9
|
||||||
|
|
|
||||||
|
LL | #[error(nonsense = "...", code = "E0123", slug = "foo")]
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[error(nonsense = ...)]` is not a valid `SessionDiagnostic` struct attribute
|
||||||
|
--> $DIR/session-derive-errors.rs:79:9
|
||||||
|
|
|
||||||
|
LL | #[error(nonsense = 4, code = "E0123", slug = "foo")]
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: value must be a string
|
||||||
|
|
||||||
error: `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute
|
error: `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute
|
||||||
--> $DIR/session-derive-errors.rs:50:5
|
--> $DIR/session-derive-errors.rs:86:5
|
||||||
|
|
|
|
||||||
LL | #[suggestion = "this is the wrong kind of attribute"]
|
LL | #[suggestion = "this is the wrong kind of attribute"]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `error` specified multiple times
|
error: `error` specified multiple times
|
||||||
--> $DIR/session-derive-errors.rs:58:11
|
--> $DIR/session-derive-errors.rs:93:1
|
||||||
|
|
|
|
||||||
LL | #[error = "E0456"]
|
LL | #[error(code = "E0456", slug = "bar")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: previously specified here
|
||||||
|
--> $DIR/session-derive-errors.rs:92:1
|
||||||
|
|
|
||||||
|
LL | #[error(code = "E0123", slug = "foo")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `warning` specified when `error` was already specified
|
||||||
|
--> $DIR/session-derive-errors.rs:98:1
|
||||||
|
|
|
||||||
|
LL | #[warning(code = "E0293", slug = "bar")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: previously specified here
|
||||||
|
--> $DIR/session-derive-errors.rs:97:1
|
||||||
|
|
|
||||||
|
LL | #[error(code = "E0123", slug = "foo")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `code` specified multiple times
|
||||||
|
--> $DIR/session-derive-errors.rs:103:32
|
||||||
|
|
|
||||||
|
LL | #[error(code = "E0456", code = "E0457", slug = "bar")]
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
note: previously specified here
|
||||||
|
--> $DIR/session-derive-errors.rs:103:16
|
||||||
|
|
|
||||||
|
LL | #[error(code = "E0456", code = "E0457", slug = "bar")]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: `lint` specified when `error` was already specified
|
error: `slug` specified multiple times
|
||||||
--> $DIR/session-derive-errors.rs:64:10
|
--> $DIR/session-derive-errors.rs:107:46
|
||||||
|
|
|
|
||||||
LL | #[lint = "some_useful_lint"]
|
LL | #[error(code = "E0456", slug = "foo", slug = "bar")]
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^
|
||||||
|
|
|
||||||
|
note: previously specified here
|
||||||
|
--> $DIR/session-derive-errors.rs:107:32
|
||||||
|
|
|
||||||
|
LL | #[error(code = "E0456", slug = "foo", slug = "bar")]
|
||||||
|
| ^^^^^
|
||||||
|
|
||||||
|
error: diagnostic kind not specified
|
||||||
|
--> $DIR/session-derive-errors.rs:111:1
|
||||||
|
|
|
||||||
|
LL | struct KindNotProvided {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: use the `#[error(...)]` attribute to create an error
|
||||||
|
|
||||||
|
error: `slug` not specified
|
||||||
|
--> $DIR/session-derive-errors.rs:114:1
|
||||||
|
|
|
||||||
|
LL | / #[error(code = "E0456")]
|
||||||
|
LL | | struct SlugNotProvided {}
|
||||||
|
| |_________________________^
|
||||||
|
|
|
||||||
|
= help: use the `#[error(slug = "...")]` attribute to set this diagnostic's slug
|
||||||
|
|
||||||
error: `code` not specified
|
error: `code` not specified
|
||||||
--> $DIR/session-derive-errors.rs:73:1
|
--> $DIR/session-derive-errors.rs:118:1
|
||||||
|
|
|
|
||||||
LL | struct ErrorCodeNotProvided {}
|
LL | / #[error(slug = "foo")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
LL | | struct CodeNotProvided {}
|
||||||
|
| |_________________________^
|
||||||
|
|
|
|
||||||
= help: use the `#[code = "..."]` attribute to set this diagnostic's error code
|
= help: use the `#[error(code = "...")]` attribute to set this diagnostic's error code
|
||||||
|
|
||||||
error: the `#[message = "..."]` attribute can only be applied to fields of type `Span`
|
error: the `#[message]` attribute can only be applied to fields of type `Span`
|
||||||
--> $DIR/session-derive-errors.rs:101:5
|
--> $DIR/session-derive-errors.rs:124:5
|
||||||
|
|
|
|
||||||
LL | #[message = "this message is applied to a String field"]
|
LL | #[message]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[nonsense]` is not a valid `SessionDiagnostic` field attribute
|
||||||
|
--> $DIR/session-derive-errors.rs:132:5
|
||||||
|
|
|
||||||
|
LL | #[nonsense]
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||||
|
--> $DIR/session-derive-errors.rs:149:5
|
||||||
|
|
|
||||||
|
LL | #[label = "this message is applied to a String field"]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `name` doesn't refer to a field on this type
|
error: `name` doesn't refer to a field on this type
|
||||||
--> $DIR/session-derive-errors.rs:108:1
|
--> $DIR/session-derive-errors.rs:157:5
|
||||||
|
|
|
|
||||||
LL | #[message = "This error has a field, and references {name}"]
|
LL | #[label = "This error has a field, and references {name}"]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: invalid format string: expected `'}'` but string was terminated
|
error: invalid format string: expected `'}'` but string was terminated
|
||||||
--> $DIR/session-derive-errors.rs:116:1
|
--> $DIR/session-derive-errors.rs:163:20
|
||||||
|
|
|
|
||||||
LL | #[derive(SessionDiagnostic)]
|
LL | #[derive(SessionDiagnostic)]
|
||||||
| ----------------- in this derive macro expansion
|
| ----------------- in this derive macro expansion
|
||||||
LL | #[error = "E0123"]
|
LL | #[error(code = "E0123", slug = "foo")]
|
||||||
| - because of this opening brace
|
| - ^ expected `'}'` in format string
|
||||||
LL | #[message = "This is missing a closing brace: {name"]
|
| |
|
||||||
| ^ expected `'}'` in format string
|
| because of this opening brace
|
||||||
|
|
|
|
||||||
= note: if you intended to print `{`, you can escape it using `{{`
|
= note: if you intended to print `{`, you can escape it using `{{`
|
||||||
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: invalid format string: unmatched `}` found
|
error: invalid format string: unmatched `}` found
|
||||||
--> $DIR/session-derive-errors.rs:125:1
|
--> $DIR/session-derive-errors.rs:173:20
|
||||||
|
|
|
|
||||||
LL | #[derive(SessionDiagnostic)]
|
LL | #[derive(SessionDiagnostic)]
|
||||||
| ----------------- in this derive macro expansion
|
| ----------------- in this derive macro expansion
|
||||||
LL | #[error = "E0123"]
|
LL | #[error(code = "E0123", slug = "foo")]
|
||||||
LL | #[message = "This is missing an opening brace: name}"]
|
|
||||||
| ^ unmatched `}` in format string
|
| ^ unmatched `}` in format string
|
||||||
|
|
|
|
||||||
= note: if you intended to print `}`, you can escape it using `}}`
|
= note: if you intended to print `}`, you can escape it using `}}`
|
||||||
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: The `#[label = ...]` attribute can only be applied to fields of type `Span`
|
error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||||
--> $DIR/session-derive-errors.rs:144:5
|
--> $DIR/session-derive-errors.rs:192:5
|
||||||
|
|
|
|
||||||
LL | #[label = "See here"]
|
LL | #[label = "See here"]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `nonsense` is not a valid key for `#[suggestion(...)]`
|
error: `nonsense` is not a valid key for `#[suggestion(...)]`
|
||||||
--> $DIR/session-derive-errors.rs:169:18
|
--> $DIR/session-derive-errors.rs:217:18
|
||||||
|
|
|
|
||||||
LL | #[suggestion(nonsense = "This is nonsense")]
|
LL | #[suggestion(nonsense = "This is nonsense")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `msg` is not a valid key for `#[suggestion(...)]`
|
error: `msg` is not a valid key for `#[suggestion(...)]`
|
||||||
--> $DIR/session-derive-errors.rs:177:18
|
--> $DIR/session-derive-errors.rs:225:18
|
||||||
|
|
|
|
||||||
LL | #[suggestion(msg = "This is a suggestion")]
|
LL | #[suggestion(msg = "This is a suggestion")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: missing suggestion message
|
error: missing suggestion message
|
||||||
--> $DIR/session-derive-errors.rs:185:7
|
--> $DIR/session-derive-errors.rs:233:7
|
||||||
|
|
|
|
||||||
LL | #[suggestion(code = "This is suggested code")]
|
LL | #[suggestion(code = "This is suggested code")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -105,7 +231,7 @@ LL | #[suggestion(code = "This is suggested code")]
|
||||||
= help: provide a suggestion message using `#[suggestion(message = "...")]`
|
= help: provide a suggestion message using `#[suggestion(message = "...")]`
|
||||||
|
|
||||||
error: wrong field type for suggestion
|
error: wrong field type for suggestion
|
||||||
--> $DIR/session-derive-errors.rs:200:5
|
--> $DIR/session-derive-errors.rs:248:5
|
||||||
|
|
|
|
||||||
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
|
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -115,7 +241,7 @@ LL | | suggestion: Applicability,
|
||||||
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
|
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
|
||||||
|
|
||||||
error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
|
error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
|
||||||
--> $DIR/session-derive-errors.rs:215:5
|
--> $DIR/session-derive-errors.rs:263:5
|
||||||
|
|
|
|
||||||
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
|
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -123,7 +249,7 @@ LL | | suggestion: (Span, Span, Applicability),
|
||||||
| |___________________________________________^
|
| |___________________________________________^
|
||||||
|
|
||||||
error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
|
error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
|
||||||
--> $DIR/session-derive-errors.rs:223:5
|
--> $DIR/session-derive-errors.rs:271:5
|
||||||
|
|
|
|
||||||
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
|
LL | / #[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -131,10 +257,22 @@ LL | | suggestion: (Applicability, Applicability, Span),
|
||||||
| |____________________________________________________^
|
| |____________________________________________________^
|
||||||
|
|
||||||
error: invalid annotation list `#[label(...)]`
|
error: invalid annotation list `#[label(...)]`
|
||||||
--> $DIR/session-derive-errors.rs:231:7
|
--> $DIR/session-derive-errors.rs:279:7
|
||||||
|
|
|
|
||||||
LL | #[label("wrong kind of annotation for label")]
|
LL | #[label("wrong kind of annotation for label")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 18 previous errors
|
error: cannot find attribute `nonsense` in this scope
|
||||||
|
--> $DIR/session-derive-errors.rs:51:3
|
||||||
|
|
|
||||||
|
LL | #[nonsense(code = "E0123", slug = "foo")]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: cannot find attribute `nonsense` in this scope
|
||||||
|
--> $DIR/session-derive-errors.rs:132:7
|
||||||
|
|
|
||||||
|
LL | #[nonsense]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 34 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue