macros: support translatable labels
Extends support for generating `DiagnosticMessage::FluentIdentifier` messages from `SessionDiagnostic` derive to `#[label]`. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
72dec56028
commit
a88717cef0
8 changed files with 140 additions and 95 deletions
|
@ -277,7 +277,7 @@ impl Diagnostic {
|
||||||
///
|
///
|
||||||
/// This span is *not* considered a ["primary span"][`MultiSpan`]; only
|
/// This span is *not* considered a ["primary span"][`MultiSpan`]; only
|
||||||
/// the `Span` supplied when creating the diagnostic is primary.
|
/// the `Span` supplied when creating the diagnostic is primary.
|
||||||
pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self {
|
pub fn span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) -> &mut Self {
|
||||||
self.span.push_span_label(span, label.into());
|
self.span.push_span_label(span, label.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,7 +408,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||||
/// the diagnostic was constructed. However, the label span is *not* considered a
|
/// the diagnostic was constructed. However, the label span is *not* considered a
|
||||||
/// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is
|
/// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is
|
||||||
/// primary.
|
/// primary.
|
||||||
pub fn span_label(&mut self, span: Span, label: impl Into<String>) -> &mut Self);
|
pub fn span_label(&mut self, span: Span, label: impl Into<DiagnosticMessage>) -> &mut Self);
|
||||||
|
|
||||||
forward!(
|
forward!(
|
||||||
/// Labels all the given spans with the provided label.
|
/// Labels all the given spans with the provided label.
|
||||||
|
|
|
@ -561,6 +561,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
) -> Result<proc_macro2::TokenStream, SessionDiagnosticDeriveError> {
|
) -> Result<proc_macro2::TokenStream, SessionDiagnosticDeriveError> {
|
||||||
let diag = &self.diag;
|
let diag = &self.diag;
|
||||||
let field_binding = &info.binding.binding;
|
let field_binding = &info.binding.binding;
|
||||||
|
|
||||||
let name = attr.path.segments.last().unwrap().ident.to_string();
|
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||||
let name = name.as_str();
|
let name = name.as_str();
|
||||||
|
|
||||||
|
@ -573,46 +574,38 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
Ok(quote! {})
|
Ok(quote! {})
|
||||||
}
|
}
|
||||||
"primary_span" => {
|
"primary_span" => {
|
||||||
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
self.report_error_if_not_applied_to_span(attr, info)?;
|
||||||
return Ok(quote! {
|
Ok(quote! {
|
||||||
#diag.set_span(*#field_binding);
|
#diag.set_span(*#field_binding);
|
||||||
});
|
})
|
||||||
} else {
|
}
|
||||||
throw_span_err!(
|
"label" => {
|
||||||
attr.span().unwrap(),
|
self.report_error_if_not_applied_to_span(attr, info)?;
|
||||||
"the `#[primary_span]` attribute can only be applied to fields of type `Span`"
|
Ok(self.add_subdiagnostic(field_binding, name, "label"))
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
other => throw_span_err!(
|
other => throw_span_err!(
|
||||||
attr.span().unwrap(),
|
attr.span().unwrap(),
|
||||||
&format!("`#[{}]` is not a valid `SessionDiagnostic` field attribute", other)
|
&format!("`#[{}]` is not a valid `SessionDiagnostic` field attribute", other)
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
|
syn::Meta::NameValue(syn::MetaNameValue { lit: syn::Lit::Str(s), .. }) => match name {
|
||||||
let formatted_str = self.build_format(&s.value(), attr.span());
|
"label" => {
|
||||||
match name {
|
self.report_error_if_not_applied_to_span(attr, info)?;
|
||||||
"label" => {
|
Ok(self.add_subdiagnostic(field_binding, name, &s.value()))
|
||||||
if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
|
||||||
return Ok(quote! {
|
|
||||||
#diag.span_label(*#field_binding, #formatted_str);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw_span_err!(
|
|
||||||
attr.span().unwrap(),
|
|
||||||
"the `#[label = ...]` 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
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
other => throw_span_err!(
|
||||||
|
attr.span().unwrap(),
|
||||||
|
&format!(
|
||||||
|
"`#[{} = ...]` is not a valid `SessionDiagnostic` field attribute",
|
||||||
|
other
|
||||||
|
)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
syn::Meta::NameValue(_) => throw_span_err!(
|
||||||
|
attr.span().unwrap(),
|
||||||
|
&format!("`#[{} = ...]` is not a valid `SessionDiagnostic` field attribute", name),
|
||||||
|
|diag| diag.help("value must be a string")
|
||||||
|
),
|
||||||
syn::Meta::List(list) => {
|
syn::Meta::List(list) => {
|
||||||
match list.path.segments.iter().last().unwrap().ident.to_string().as_str() {
|
match list.path.segments.iter().last().unwrap().ident.to_string().as_str() {
|
||||||
suggestion_kind @ "suggestion"
|
suggestion_kind @ "suggestion"
|
||||||
|
@ -681,7 +674,55 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => panic!("unhandled meta kind"),
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reports an error if the field's type is not `Span`.
|
||||||
|
fn report_error_if_not_applied_to_span(
|
||||||
|
&self,
|
||||||
|
attr: &syn::Attribute,
|
||||||
|
info: FieldInfo<'_>,
|
||||||
|
) -> Result<(), SessionDiagnosticDeriveError> {
|
||||||
|
if !type_matches_path(&info.ty, &["rustc_span", "Span"]) {
|
||||||
|
let name = attr.path.segments.last().unwrap().ident.to_string();
|
||||||
|
let name = name.as_str();
|
||||||
|
let meta = attr.parse_meta()?;
|
||||||
|
|
||||||
|
throw_span_err!(
|
||||||
|
attr.span().unwrap(),
|
||||||
|
&format!(
|
||||||
|
"the `#[{}{}]` attribute can only be applied to fields of type `Span`",
|
||||||
|
name,
|
||||||
|
match meta {
|
||||||
|
syn::Meta::Path(_) => "",
|
||||||
|
syn::Meta::NameValue(_) => " = ...",
|
||||||
|
syn::Meta::List(_) => "(...)",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug and
|
||||||
|
/// `fluent_attr_identifier`.
|
||||||
|
fn add_subdiagnostic(
|
||||||
|
&self,
|
||||||
|
field_binding: &proc_macro2::Ident,
|
||||||
|
kind: &str,
|
||||||
|
fluent_attr_identifier: &str,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let diag = &self.diag;
|
||||||
|
|
||||||
|
let slug =
|
||||||
|
self.slug.as_ref().map(|(slug, _)| slug.as_str()).unwrap_or_else(|| "missing-slug");
|
||||||
|
let fn_name = format_ident!("span_{}", kind);
|
||||||
|
quote! {
|
||||||
|
#diag.#fn_name(
|
||||||
|
*#field_binding,
|
||||||
|
rustc_errors::DiagnosticMessage::fluent_attr(#slug, #fluent_attr_identifier)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@ use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
#[error(code = "E0062", slug = "typeck-field-multiply-specified-in-initializer")]
|
#[error(code = "E0062", slug = "typeck-field-multiply-specified-in-initializer")]
|
||||||
pub struct FieldMultiplySpecifiedInInitializer {
|
pub struct FieldMultiplySpecifiedInInitializer {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "used more than once"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "first use of `{ident}`"]
|
#[label = "previous-use-label"]
|
||||||
pub prev_span: Span,
|
pub prev_span: Span,
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ pub struct FieldMultiplySpecifiedInInitializer {
|
||||||
#[error(code = "E0092", slug = "typeck-unrecognized-atomic-operation")]
|
#[error(code = "E0092", slug = "typeck-unrecognized-atomic-operation")]
|
||||||
pub struct UnrecognizedAtomicOperation<'a> {
|
pub struct UnrecognizedAtomicOperation<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "unrecognized atomic operation"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub op: &'a str,
|
pub op: &'a str,
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ pub struct UnrecognizedAtomicOperation<'a> {
|
||||||
#[error(code = "E0094", slug = "typeck-wrong-number-of-generic-arguments-to-intrinsic")]
|
#[error(code = "E0094", slug = "typeck-wrong-number-of-generic-arguments-to-intrinsic")]
|
||||||
pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "expected {expected} {descr} parameter{expected_pluralize}"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub found: usize,
|
pub found: usize,
|
||||||
pub expected: usize,
|
pub expected: usize,
|
||||||
|
@ -38,7 +38,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
|
||||||
#[error(code = "E0093", slug = "typeck-unrecognized-intrinsic-function")]
|
#[error(code = "E0093", slug = "typeck-unrecognized-intrinsic-function")]
|
||||||
pub struct UnrecognizedIntrinsicFunction {
|
pub struct UnrecognizedIntrinsicFunction {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "unrecognized intrinsic"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,9 @@ pub struct UnrecognizedIntrinsicFunction {
|
||||||
#[error(code = "E0195", slug = "typeck-lifetimes-or-bounds-mismatch-on-trait")]
|
#[error(code = "E0195", slug = "typeck-lifetimes-or-bounds-mismatch-on-trait")]
|
||||||
pub struct LifetimesOrBoundsMismatchOnTrait {
|
pub struct LifetimesOrBoundsMismatchOnTrait {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "lifetimes do not match {item_kind} in trait"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "lifetimes in impl do not match this {item_kind} in trait"]
|
#[label = "generics-label"]
|
||||||
pub generics_span: Option<Span>,
|
pub generics_span: Option<Span>,
|
||||||
pub item_kind: &'static str,
|
pub item_kind: &'static str,
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
|
@ -59,7 +59,7 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
|
||||||
#[error(code = "E0120", slug = "typeck-drop-impl-on-wrong-item")]
|
#[error(code = "E0120", slug = "typeck-drop-impl-on-wrong-item")]
|
||||||
pub struct DropImplOnWrongItem {
|
pub struct DropImplOnWrongItem {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "must be a struct, enum, or union"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ pub struct DropImplOnWrongItem {
|
||||||
pub struct FieldAlreadyDeclared {
|
pub struct FieldAlreadyDeclared {
|
||||||
pub field_name: Ident,
|
pub field_name: Ident,
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "field already declared"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "`{field_name}` first declared here"]
|
#[label = "previous-decl-label"]
|
||||||
pub prev_span: Span,
|
pub prev_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ pub struct FieldAlreadyDeclared {
|
||||||
#[error(code = "E0184", slug = "typeck-copy-impl-on-type-with-dtor")]
|
#[error(code = "E0184", slug = "typeck-copy-impl-on-type-with-dtor")]
|
||||||
pub struct CopyImplOnTypeWithDtor {
|
pub struct CopyImplOnTypeWithDtor {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "Copy not allowed on types with destructors"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ pub struct MultipleRelaxedDefaultBounds {
|
||||||
#[error(code = "E0206", slug = "typeck-copy-impl-on-non-adt")]
|
#[error(code = "E0206", slug = "typeck-copy-impl-on-non-adt")]
|
||||||
pub struct CopyImplOnNonAdt {
|
pub struct CopyImplOnNonAdt {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "type is not a structure or enumeration"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ pub struct AmbiguousLifetimeBound {
|
||||||
#[error(code = "E0229", slug = "typeck-assoc-type-binding-not-allowed")]
|
#[error(code = "E0229", slug = "typeck-assoc-type-binding-not-allowed")]
|
||||||
pub struct AssocTypeBindingNotAllowed {
|
pub struct AssocTypeBindingNotAllowed {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "associated type not allowed here"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ pub struct FunctionalRecordUpdateOnNonStruct {
|
||||||
#[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")]
|
#[error(code = "E0516", slug = "typeck-typeof-reserved-keyword-used")]
|
||||||
pub struct TypeofReservedKeywordUsed {
|
pub struct TypeofReservedKeywordUsed {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "reserved keyword"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,9 +139,9 @@ pub struct TypeofReservedKeywordUsed {
|
||||||
pub struct ReturnStmtOutsideOfFnBody {
|
pub struct ReturnStmtOutsideOfFnBody {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "the return is part of this body..."]
|
#[label = "encl-body-label"]
|
||||||
pub encl_body_span: Option<Span>,
|
pub encl_body_span: Option<Span>,
|
||||||
#[label = "...not the enclosing function body"]
|
#[label = "encl-fn-label"]
|
||||||
pub encl_fn_span: Option<Span>,
|
pub encl_fn_span: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,9 +171,9 @@ pub struct MethodCallOnUnknownType {
|
||||||
#[error(code = "E0719", slug = "typeck-value-of-associated-struct-already-specified")]
|
#[error(code = "E0719", slug = "typeck-value-of-associated-struct-already-specified")]
|
||||||
pub struct ValueOfAssociatedStructAlreadySpecified {
|
pub struct ValueOfAssociatedStructAlreadySpecified {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "re-bound here"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
#[label = "`{item_name}` bound here first"]
|
#[label = "previous-bound-label"]
|
||||||
pub prev_span: Span,
|
pub prev_span: Span,
|
||||||
pub item_name: Ident,
|
pub item_name: Ident,
|
||||||
pub def_path: String,
|
pub def_path: String,
|
||||||
|
@ -183,6 +183,6 @@ pub struct ValueOfAssociatedStructAlreadySpecified {
|
||||||
#[error(code = "E0745", slug = "typeck-address-of-temporary-taken")]
|
#[error(code = "E0745", slug = "typeck-address-of-temporary-taken")]
|
||||||
pub struct AddressOfTemporaryTaken {
|
pub struct AddressOfTemporaryTaken {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "temporary value"]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,14 +139,14 @@ struct InvalidPathFieldAttr {
|
||||||
#[error(code = "E0123", slug = "foo")]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorWithField {
|
struct ErrorWithField {
|
||||||
name: String,
|
name: String,
|
||||||
#[label = "This error has a field, and references {name}"]
|
#[label = "bar"]
|
||||||
span: Span,
|
span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorWithMessageAppliedToField {
|
struct ErrorWithMessageAppliedToField {
|
||||||
#[label = "this message is applied to a String field"]
|
#[label = "bar"]
|
||||||
//~^ 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`
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
@ -154,27 +154,27 @@ struct ErrorWithMessageAppliedToField {
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorWithNonexistentField {
|
struct ErrorWithNonexistentField {
|
||||||
#[label = "This error has a field, and references {name}"]
|
#[suggestion(message = "This is a suggestion", code = "{name}")]
|
||||||
//~^ ERROR `name` doesn't refer to a field on this type
|
//~^ ERROR `name` doesn't refer to a field on this type
|
||||||
foo: Span,
|
suggestion: (Span, Applicability),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
|
||||||
//~^ ERROR invalid format string: expected `'}'`
|
//~^ ERROR invalid format string: expected `'}'`
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorMissingClosingBrace {
|
struct ErrorMissingClosingBrace {
|
||||||
#[label = "This is missing a closing brace: {name"]
|
#[suggestion(message = "This is a suggestion", code = "{name")]
|
||||||
foo: Span,
|
suggestion: (Span, Applicability),
|
||||||
name: String,
|
name: String,
|
||||||
val: usize,
|
val: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
|
||||||
//~^ ERROR invalid format string: unmatched `}`
|
//~^ ERROR invalid format string: unmatched `}`
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorMissingOpeningBrace {
|
struct ErrorMissingOpeningBrace {
|
||||||
#[label = "This is missing an opening brace: name}"]
|
#[suggestion(message = "This is a suggestion", code = "name}")]
|
||||||
foo: Span,
|
suggestion: (Span, Applicability),
|
||||||
name: String,
|
name: String,
|
||||||
val: usize,
|
val: usize,
|
||||||
}
|
}
|
||||||
|
@ -182,14 +182,14 @@ struct ErrorMissingOpeningBrace {
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct LabelOnSpan {
|
struct LabelOnSpan {
|
||||||
#[label = "See here"]
|
#[label = "bar"]
|
||||||
sp: Span,
|
sp: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct LabelOnNonSpan {
|
struct LabelOnNonSpan {
|
||||||
#[label = "See here"]
|
#[label = "bar"]
|
||||||
//~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
//~^ ERROR the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||||
id: u32,
|
id: u32,
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ struct SuggestWithDuplicateApplicabilityAndSpan {
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct WrongKindOfAnnotation {
|
struct WrongKindOfAnnotation {
|
||||||
#[label("wrong kind of annotation for label")]
|
#[label("bar")]
|
||||||
//~^ ERROR invalid annotation list `#[label(...)]`
|
//~^ ERROR invalid annotation list `#[label(...)]`
|
||||||
z: Span,
|
z: Span,
|
||||||
}
|
}
|
||||||
|
@ -284,7 +284,7 @@ struct WrongKindOfAnnotation {
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct OptionsInErrors {
|
struct OptionsInErrors {
|
||||||
#[label = "Label message"]
|
#[label = "bar"]
|
||||||
label: Option<Span>,
|
label: Option<Span>,
|
||||||
#[suggestion(message = "suggestion message")]
|
#[suggestion(message = "suggestion message")]
|
||||||
opt_sugg: Option<(Span, Applicability)>,
|
opt_sugg: Option<(Span, Applicability)>,
|
||||||
|
@ -296,9 +296,9 @@ struct MoveOutOfBorrowError<'tcx> {
|
||||||
name: Ident,
|
name: Ident,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label = "cannot move out of borrow"]
|
#[label = "bar"]
|
||||||
span: Span,
|
span: Span,
|
||||||
#[label = "`{ty}` first borrowed here"]
|
#[label = "qux"]
|
||||||
other_span: Span,
|
other_span: Span,
|
||||||
#[suggestion(message = "consider cloning here", code = "{name}.clone()")]
|
#[suggestion(message = "consider cloning here", code = "{name}.clone()")]
|
||||||
opt_sugg: Option<(Span, Applicability)>,
|
opt_sugg: Option<(Span, Applicability)>,
|
||||||
|
@ -307,7 +307,15 @@ struct MoveOutOfBorrowError<'tcx> {
|
||||||
#[derive(SessionDiagnostic)]
|
#[derive(SessionDiagnostic)]
|
||||||
#[error(code = "E0123", slug = "foo")]
|
#[error(code = "E0123", slug = "foo")]
|
||||||
struct ErrorWithLifetime<'a> {
|
struct ErrorWithLifetime<'a> {
|
||||||
#[label = "Some message that references {name}"]
|
#[label = "bar"]
|
||||||
|
span: Span,
|
||||||
|
name: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SessionDiagnostic)]
|
||||||
|
#[error(code = "E0123", slug = "foo")]
|
||||||
|
struct ErrorWithDefaultLabelAttr<'a> {
|
||||||
|
#[label]
|
||||||
span: Span,
|
span: Span,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,35 +162,31 @@ LL | #[nonsense]
|
||||||
error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||||
--> $DIR/session-derive-errors.rs:149:5
|
--> $DIR/session-derive-errors.rs:149:5
|
||||||
|
|
|
|
||||||
LL | #[label = "this message is applied to a String field"]
|
LL | #[label = "bar"]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `name` doesn't refer to a field on this type
|
error: `name` doesn't refer to a field on this type
|
||||||
--> $DIR/session-derive-errors.rs:157:5
|
--> $DIR/session-derive-errors.rs:157:52
|
||||||
|
|
|
|
||||||
LL | #[label = "This error has a field, and references {name}"]
|
LL | #[suggestion(message = "This is a suggestion", code = "{name}")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: invalid format string: expected `'}'` but string was terminated
|
error: invalid format string: expected `'}'` but string was terminated
|
||||||
--> $DIR/session-derive-errors.rs:163:20
|
--> $DIR/session-derive-errors.rs:162:16
|
||||||
|
|
|
|
||||||
LL | #[derive(SessionDiagnostic)]
|
LL | #[derive(SessionDiagnostic)]
|
||||||
| ----------------- in this derive macro expansion
|
| - ^ expected `'}'` in format string
|
||||||
LL | #[error(code = "E0123", slug = "foo")]
|
| |
|
||||||
| - ^ expected `'}'` in format string
|
| because of this opening brace
|
||||||
| |
|
|
||||||
| because of this opening brace
|
|
||||||
|
|
|
|
||||||
= note: if you intended to print `{`, you can escape it using `{{`
|
= note: if you intended to print `{`, you can escape it using `{{`
|
||||||
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: invalid format string: unmatched `}` found
|
error: invalid format string: unmatched `}` found
|
||||||
--> $DIR/session-derive-errors.rs:173:20
|
--> $DIR/session-derive-errors.rs:172:15
|
||||||
|
|
|
|
||||||
LL | #[derive(SessionDiagnostic)]
|
LL | #[derive(SessionDiagnostic)]
|
||||||
| ----------------- in this derive macro expansion
|
| ^ 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: if you intended to print `}`, you can escape it using `}}`
|
||||||
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
@ -198,8 +194,8 @@ LL | #[error(code = "E0123", slug = "foo")]
|
||||||
error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
error: the `#[label = ...]` attribute can only be applied to fields of type `Span`
|
||||||
--> $DIR/session-derive-errors.rs:192:5
|
--> $DIR/session-derive-errors.rs:192:5
|
||||||
|
|
|
|
||||||
LL | #[label = "See here"]
|
LL | #[label = "bar"]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `nonsense` is not a valid key for `#[suggestion(...)]`
|
error: `nonsense` is not a valid key for `#[suggestion(...)]`
|
||||||
--> $DIR/session-derive-errors.rs:217:18
|
--> $DIR/session-derive-errors.rs:217:18
|
||||||
|
@ -250,8 +246,8 @@ LL | | suggestion: (Applicability, Applicability, Span),
|
||||||
error: invalid annotation list `#[label(...)]`
|
error: invalid annotation list `#[label(...)]`
|
||||||
--> $DIR/session-derive-errors.rs:279:7
|
--> $DIR/session-derive-errors.rs:279:7
|
||||||
|
|
|
|
||||||
LL | #[label("wrong kind of annotation for label")]
|
LL | #[label("bar")]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: cannot find attribute `nonsense` in this scope
|
error: cannot find attribute `nonsense` in this scope
|
||||||
--> $DIR/session-derive-errors.rs:51:3
|
--> $DIR/session-derive-errors.rs:51:3
|
||||||
|
@ -266,7 +262,7 @@ LL | #[nonsense]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error[E0599]: no method named `into_diagnostic_arg` found for struct `Hello` in the current scope
|
error[E0599]: no method named `into_diagnostic_arg` found for struct `Hello` in the current scope
|
||||||
--> $DIR/session-derive-errors.rs:315:10
|
--> $DIR/session-derive-errors.rs:323:10
|
||||||
|
|
|
|
||||||
LL | struct Hello {}
|
LL | struct Hello {}
|
||||||
| ------------ method `into_diagnostic_arg` not found for this
|
| ------------ method `into_diagnostic_arg` not found for this
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0184]: the trait `Copy` may not be implemented for this type; the type ha
|
||||||
--> $DIR/E0184.rs:1:10
|
--> $DIR/E0184.rs:1:10
|
||||||
|
|
|
|
||||||
LL | #[derive(Copy)]
|
LL | #[derive(Copy)]
|
||||||
| ^^^^ Copy not allowed on types with destructors
|
| ^^^^ `Copy` not allowed on types with destructors
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0184]: the trait `Copy` may not be implemented for this type; the type ha
|
||||||
--> $DIR/exclusive-drop-and-copy.rs:3:10
|
--> $DIR/exclusive-drop-and-copy.rs:3:10
|
||||||
|
|
|
|
||||||
LL | #[derive(Copy, Clone)]
|
LL | #[derive(Copy, Clone)]
|
||||||
| ^^^^ Copy not allowed on types with destructors
|
| ^^^^ `Copy` not allowed on types with destructors
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ error[E0184]: the trait `Copy` may not be implemented for this type; the type ha
|
||||||
--> $DIR/exclusive-drop-and-copy.rs:10:10
|
--> $DIR/exclusive-drop-and-copy.rs:10:10
|
||||||
|
|
|
|
||||||
LL | #[derive(Copy, Clone)]
|
LL | #[derive(Copy, Clone)]
|
||||||
| ^^^^ Copy not allowed on types with destructors
|
| ^^^^ `Copy` not allowed on types with destructors
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue