macros: translatable struct attrs and warnings

Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
David Wood 2022-03-31 08:35:17 +01:00
parent f0de7df204
commit d0fd8d7880
9 changed files with 729 additions and 276 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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,

View File

@ -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,

View File

@ -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`"
);
}
}

View File

@ -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()

View File

@ -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,
}

View File

@ -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,
}

View File

@ -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