mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
macros: translatable struct attrs and warnings
Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
f0de7df204
commit
d0fd8d7880
@ -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
|
||||
|
||||
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,
|
||||
args: &'a FluentArgs<'_>,
|
||||
) -> Cow<'_, str> {
|
||||
trace!(?message);
|
||||
trace!(?message, ?args);
|
||||
let (identifier, attr) = match message {
|
||||
DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
|
||||
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||
@ -283,7 +283,13 @@ pub trait Emitter {
|
||||
let mut err = vec![];
|
||||
let translated = bundle.format_pattern(value, Some(&args), &mut err);
|
||||
trace!(?translated, ?err);
|
||||
debug_assert!(err.is_empty());
|
||||
debug_assert!(
|
||||
err.is_empty(),
|
||||
"identifier: {:?}, args: {:?}, errors: {:?}",
|
||||
identifier,
|
||||
args,
|
||||
err
|
||||
);
|
||||
translated
|
||||
}
|
||||
|
||||
|
@ -777,6 +777,17 @@ impl Handler {
|
||||
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`.
|
||||
pub fn struct_span_fatal(
|
||||
&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!(
|
||||
[SessionDiagnostic, attributes(
|
||||
message,
|
||||
lint,
|
||||
// struct attributes
|
||||
warning,
|
||||
error,
|
||||
// nested parts of struct attributes
|
||||
code,
|
||||
slug,
|
||||
// field attributes
|
||||
message,
|
||||
label,
|
||||
suggestion,
|
||||
suggestion_short,
|
||||
|
@ -16,11 +16,11 @@ use std::collections::{BTreeSet, HashMap};
|
||||
/// # extern crate rust_middle;
|
||||
/// # use rustc_middle::ty::Ty;
|
||||
/// #[derive(SessionDiagnostic)]
|
||||
/// #[code = "E0505"]
|
||||
/// #[error = "cannot move out of {name} because it is borrowed"]
|
||||
/// #[error(code = "E0505", slug = "move-out-of-borrow-error")]
|
||||
/// pub struct MoveOutOfBorrowError<'tcx> {
|
||||
/// pub name: Ident,
|
||||
/// pub ty: Ty<'tcx>,
|
||||
/// #[message]
|
||||
/// #[label = "cannot move out of borrow"]
|
||||
/// pub span: Span,
|
||||
/// #[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)]
|
||||
enum SessionDiagnosticDeriveError {
|
||||
SynError(syn::Error),
|
||||
@ -100,7 +93,7 @@ impl SessionDiagnosticDeriveError {
|
||||
// Return ! to avoid having to create a blank DiagnosticBuilder to return when an
|
||||
// error has already been emitted to the compiler.
|
||||
quote! {
|
||||
unreachable!()
|
||||
{ unreachable!(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,17 +145,25 @@ impl<'a> SessionDiagnosticDerive<'a> {
|
||||
}
|
||||
|
||||
Self {
|
||||
builder: SessionDiagnosticDeriveBuilder { diag, sess, fields: fields_map, kind: None },
|
||||
builder: SessionDiagnosticDeriveBuilder {
|
||||
diag,
|
||||
sess,
|
||||
fields: fields_map,
|
||||
kind: None,
|
||||
code: None,
|
||||
slug: None,
|
||||
},
|
||||
structure,
|
||||
}
|
||||
}
|
||||
|
||||
fn into_tokens(self) -> proc_macro2::TokenStream {
|
||||
let SessionDiagnosticDerive { mut structure, mut builder } = self;
|
||||
|
||||
let ast = structure.ast();
|
||||
let attrs = &ast.attrs;
|
||||
|
||||
let implementation = {
|
||||
let (implementation, param_ty) = {
|
||||
if let syn::Data::Struct(..) = ast.data {
|
||||
let preamble = {
|
||||
let preamble = attrs.iter().map(|attr| {
|
||||
@ -170,6 +171,7 @@ impl<'a> SessionDiagnosticDerive<'a> {
|
||||
.generate_structure_code(attr)
|
||||
.unwrap_or_else(|v| v.to_compile_error())
|
||||
});
|
||||
|
||||
quote! {
|
||||
#(#preamble)*;
|
||||
}
|
||||
@ -213,58 +215,94 @@ impl<'a> SessionDiagnosticDerive<'a> {
|
||||
// it can be referred to by Fluent messages.
|
||||
if field.attrs.is_empty() {
|
||||
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()); }
|
||||
} else {
|
||||
quote! {}
|
||||
}
|
||||
});
|
||||
|
||||
// Finally, putting it altogether.
|
||||
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()
|
||||
let span = ast.span().unwrap();
|
||||
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, _)) => match kind {
|
||||
DiagnosticId::Lint(_lint) => todo!(),
|
||||
DiagnosticId::Error(code) => {
|
||||
let (diag, sess) = (&builder.diag, &builder.sess);
|
||||
quote! {
|
||||
let mut #diag = #sess.struct_err_with_code("", rustc_errors::DiagnosticId::Error(#code));
|
||||
#preamble
|
||||
match self {
|
||||
#attrs
|
||||
}
|
||||
match self {
|
||||
#args
|
||||
}
|
||||
#diag
|
||||
}
|
||||
(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! {
|
||||
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
|
||||
match self {
|
||||
#attrs
|
||||
}
|
||||
match self {
|
||||
#args
|
||||
}
|
||||
#diag
|
||||
};
|
||||
let param_ty = match builder.kind {
|
||||
Some((SessionDiagnosticKind::Error, _)) => {
|
||||
quote! { rustc_errors::ErrorGuaranteed }
|
||||
}
|
||||
Some((SessionDiagnosticKind::Warn, _)) => quote! { () },
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
(implementation, param_ty)
|
||||
} else {
|
||||
span_err(
|
||||
ast.span().unwrap(),
|
||||
"`#[derive(SessionDiagnostic)]` can only be used on structs",
|
||||
)
|
||||
.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;
|
||||
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
|
||||
{
|
||||
fn into_diagnostic(
|
||||
self,
|
||||
#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;
|
||||
#implementation
|
||||
}
|
||||
@ -282,6 +320,25 @@ struct FieldInfo<'a> {
|
||||
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
|
||||
/// 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
|
||||
@ -289,89 +346,182 @@ struct FieldInfo<'a> {
|
||||
struct SessionDiagnosticDeriveBuilder<'a> {
|
||||
/// Name of the session parameter that's passed in to the `as_error` method.
|
||||
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
|
||||
/// derive builder.
|
||||
fields: HashMap<String, &'a syn::Field>,
|
||||
|
||||
/// The identifier to use for the generated `DiagnosticBuilder` instance.
|
||||
diag: syn::Ident,
|
||||
|
||||
/// Whether this is a lint or an error. This dictates how the diag will be initialised. `Span`
|
||||
/// stores at what `Span` the kind was first set at (for error reporting purposes, if the kind
|
||||
/// was multiply specified).
|
||||
kind: Option<(DiagnosticId, proc_macro2::Span)>,
|
||||
/// Kind of diagnostic requested via the struct attribute.
|
||||
kind: Option<(SessionDiagnosticKind, proc_macro::Span)>,
|
||||
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
|
||||
/// has the actual diagnostic message.
|
||||
slug: Option<(String, proc_macro::Span)>,
|
||||
/// Error codes are a mandatory part of the struct attribute. Slugs may replace error codes
|
||||
/// in future but it is desirable to mandate error codes until such a time.
|
||||
code: Option<(String, proc_macro::Span)>,
|
||||
}
|
||||
|
||||
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(
|
||||
&mut self,
|
||||
attr: &syn::Attribute,
|
||||
) -> Result<proc_macro2::TokenStream, SessionDiagnosticDeriveError> {
|
||||
Ok(match attr.parse_meta()? {
|
||||
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 = name.as_str();
|
||||
match name {
|
||||
"message" => {
|
||||
let diag = &self.diag;
|
||||
quote! {
|
||||
#diag.set_primary_message(#formatted_str);
|
||||
let span = attr.span().unwrap();
|
||||
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||
|
||||
let nested = match attr.parse_meta()? {
|
||||
syn::Meta::List(syn::MetaList { nested, .. }) => nested,
|
||||
syn::Meta::Path(..) => throw_span_err!(
|
||||
span,
|
||||
&format!("`#[{}]` is not a valid `SessionDiagnostic` struct attribute", name)
|
||||
),
|
||||
syn::Meta::NameValue(..) => throw_span_err!(
|
||||
span,
|
||||
&format!("`#[{} = ...]` is not a valid `SessionDiagnostic` struct attribute", name)
|
||||
),
|
||||
};
|
||||
|
||||
let kind = match name.as_str() {
|
||||
"error" => SessionDiagnosticKind::Error,
|
||||
"warning" => SessionDiagnosticKind::Warn,
|
||||
other => throw_span_err!(
|
||||
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!(
|
||||
"`#[{}(\"...\")]` is not a valid `SessionDiagnostic` struct attribute",
|
||||
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();
|
||||
}
|
||||
}
|
||||
attr @ "error" | attr @ "lint" => {
|
||||
self.set_kind_once(
|
||||
if attr == "error" {
|
||||
DiagnosticId::Error(formatted_str)
|
||||
} else if attr == "lint" {
|
||||
DiagnosticId::Lint(formatted_str)
|
||||
} else {
|
||||
unreachable!()
|
||||
},
|
||||
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!(
|
||||
attr.span().unwrap(),
|
||||
}
|
||||
syn::Meta::NameValue(..) => {
|
||||
span_err(
|
||||
span,
|
||||
&format!(
|
||||
"`#[{} = ...]` is not a valid `SessionDiagnostic` struct attribute",
|
||||
other
|
||||
)
|
||||
),
|
||||
"`#[{}({} = ...)]` 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();
|
||||
}
|
||||
}
|
||||
_ => todo!("unhandled meta kind"),
|
||||
})
|
||||
}
|
||||
|
||||
Ok(quote! {})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn set_kind_once(
|
||||
&mut self,
|
||||
kind: DiagnosticId,
|
||||
span: proc_macro2::Span,
|
||||
kind: SessionDiagnosticKind,
|
||||
span: proc_macro::Span,
|
||||
) -> Result<(), SessionDiagnosticDeriveError> {
|
||||
if self.kind.is_none() {
|
||||
self.kind = Some((kind, span));
|
||||
Ok(())
|
||||
} else {
|
||||
let kind_str = |kind: &DiagnosticId| match kind {
|
||||
DiagnosticId::Lint(..) => "lint",
|
||||
DiagnosticId::Error(..) => "error",
|
||||
};
|
||||
match self.kind {
|
||||
None => {
|
||||
self.kind = Some((kind, span));
|
||||
Ok(())
|
||||
}
|
||||
Some((prev_kind, prev_span)) => {
|
||||
let existing = prev_kind.descr();
|
||||
let current = kind.descr();
|
||||
|
||||
let existing_kind = kind_str(&self.kind.as_ref().unwrap().0);
|
||||
let this_kind = kind_str(&kind);
|
||||
let msg = if current == existing {
|
||||
format!("`{}` specified multiple times", existing)
|
||||
} else {
|
||||
format!("`{}` specified when `{}` was already specified", current, existing)
|
||||
};
|
||||
throw_span_err!(span, &msg, |diag| diag
|
||||
.span_note(prev_span, "previously specified here"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let msg = if this_kind == existing_kind {
|
||||
format!("`{}` specified multiple times", existing_kind)
|
||||
} else {
|
||||
format!("`{}` specified when `{}` was already specified", this_kind, existing_kind)
|
||||
};
|
||||
throw_span_err!(span.unwrap(), &msg);
|
||||
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 = name.as_str();
|
||||
|
||||
// At this point, we need to dispatch based on the attribute key + the
|
||||
// type.
|
||||
let meta = attr.parse_meta()?;
|
||||
match meta {
|
||||
syn::Meta::Path(_) => match name {
|
||||
"message" => {
|
||||
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
||||
return Ok(quote! {
|
||||
#diag.set_span(*#field_binding);
|
||||
});
|
||||
} else {
|
||||
throw_span_err!(
|
||||
attr.span().unwrap(),
|
||||
"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 {
|
||||
"message" => {
|
||||
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
||||
return Ok(quote! {
|
||||
#diag.set_span(*#field_binding);
|
||||
#diag.set_primary_message(#formatted_str);
|
||||
});
|
||||
} else {
|
||||
throw_span_err!(
|
||||
attr.span().unwrap(),
|
||||
"the `#[message = \"...\"]` attribute can only be applied to fields of type `Span`"
|
||||
);
|
||||
}
|
||||
}
|
||||
"label" => {
|
||||
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
||||
return Ok(quote! {
|
||||
@ -441,7 +594,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||
} else {
|
||||
throw_span_err!(
|
||||
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::{
|
||||
fallback_fluent_bundle, fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
|
||||
ErrorGuaranteed, FluentBundle, MultiSpan,
|
||||
EmissionGuarantee, ErrorGuaranteed, FluentBundle, MultiSpan,
|
||||
};
|
||||
use rustc_macros::HashStable_Generic;
|
||||
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
|
||||
/// `#[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`.
|
||||
#[must_use]
|
||||
fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, ErrorGuaranteed>;
|
||||
fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, T>;
|
||||
}
|
||||
|
||||
impl Session {
|
||||
@ -343,6 +343,13 @@ impl Session {
|
||||
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
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>>(
|
||||
&self,
|
||||
sp: S,
|
||||
@ -409,6 +416,9 @@ impl Session {
|
||||
pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
|
||||
err.into_diagnostic(self).emit()
|
||||
}
|
||||
pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) {
|
||||
warning.into_diagnostic(self).emit()
|
||||
}
|
||||
#[inline]
|
||||
pub fn err_count(&self) -> usize {
|
||||
self.diagnostic().err_count()
|
||||
|
@ -3,9 +3,9 @@ use rustc_macros::SessionDiagnostic;
|
||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0062"]
|
||||
#[error(code = "E0062", slug = "typeck-field-multiply-specified-in-initializer")]
|
||||
pub struct FieldMultiplySpecifiedInInitializer {
|
||||
#[message = "field `{ident}` specified more than once"]
|
||||
#[message]
|
||||
#[label = "used more than once"]
|
||||
pub span: Span,
|
||||
#[label = "first use of `{ident}`"]
|
||||
@ -14,19 +14,18 @@ pub struct FieldMultiplySpecifiedInInitializer {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0092"]
|
||||
#[error(code = "E0092", slug = "typeck-unrecognized-atomic-operation")]
|
||||
pub struct UnrecognizedAtomicOperation<'a> {
|
||||
#[message = "unrecognized atomic operation function: `{op}`"]
|
||||
#[message]
|
||||
#[label = "unrecognized atomic operation"]
|
||||
pub span: Span,
|
||||
pub op: &'a str,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0094"]
|
||||
#[error(code = "E0094", slug = "typeck-wrong-number-of-generic-arguments-to-intrinsic")]
|
||||
pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
||||
#[message = "intrinsic has wrong number of {descr} \
|
||||
parameters: found {found}, expected {expected}"]
|
||||
#[message]
|
||||
#[label = "expected {expected} {descr} parameter{expected_pluralize}"]
|
||||
pub span: Span,
|
||||
pub found: usize,
|
||||
@ -36,18 +35,18 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0093"]
|
||||
#[error(code = "E0093", slug = "typeck-unrecognized-intrinsic-function")]
|
||||
pub struct UnrecognizedIntrinsicFunction {
|
||||
#[message = "unrecognized intrinsic function: `{name}`"]
|
||||
#[message]
|
||||
#[label = "unrecognized intrinsic"]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0195"]
|
||||
#[error(code = "E0195", slug = "typeck-lifetimes-or-bounds-mismatch-on-trait")]
|
||||
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"]
|
||||
pub span: Span,
|
||||
#[label = "lifetimes in impl do not match this {item_kind} in trait"]
|
||||
@ -57,18 +56,18 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0120"]
|
||||
#[error(code = "E0120", slug = "typeck-drop-impl-on-wrong-item")]
|
||||
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"]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0124"]
|
||||
#[error(code = "E0124", slug = "typeck-field-already-declared")]
|
||||
pub struct FieldAlreadyDeclared {
|
||||
pub field_name: Ident,
|
||||
#[message = "field `{field_name}` is already declared"]
|
||||
#[message]
|
||||
#[label = "field already declared"]
|
||||
pub span: Span,
|
||||
#[label = "`{field_name}` first declared here"]
|
||||
@ -76,70 +75,69 @@ pub struct FieldAlreadyDeclared {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0184"]
|
||||
#[error(code = "E0184", slug = "typeck-copy-impl-on-type-with-dtor")]
|
||||
pub struct CopyImplOnTypeWithDtor {
|
||||
#[message = "the trait `Copy` may not be implemented for this type; the \
|
||||
type has a destructor"]
|
||||
#[message]
|
||||
#[label = "Copy not allowed on types with destructors"]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0203"]
|
||||
#[error(code = "E0203", slug = "typeck-multiple-relaxed-default-bounds")]
|
||||
pub struct MultipleRelaxedDefaultBounds {
|
||||
#[message = "type parameter has more than one relaxed default bound, only one is supported"]
|
||||
#[message]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0206"]
|
||||
#[error(code = "E0206", slug = "typeck-copy-impl-on-non-adt")]
|
||||
pub struct CopyImplOnNonAdt {
|
||||
#[message = "the trait `Copy` may not be implemented for this type"]
|
||||
#[message]
|
||||
#[label = "type is not a structure or enumeration"]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0224"]
|
||||
#[error(code = "E0224", slug = "typeck-trait-object-declared-with-no-traits")]
|
||||
pub struct TraitObjectDeclaredWithNoTraits {
|
||||
#[message = "at least one trait is required for an object type"]
|
||||
#[message]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0227"]
|
||||
#[error(code = "E0227", slug = "typeck-ambiguous-lifetime-bound")]
|
||||
pub struct AmbiguousLifetimeBound {
|
||||
#[message = "ambiguous lifetime bound, explicit lifetime bound required"]
|
||||
#[message]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0229"]
|
||||
#[error(code = "E0229", slug = "typeck-assoc-type-binding-not-allowed")]
|
||||
pub struct AssocTypeBindingNotAllowed {
|
||||
#[message = "associated type bindings are not allowed here"]
|
||||
#[message]
|
||||
#[label = "associated type not allowed here"]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0436"]
|
||||
#[error(code = "E0436", slug = "typeck-functional-record-update-on-non-struct")]
|
||||
pub struct FunctionalRecordUpdateOnNonStruct {
|
||||
#[message = "functional record update syntax requires a struct"]
|
||||
#[message]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0516"]
|
||||
#[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")]
|
||||
pub struct TypeofReservedKeywordUsed {
|
||||
#[message = "`typeof` is a reserved keyword but unimplemented"]
|
||||
#[message]
|
||||
#[label = "reserved keyword"]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0572"]
|
||||
#[error(code = "E0572", slug = "typeck-return-stmt-outside-of-fn-body")]
|
||||
pub struct ReturnStmtOutsideOfFnBody {
|
||||
#[message = "return statement outside of function body"]
|
||||
#[message]
|
||||
pub span: Span,
|
||||
#[label = "the return is part of this body..."]
|
||||
pub encl_body_span: Option<Span>,
|
||||
@ -148,31 +146,31 @@ pub struct ReturnStmtOutsideOfFnBody {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0627"]
|
||||
#[error(code = "E0627", slug = "typeck-yield-expr-outside-of-generator")]
|
||||
pub struct YieldExprOutsideOfGenerator {
|
||||
#[message = "yield expression outside of generator literal"]
|
||||
#[message]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0639"]
|
||||
#[error(code = "E0639", slug = "typeck-struct-expr-non-exhaustive")]
|
||||
pub struct StructExprNonExhaustive {
|
||||
#[message = "cannot create non-exhaustive {what} using struct expression"]
|
||||
#[message]
|
||||
pub span: Span,
|
||||
pub what: &'static str,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0699"]
|
||||
#[error(code = "E0699", slug = "typeck-method-call-on-unknown-type")]
|
||||
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,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0719"]
|
||||
#[error(code = "E0719", slug = "typeck-value-of-associated-struct-already-specified")]
|
||||
pub struct ValueOfAssociatedStructAlreadySpecified {
|
||||
#[message = "the value of the associated type `{item_name}` (from trait `{def_path}`) is already specified"]
|
||||
#[message]
|
||||
#[label = "re-bound here"]
|
||||
pub span: Span,
|
||||
#[label = "`{item_name}` bound here first"]
|
||||
@ -182,9 +180,9 @@ pub struct ValueOfAssociatedStructAlreadySpecified {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0745"]
|
||||
#[error(code = "E0745", slug = "typeck-address-of-temporary-taken")]
|
||||
pub struct AddressOfTemporaryTaken {
|
||||
#[message = "cannot take address of a temporary"]
|
||||
#[message]
|
||||
#[label = "temporary value"]
|
||||
pub span: Span,
|
||||
}
|
||||
|
@ -26,12 +26,15 @@ use rustc_errors::Applicability;
|
||||
extern crate rustc_session;
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[message = "Hello, world!"]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "hello-world")]
|
||||
struct Hello {}
|
||||
|
||||
#[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
|
||||
enum SessionDiagnosticOnEnum {
|
||||
Foo,
|
||||
@ -39,13 +42,46 @@ enum SessionDiagnosticOnEnum {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
#[error = "E0123"]
|
||||
#[label = "This is in the wrong place"]
|
||||
//~^ ERROR `#[label = ...]` is not a valid `SessionDiagnostic` struct attribute
|
||||
struct WrongPlace {}
|
||||
//~^ ERROR `#[error = ...]` is not a valid `SessionDiagnostic` struct attribute
|
||||
struct WrongStructAttrStyle {}
|
||||
|
||||
#[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 {
|
||||
#[suggestion = "this is the wrong kind of attribute"]
|
||||
//~^ ERROR `#[suggestion = ...]` is not a valid `SessionDiagnostic` field attribute
|
||||
@ -53,101 +89,113 @@ struct WrongPlaceField {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[message = "Hello, world!"]
|
||||
#[error = "E0123"]
|
||||
#[error = "E0456"] //~ ERROR `error` specified multiple times
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
#[error(code = "E0456", slug = "bar")] //~ ERROR `error` specified multiple times
|
||||
struct ErrorSpecifiedTwice {}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[message = "Hello, world!"]
|
||||
#[error = "E0123"]
|
||||
#[lint = "some_useful_lint"] //~ ERROR `lint` specified when `error` was already specified
|
||||
struct LintSpecifiedAfterError {}
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
#[warning(code = "E0293", slug = "bar")]
|
||||
//~^ ERROR `warning` specified when `error` was already specified
|
||||
struct WarnSpecifiedAfterError {}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[message = "Some lint message"]
|
||||
#[error = "E0123"]
|
||||
struct LintButHasErrorCode {}
|
||||
#[error(code = "E0456", code = "E0457", slug = "bar")] //~ ERROR `code` specified multiple times
|
||||
struct CodeSpecifiedTwice {}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
struct ErrorCodeNotProvided {} //~ ERROR `code` not specified
|
||||
|
||||
// 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 {}
|
||||
#[error(code = "E0456", slug = "foo", slug = "bar")] //~ ERROR `slug` specified multiple times
|
||||
struct SlugSpecifiedTwice {}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[lint = "Some lint message"]
|
||||
#[message = "Some error message"]
|
||||
#[error = "E0123"] // ERROR `error` specified when `lint` was already specified
|
||||
struct ErrorSpecifiedAfterLint {}
|
||||
*/
|
||||
struct KindNotProvided {} //~ ERROR diagnostic kind not specified
|
||||
|
||||
#[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 {
|
||||
name: String,
|
||||
#[message = "This error has a field, and references {name}"]
|
||||
#[label = "This error has a field, and references {name}"]
|
||||
span: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct ErrorWithMessageAppliedToField {
|
||||
#[message = "this message is applied to a String field"]
|
||||
//~^ ERROR the `#[message = "..."]` attribute can only be applied to fields of type `Span`
|
||||
#[label = "this message is applied to a String field"]
|
||||
//~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[message = "This error has a field, and references {name}"]
|
||||
//~^ ERROR `name` doesn't refer to a field on this type
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
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)]
|
||||
#[error = "E0123"]
|
||||
#[message = "This is missing a closing brace: {name"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
//~^ ERROR invalid format string: expected `'}'`
|
||||
struct ErrorMissingClosingBrace {
|
||||
#[label = "This is missing a closing brace: {name"]
|
||||
foo: Span,
|
||||
name: String,
|
||||
val: usize,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[message = "This is missing an opening brace: name}"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
//~^ ERROR invalid format string: unmatched `}`
|
||||
struct ErrorMissingOpeningBrace {
|
||||
#[label = "This is missing an opening brace: name}"]
|
||||
foo: Span,
|
||||
name: String,
|
||||
val: usize,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[message = "Something something"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct LabelOnSpan {
|
||||
#[label = "See here"]
|
||||
sp: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[message = "Something something"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct LabelOnNonSpan {
|
||||
#[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,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct Suggest {
|
||||
#[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")]
|
||||
@ -157,14 +205,14 @@ struct Suggest {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithoutCode {
|
||||
#[suggestion(message = "This is a suggestion")]
|
||||
suggestion: (Span, Applicability),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithBadKey {
|
||||
#[suggestion(nonsense = "This is nonsense")]
|
||||
//~^ ERROR `nonsense` is not a valid key for `#[suggestion(...)]`
|
||||
@ -172,7 +220,7 @@ struct SuggestWithBadKey {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithShorthandMsg {
|
||||
#[suggestion(msg = "This is a suggestion")]
|
||||
//~^ ERROR `msg` is not a valid key for `#[suggestion(...)]`
|
||||
@ -180,7 +228,7 @@ struct SuggestWithShorthandMsg {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithoutMsg {
|
||||
#[suggestion(code = "This is suggested code")]
|
||||
//~^ ERROR missing suggestion message
|
||||
@ -188,14 +236,14 @@ struct SuggestWithoutMsg {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithTypesSwapped {
|
||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||
suggestion: (Applicability, Span),
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithWrongTypeApplicabilityOnly {
|
||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||
//~^ ERROR wrong field type for suggestion
|
||||
@ -203,14 +251,14 @@ struct SuggestWithWrongTypeApplicabilityOnly {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithSpanOnly {
|
||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||
suggestion: Span,
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithDuplicateSpanAndApplicability {
|
||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||
//~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
|
||||
@ -218,7 +266,7 @@ struct SuggestWithDuplicateSpanAndApplicability {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct SuggestWithDuplicateApplicabilityAndSpan {
|
||||
#[suggestion(message = "This is a message", code = "This is suggested code")]
|
||||
//~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one
|
||||
@ -226,7 +274,7 @@ struct SuggestWithDuplicateApplicabilityAndSpan {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct WrongKindOfAnnotation {
|
||||
#[label("wrong kind of annotation for label")]
|
||||
//~^ ERROR invalid annotation list `#[label(...)]`
|
||||
@ -234,8 +282,7 @@ struct WrongKindOfAnnotation {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[message = "Something something else"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct OptionsInErrors {
|
||||
#[label = "Label message"]
|
||||
label: Option<Span>,
|
||||
@ -244,11 +291,11 @@ struct OptionsInErrors {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0456"]
|
||||
#[error(code = "E0456", slug = "foo")]
|
||||
struct MoveOutOfBorrowError<'tcx> {
|
||||
name: Ident,
|
||||
ty: Ty<'tcx>,
|
||||
#[message = "cannot move {ty} out of borrow"]
|
||||
#[message]
|
||||
#[label = "cannot move out of borrow"]
|
||||
span: Span,
|
||||
#[label = "`{ty}` first borrowed here"]
|
||||
@ -258,9 +305,9 @@ struct MoveOutOfBorrowError<'tcx> {
|
||||
}
|
||||
|
||||
#[derive(SessionDiagnostic)]
|
||||
#[error = "E0123"]
|
||||
#[error(code = "E0123", slug = "foo")]
|
||||
struct ErrorWithLifetime<'a> {
|
||||
#[message = "Some message that references {name}"]
|
||||
#[label = "Some message that references {name}"]
|
||||
span: Span,
|
||||
name: &'a str,
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
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 | | enum SessionDiagnosticOnEnum {
|
||||
LL | | Foo,
|
||||
@ -9,95 +9,221 @@ LL | | Bar,
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: `#[label = ...]` is not a valid `SessionDiagnostic` struct attribute
|
||||
--> $DIR/session-derive-errors.rs:43:1
|
||||
error: `#[error = ...]` is not a valid `SessionDiagnostic` struct attribute
|
||||
--> $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
|
||||
--> $DIR/session-derive-errors.rs:50:5
|
||||
--> $DIR/session-derive-errors.rs:86:5
|
||||
|
|
||||
LL | #[suggestion = "this is the wrong kind of attribute"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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: `lint` specified when `error` was already specified
|
||||
--> $DIR/session-derive-errors.rs:64:10
|
||||
error: `warning` specified when `error` was already specified
|
||||
--> $DIR/session-derive-errors.rs:98:1
|
||||
|
|
||||
LL | #[lint = "some_useful_lint"]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
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: `slug` specified multiple times
|
||||
--> $DIR/session-derive-errors.rs:107:46
|
||||
|
|
||||
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
|
||||
--> $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`
|
||||
--> $DIR/session-derive-errors.rs:101:5
|
||||
error: the `#[message]` attribute can only be applied to fields of type `Span`
|
||||
--> $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
|
||||
--> $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
|
||||
--> $DIR/session-derive-errors.rs:116:1
|
||||
--> $DIR/session-derive-errors.rs:163:20
|
||||
|
|
||||
LL | #[derive(SessionDiagnostic)]
|
||||
| ----------------- in this derive macro expansion
|
||||
LL | #[error = "E0123"]
|
||||
| - because of this opening brace
|
||||
LL | #[message = "This is missing a closing brace: {name"]
|
||||
| ^ expected `'}'` in format string
|
||||
LL | #[error(code = "E0123", slug = "foo")]
|
||||
| - ^ expected `'}'` in format string
|
||||
| |
|
||||
| because of this opening brace
|
||||
|
|
||||
= 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)
|
||||
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/session-derive-errors.rs:125:1
|
||||
--> $DIR/session-derive-errors.rs:173:20
|
||||
|
|
||||
LL | #[derive(SessionDiagnostic)]
|
||||
| ----------------- in this derive macro expansion
|
||||
LL | #[error = "E0123"]
|
||||
LL | #[message = "This is missing an opening brace: name}"]
|
||||
| ^ unmatched `}` in format string
|
||||
LL | #[error(code = "E0123", slug = "foo")]
|
||||
| ^ unmatched `}` in format string
|
||||
|
|
||||
= 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)
|
||||
|
||||
error: The `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||
--> $DIR/session-derive-errors.rs:144:5
|
||||
error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||
--> $DIR/session-derive-errors.rs:192:5
|
||||
|
|
||||
LL | #[label = "See here"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -105,7 +231,7 @@ LL | #[suggestion(code = "This is suggested code")]
|
||||
= help: provide a suggestion message using `#[suggestion(message = "...")]`
|
||||
|
||||
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 | |
|
||||
@ -115,7 +241,7 @@ LL | | suggestion: 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`
|
||||
--> $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 | |
|
||||
@ -123,7 +249,7 @@ LL | | suggestion: (Span, Span, 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 | |
|
||||
@ -131,10 +257,22 @@ LL | | suggestion: (Applicability, Applicability, Span),
|
||||
| |____________________________________________________^
|
||||
|
||||
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")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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…
Reference in New Issue
Block a user