Permit {This} in diagnostic attribute format literals

This commit is contained in:
mejrs
2026-04-23 21:59:41 +02:00
parent acb65f36a0
commit c2916be8d7
23 changed files with 368 additions and 204 deletions
@@ -6,7 +6,6 @@
Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, NameValue, Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, NameValue,
OnUnimplementedCondition, Piece, Predicate, OnUnimplementedCondition, Piece, Predicate,
}; };
use rustc_hir::lints::FormatWarning;
use rustc_macros::Diagnostic; use rustc_macros::Diagnostic;
use rustc_parse_format::{ use rustc_parse_format::{
Argument, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, Position, Argument, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, Position,
@@ -19,9 +18,8 @@
use crate::context::{AcceptContext, Stage}; use crate::context::{AcceptContext, Stage};
use crate::errors::{ use crate::errors::{
DisallowedPlaceholder, DisallowedPositionalArgument, IgnoredDiagnosticOption, FormatWarning, IgnoredDiagnosticOption, MalFormedDiagnosticAttributeLint,
InvalidFormatSpecifier, MalFormedDiagnosticAttributeLint, MissingOptionsForDiagnosticAttribute, MissingOptionsForDiagnosticAttribute, NonMetaItemDiagnosticAttribute, WrappedParserError,
NonMetaItemDiagnosticAttribute, WrappedParserError,
}; };
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser}; use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser};
@@ -88,6 +86,29 @@ fn allowed_options(&self) -> &'static str {
Self::DiagnosticOnUnmatchArgs => DEFAULT, Self::DiagnosticOnUnmatchArgs => DEFAULT,
} }
} }
fn allowed_format_arguments(&self) -> &'static str {
match self {
Self::RustcOnUnimplemented => {
"see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented> for allowed format arguments"
}
Self::DiagnosticOnUnimplemented => {
"only `Self` and generics of the trait are allowed as a format argument"
}
Self::DiagnosticOnConst => {
"only `Self` and generics of the implementation are allowed as a format argument"
}
Self::DiagnosticOnMove => {
"only `This`, `Self` and generics of the type are allowed as a format argument"
}
Self::DiagnosticOnUnknown => {
"only `This` is allowed as a format argument, referring to the failed import"
}
Self::DiagnosticOnUnmatchArgs => {
"only `This` is allowed as a format argument, referring to the macro's name"
}
}
}
} }
fn merge_directives<S: Stage>( fn merge_directives<S: Stage>(
@@ -257,22 +278,13 @@ fn parse_directive_items<'p, S: Stage>(
match parse_format_string(input.name, snippet, input.span, mode) { match parse_format_string(input.name, snippet, input.span, mode) {
Ok((f, warnings)) => { Ok((f, warnings)) => {
for warning in warnings { for warning in warnings {
let (FormatWarning::InvalidSpecifier { span, .. } let (FormatWarning::InvalidSpecifier { span }
| FormatWarning::PositionalArgument { span, .. } | FormatWarning::PositionalArgument { span }
| FormatWarning::DisallowedPlaceholder { span }) = warning; | FormatWarning::IndexedArgument { span }
| FormatWarning::DisallowedPlaceholder { span, .. }) = warning;
cx.emit_dyn_lint( cx.emit_dyn_lint(
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
move |dcx, level| match warning { move |dcx, level| warning.into_diag(dcx, level),
FormatWarning::PositionalArgument { .. } => {
DisallowedPositionalArgument.into_diag(dcx, level)
}
FormatWarning::InvalidSpecifier { .. } => {
InvalidFormatSpecifier.into_diag(dcx, level)
}
FormatWarning::DisallowedPlaceholder { .. } => {
DisallowedPlaceholder.into_diag(dcx, level)
}
},
span, span,
); );
} }
@@ -422,38 +434,74 @@ fn parse_arg(
is_source_literal: bool, is_source_literal: bool,
) -> FormatArg { ) -> FormatArg {
let span = slice_span(input_span, arg.position_span.clone(), is_source_literal); let span = slice_span(input_span, arg.position_span.clone(), is_source_literal);
if matches!(mode, Mode::DiagnosticOnUnknown) {
warnings.push(FormatWarning::DisallowedPlaceholder { span });
return FormatArg::AsIs(sym::empty_braces);
}
match arg.position { match arg.position {
// Something like "hello {name}" // Something like "hello {name}"
Position::ArgumentNamed(name) => match (mode, Symbol::intern(name)) { Position::ArgumentNamed(name) => match (mode, Symbol::intern(name)) {
// Only `#[rustc_on_unimplemented]` can use these (Mode::RustcOnUnimplemented, sym::ItemContext) => FormatArg::ItemContext,
(Mode::RustcOnUnimplemented { .. }, sym::ItemContext) => FormatArg::ItemContext,
(Mode::RustcOnUnimplemented { .. } | Mode::DiagnosticOnUnmatchArgs, sym::This) => { // Like `{This}`, but sugared.
FormatArg::This // FIXME(mejrs) maybe rename/rework this or something
// if we want to apply this to other attrs?
(Mode::RustcOnUnimplemented, sym::Trait) => FormatArg::Trait,
// Some diagnostic attributes can use `{This}` to refer to the annotated item.
// For those that don't, we continue and maybe use it as a generic parameter.
//
// FIXME(mejrs) `DiagnosticOnUnimplemented` is intentionally not here;
// that requires lang approval which is best kept for a standalone PR.
(
Mode::RustcOnUnimplemented
| Mode::DiagnosticOnUnknown
| Mode::DiagnosticOnMove
| Mode::DiagnosticOnUnmatchArgs,
sym::This,
) => FormatArg::This,
// `{Self}`; the self type.
// - For trait declaration attributes that's the type that does not implement it.
// - for trait impl attributes, the implemented for type.
// - For ADT attributes, that's the type (which will be identical to `{This}`)
// - For everything else it doesn't make sense.
(
Mode::RustcOnUnimplemented
| Mode::DiagnosticOnUnimplemented
| Mode::DiagnosticOnMove
| Mode::DiagnosticOnConst,
kw::SelfUpper,
) => FormatArg::SelfUpper,
// Generic parameters.
// FIXME(mejrs) unfortunately, all the "special" symbols above might fall through,
// but at this time we are not aware of what generic parameters the trait actually has.
// If we find `ItemContext` or something we have to assume that's a generic parameter.
// We lint against that in `check_attr.rs` though.
(
Mode::RustcOnUnimplemented
| Mode::DiagnosticOnUnimplemented
| Mode::DiagnosticOnMove
| Mode::DiagnosticOnConst,
generic_param,
) => FormatArg::GenericParam { generic_param, span },
// Generics are explicitly not allowed, we print those back as is.
(Mode::DiagnosticOnUnknown | Mode::DiagnosticOnUnmatchArgs, as_is) => {
warnings.push(FormatWarning::DisallowedPlaceholder {
span,
attr: mode.as_str(),
allowed: mode.allowed_format_arguments(),
});
return FormatArg::AsIs(Symbol::intern(&format!("{{{as_is}}}")));
} }
(Mode::RustcOnUnimplemented { .. }, sym::Trait) => FormatArg::Trait,
// Any attribute can use these
(_, kw::SelfUpper) => FormatArg::SelfUpper,
(_, generic_param) => FormatArg::GenericParam { generic_param, span },
}, },
// `{:1}` and `{}` are ignored // `{:1}` and `{}` are ignored
Position::ArgumentIs(idx) => { Position::ArgumentIs(idx) => {
warnings.push(FormatWarning::PositionalArgument { warnings.push(FormatWarning::IndexedArgument { span });
span,
help: format!("use `{{{idx}}}` to print a number in braces"),
});
FormatArg::AsIs(Symbol::intern(&format!("{{{idx}}}"))) FormatArg::AsIs(Symbol::intern(&format!("{{{idx}}}")))
} }
Position::ArgumentImplicitlyIs(_) => { Position::ArgumentImplicitlyIs(_) => {
warnings.push(FormatWarning::PositionalArgument { warnings.push(FormatWarning::PositionalArgument { span });
span,
help: String::from("use `{{}}` to print empty braces"),
});
FormatArg::AsIs(sym::empty_braces) FormatArg::AsIs(sym::empty_braces)
} }
} }
@@ -473,7 +521,7 @@ fn warn_on_format_spec(
.as_ref() .as_ref()
.map(|inner| slice_span(input_span, inner.clone(), is_source_literal)) .map(|inner| slice_span(input_span, inner.clone(), is_source_literal))
.unwrap_or(input_span); .unwrap_or(input_span);
warnings.push(FormatWarning::InvalidSpecifier { span, name: spec.ty.into() }) warnings.push(FormatWarning::InvalidSpecifier { span })
} }
} }
+31 -17
View File
@@ -357,23 +357,6 @@ pub(crate) struct MalFormedDiagnosticAttributeLint {
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[diag("positional format arguments are not allowed here")]
#[help(
"only named format arguments with the name of one of the generic types are allowed in this context"
)]
pub(crate) struct DisallowedPositionalArgument;
#[derive(Diagnostic)]
#[diag("format arguments are not allowed here")]
#[help("consider removing this format argument")]
pub(crate) struct DisallowedPlaceholder;
#[derive(Diagnostic)]
#[diag("invalid format specifier")]
#[help("no format specifier are supported in this position")]
pub(crate) struct InvalidFormatSpecifier;
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag("{$description}")] #[diag("{$description}")]
pub(crate) struct WrappedParserError<'a> { pub(crate) struct WrappedParserError<'a> {
@@ -407,3 +390,34 @@ pub(crate) struct MissingOptionsForDiagnosticAttribute {
"only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma" "only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma"
)] )]
pub(crate) struct NonMetaItemDiagnosticAttribute; pub(crate) struct NonMetaItemDiagnosticAttribute;
#[derive(Diagnostic, Clone, Copy)]
pub(crate) enum FormatWarning {
#[diag("positional arguments are not permitted in diagnostic attributes")]
#[help("you can print empty braces by escaping them")]
PositionalArgument {
#[label("remove this format argument")]
span: Span,
},
#[diag("indexed format arguments are not permitted in diagnostic attributes")]
IndexedArgument {
#[label("remove this format argument")]
span: Span,
},
#[diag("format specifiers are not permitted in diagnostic attributes")]
InvalidSpecifier {
#[label("remove this format specifier")]
span: Span,
},
#[diag("this format argument is not allowed in `#[{$attr}]`")]
#[note("{$allowed}")]
DisallowedPlaceholder {
#[label("remove this format argument")]
span: Span,
attr: &'static str,
allowed: &'static str,
},
}
+1 -1
View File
@@ -1,8 +1,8 @@
use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_error_messages::MultiSpan; use rustc_error_messages::MultiSpan;
use rustc_errors::{Diag, DiagCtxtHandle, Level}; use rustc_errors::{Diag, DiagCtxtHandle, Level};
pub use rustc_lint_defs::AttributeLintKind;
use rustc_lint_defs::LintId; use rustc_lint_defs::LintId;
pub use rustc_lint_defs::{AttributeLintKind, FormatWarning};
use crate::HirId; use crate::HirId;
-7
View File
@@ -658,13 +658,6 @@ pub enum AttributeLintKind {
UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>),
} }
#[derive(Debug, Clone, HashStable_Generic)]
pub enum FormatWarning {
PositionalArgument { span: Span, help: String },
InvalidSpecifier { name: String, span: Span },
DisallowedPlaceholder { span: Span },
}
pub type RegisteredTools = FxIndexSet<Ident>; pub type RegisteredTools = FxIndexSet<Ident>;
/// Declares a static item of type `&'static Lint`. /// Declares a static item of type `&'static Lint`.
+1 -17
View File
@@ -201,9 +201,6 @@ fn check_attributes(
}, },
Attribute::Parsed(AttributeKind::OnUnimplemented{directive,..}) => {self.check_diagnostic_on_unimplemented(hir_id, directive.as_deref())}, Attribute::Parsed(AttributeKind::OnUnimplemented{directive,..}) => {self.check_diagnostic_on_unimplemented(hir_id, directive.as_deref())},
Attribute::Parsed(AttributeKind::OnConst{span, ..}) => {self.check_diagnostic_on_const(*span, hir_id, target, item)}, Attribute::Parsed(AttributeKind::OnConst{span, ..}) => {self.check_diagnostic_on_const(*span, hir_id, target, item)},
Attribute::Parsed(AttributeKind::OnUnmatchArgs { directive, .. }) => {
self.check_diagnostic_on_unmatch_args(hir_id, directive.as_deref())
},
Attribute::Parsed(AttributeKind::OnMove { directive , .. }) => { Attribute::Parsed(AttributeKind::OnMove { directive , .. }) => {
self.check_diagnostic_on_move(hir_id, directive.as_deref()) self.check_diagnostic_on_move(hir_id, directive.as_deref())
}, },
@@ -256,6 +253,7 @@ fn check_attributes(
| AttributeKind::NoMangle(..) | AttributeKind::NoMangle(..)
| AttributeKind::NoStd { .. } | AttributeKind::NoStd { .. }
| AttributeKind::OnUnknown { .. } | AttributeKind::OnUnknown { .. }
| AttributeKind::OnUnmatchArgs { .. }
| AttributeKind::Optimize(..) | AttributeKind::Optimize(..)
| AttributeKind::PanicRuntime | AttributeKind::PanicRuntime
| AttributeKind::PatchableFunctionEntry { .. } | AttributeKind::PatchableFunctionEntry { .. }
@@ -562,20 +560,6 @@ fn check_diagnostic_on_const(
// ...whose generics would that be, anyway? The traits' or the impls'? // ...whose generics would that be, anyway? The traits' or the impls'?
} }
/// Checks use of generic formatting parameters in `#[diagnostic::on_unmatch_args]`.
fn check_diagnostic_on_unmatch_args(&self, hir_id: HirId, directive: Option<&Directive>) {
if let Some(directive) = directive {
directive.visit_params(&mut |argument_name, span| {
self.tcx.emit_node_span_lint(
MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
hir_id,
span,
errors::OnUnmatchArgsMalformedFormatLiterals { name: argument_name },
)
});
}
}
/// Checks use of generic formatting parameters in `#[diagnostic::on_move]` /// Checks use of generic formatting parameters in `#[diagnostic::on_move]`
fn check_diagnostic_on_move(&self, hir_id: HirId, directive: Option<&Directive>) { fn check_diagnostic_on_move(&self, hir_id: HirId, directive: Option<&Directive>) {
if let Some(directive) = directive { if let Some(directive) = directive {
-7
View File
@@ -1303,10 +1303,3 @@ pub(crate) struct UnknownFormatParameterForOnUnimplementedAttr {
pub(crate) struct OnMoveMalformedFormatLiterals { pub(crate) struct OnMoveMalformedFormatLiterals {
pub name: Symbol, pub name: Symbol,
} }
#[derive(Diagnostic)]
#[diag("unknown parameter `{$name}`")]
#[help(r#"use {"`{This}`"} to refer to the macro name"#)]
pub(crate) struct OnUnmatchArgsMalformedFormatLiterals {
pub name: Symbol,
}
+8 -1
View File
@@ -2,6 +2,7 @@
use std::mem; use std::mem;
use itertools::Itertools;
use rustc_ast::{Item, NodeId}; use rustc_ast::{Item, NodeId};
use rustc_attr_parsing::AttributeParser; use rustc_attr_parsing::AttributeParser;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
@@ -879,8 +880,14 @@ fn throw_unresolved_import_error(
let (message, label, notes) = let (message, label, notes) =
// Feature gating for `on_unknown_attr` happens initialization of the field // Feature gating for `on_unknown_attr` happens initialization of the field
if let Some(directive) = errors[0].1.on_unknown_attr.as_ref().map(|a| &a.directive) { if let Some(directive) = errors[0].1.on_unknown_attr.as_ref().map(|a| &a.directive) {
let this = errors.iter().map(|(_import, err)| {
// Is this unwrap_or reachable?
err.segment.unwrap_or(kw::Underscore)
}).join(", ");
let args = FormatArgs { let args = FormatArgs {
this: paths.join(", "), this,
// Unused // Unused
this_sugared: String::new(), this_sugared: String::new(),
// Unused // Unused
@@ -4,7 +4,6 @@
use rustc_hir::attrs::diagnostic::{ConditionOptions, CustomDiagnostic, FormatArgs}; use rustc_hir::attrs::diagnostic::{ConditionOptions, CustomDiagnostic, FormatArgs};
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::find_attr; use rustc_hir::find_attr;
pub use rustc_hir::lints::FormatWarning;
use rustc_middle::ty::print::PrintTraitRefExt; use rustc_middle::ty::print::PrintTraitRefExt;
use rustc_middle::ty::{self, GenericParamDef, GenericParamDefKind}; use rustc_middle::ty::{self, GenericParamDef, GenericParamDefKind};
use rustc_span::Symbol; use rustc_span::Symbol;
@@ -31,17 +31,17 @@ pub trait MultiLine4 {}
#[diagnostic::on_unimplemented(message = "here is a big \ #[diagnostic::on_unimplemented(message = "here is a big \
multiline string \ multiline string \
{Self:+}")] {Self:+}")]
//~^ ERROR invalid format specifier [malformed_diagnostic_format_literals] //~^ ERROR format specifiers are not permitted in diagnostic attributes [malformed_diagnostic_format_literals]
pub trait MultiLineFmt {} pub trait MultiLineFmt {}
#[diagnostic::on_unimplemented(message = "here is a big \ #[diagnostic::on_unimplemented(message = "here is a big \
multiline string {Self:X}")] multiline string {Self:X}")]
//~^ ERROR invalid format specifier [malformed_diagnostic_format_literals] //~^ ERROR format specifiers are not permitted in diagnostic attributes [malformed_diagnostic_format_literals]
pub trait MultiLineFmt2 {} pub trait MultiLineFmt2 {}
#[diagnostic::on_unimplemented(message = "here is a big \ #[diagnostic::on_unimplemented(message = "here is a big \
multiline string {Self:#}")] multiline string {Self:#}")]
//~^ ERROR invalid format specifier [malformed_diagnostic_format_literals] //~^ ERROR format specifiers are not permitted in diagnostic attributes [malformed_diagnostic_format_literals]
pub trait MultiLineFmt3 {} pub trait MultiLineFmt3 {}
@@ -51,5 +51,5 @@ pub trait MultiLineFmt3 {}
\ \
\ \
multiline string {Self:?}")] multiline string {Self:?}")]
//~^ ERROR invalid format specifier [malformed_diagnostic_format_literals] //~^ ERROR format specifiers are not permitted in diagnostic attributes [malformed_diagnostic_format_literals]
pub trait MultiLineFmt4 {} pub trait MultiLineFmt4 {}
@@ -36,37 +36,29 @@ LL | multiline string {unknown}")]
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
error: invalid format specifier error: format specifiers are not permitted in diagnostic attributes
--> $DIR/multiline_spans.rs:33:47 --> $DIR/multiline_spans.rs:33:47
| |
LL | ... {Self:+}")] LL | ... {Self:+}")]
| ^^ | ^^ remove this format specifier
|
= help: no format specifier are supported in this position
error: invalid format specifier error: format specifiers are not permitted in diagnostic attributes
--> $DIR/multiline_spans.rs:38:64 --> $DIR/multiline_spans.rs:38:64
| |
LL | ... multiline string {Self:X}")] LL | ... multiline string {Self:X}")]
| ^^ | ^^ remove this format specifier
|
= help: no format specifier are supported in this position
error: invalid format specifier error: format specifiers are not permitted in diagnostic attributes
--> $DIR/multiline_spans.rs:43:27 --> $DIR/multiline_spans.rs:43:27
| |
LL | multiline string {Self:#}")] LL | multiline string {Self:#}")]
| ^^ | ^^ remove this format specifier
|
= help: no format specifier are supported in this position
error: invalid format specifier error: format specifiers are not permitted in diagnostic attributes
--> $DIR/multiline_spans.rs:53:27 --> $DIR/multiline_spans.rs:53:27
| |
LL | multiline string {Self:?}")] LL | multiline string {Self:?}")]
| ^^ | ^^ remove this format specifier
|
= help: no format specifier are supported in this position
error: aborting due to 8 previous errors error: aborting due to 8 previous errors
@@ -1,3 +1,4 @@
//@ dont-require-annotations: NOTE
#![feature(diagnostic_on_move)] #![feature(diagnostic_on_move)]
#[diagnostic::on_move( #[diagnostic::on_move(
@@ -10,6 +11,7 @@
#[diagnostic::on_move( #[diagnostic::on_move(
message="Foo for {X}", message="Foo for {X}",
label="Bar for {X}", label="Bar for {X}",
note = "This is `{This}`",
)] )]
struct MyType<X> { struct MyType<X> {
_x: X, _x: X,
@@ -21,12 +23,15 @@ fn takes_mytype<X>(_: MyType<X>) {}
fn main() { fn main() {
let foo = Foo; let foo = Foo;
//~^ NOTE Bar for Foo
takes_foo(foo); takes_foo(foo);
let bar = foo; let bar = foo;
//~^ERROR Foo for Foo //~^ERROR Foo for Foo
let mytype = MyType { _x: 0 }; let mytype = MyType { _x: 0 };
//~^ NOTE Bar for i32
takes_mytype(mytype); takes_mytype(mytype);
let baz = mytype; let baz = mytype;
//~^ERROR Foo for i32 //~^ERROR Foo for i32
//~|NOTE This is `MyType`
} }
@@ -1,22 +1,23 @@
error[E0382]: Foo for Foo error[E0382]: Foo for Foo
--> $DIR/on_move_with_format.rs:25:15 --> $DIR/on_move_with_format.rs:28:15
| |
LL | let foo = Foo; LL | let foo = Foo;
| --- Bar for Foo | --- Bar for Foo
LL |
LL | takes_foo(foo); LL | takes_foo(foo);
| --- value moved here | --- value moved here
LL | let bar = foo; LL | let bar = foo;
| ^^^ value used here after move | ^^^ value used here after move
| |
note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary note: consider changing this parameter type in function `takes_foo` to borrow instead if owning the value isn't necessary
--> $DIR/on_move_with_format.rs:18:17 --> $DIR/on_move_with_format.rs:20:17
| |
LL | fn takes_foo(_: Foo) {} LL | fn takes_foo(_: Foo) {}
| --------- ^^^ this parameter takes ownership of the value | --------- ^^^ this parameter takes ownership of the value
| | | |
| in this function | in this function
note: if `Foo` implemented `Clone`, you could clone the value note: if `Foo` implemented `Clone`, you could clone the value
--> $DIR/on_move_with_format.rs:8:1 --> $DIR/on_move_with_format.rs:9:1
| |
LL | struct Foo; LL | struct Foo;
| ^^^^^^^^^^ consider implementing `Clone` for this type | ^^^^^^^^^^ consider implementing `Clone` for this type
@@ -25,24 +26,26 @@ LL | takes_foo(foo);
| --- you could clone this value | --- you could clone this value
error[E0382]: Foo for i32 error[E0382]: Foo for i32
--> $DIR/on_move_with_format.rs:30:15 --> $DIR/on_move_with_format.rs:34:15
| |
LL | let mytype = MyType { _x: 0 }; LL | let mytype = MyType { _x: 0 };
| ------ Bar for i32 | ------ Bar for i32
LL |
LL | takes_mytype(mytype); LL | takes_mytype(mytype);
| ------ value moved here | ------ value moved here
LL | let baz = mytype; LL | let baz = mytype;
| ^^^^^^ value used here after move | ^^^^^^ value used here after move
| |
= note: This is `MyType`
note: consider changing this parameter type in function `takes_mytype` to borrow instead if owning the value isn't necessary note: consider changing this parameter type in function `takes_mytype` to borrow instead if owning the value isn't necessary
--> $DIR/on_move_with_format.rs:20:23 --> $DIR/on_move_with_format.rs:22:23
| |
LL | fn takes_mytype<X>(_: MyType<X>) {} LL | fn takes_mytype<X>(_: MyType<X>) {}
| ------------ ^^^^^^^^^ this parameter takes ownership of the value | ------------ ^^^^^^^^^ this parameter takes ownership of the value
| | | |
| in this function | in this function
note: if `MyType<i32>` implemented `Clone`, you could clone the value note: if `MyType<i32>` implemented `Clone`, you could clone the value
--> $DIR/on_move_with_format.rs:14:1 --> $DIR/on_move_with_format.rs:16:1
| |
LL | struct MyType<X> { LL | struct MyType<X> {
| ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type
@@ -4,24 +4,24 @@
trait ImportantTrait1 {} trait ImportantTrait1 {}
#[diagnostic::on_unimplemented(message = "Test {}")] #[diagnostic::on_unimplemented(message = "Test {}")]
//~^WARN positional format arguments are not allowed here //~^WARN positional arguments are not permitted in diagnostic attributes
trait ImportantTrait2 {} trait ImportantTrait2 {}
#[diagnostic::on_unimplemented(message = "Test {1:}")] #[diagnostic::on_unimplemented(message = "Test {1:}")]
//~^WARN positional format arguments are not allowed here //~^WARN indexed format arguments are not permitted in diagnostic attributes
//~|WARN invalid format specifier [malformed_diagnostic_format_literals] //~|WARN format specifiers are not permitted in diagnostic attributes [malformed_diagnostic_format_literals]
trait ImportantTrait3 {} trait ImportantTrait3 {}
#[diagnostic::on_unimplemented(message = "Test {Self:123}")] #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
//~^WARN invalid format specifier //~^WARN format specifiers are not permitted in diagnostic attributes
trait ImportantTrait4 {} trait ImportantTrait4 {}
#[diagnostic::on_unimplemented(message = "Test {Self:!}")] #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
//~^WARN invalid format specifier [malformed_diagnostic_format_literals] //~^WARN format specifiers are not permitted in diagnostic attributes [malformed_diagnostic_format_literals]
trait ImportantTrait5 {} trait ImportantTrait5 {}
#[diagnostic::on_unimplemented(message = "Test {Self:}")] #[diagnostic::on_unimplemented(message = "Test {Self:}")]
//~^WARN invalid format specifier [malformed_diagnostic_format_literals] //~^WARN format specifiers are not permitted in diagnostic attributes [malformed_diagnostic_format_literals]
trait ImportantTrait6 {} trait ImportantTrait6 {}
@@ -8,53 +8,43 @@ LL | #[diagnostic::on_unimplemented(message = "{{Test } thing")]
| |
= note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default = note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
warning: positional format arguments are not allowed here warning: positional arguments are not permitted in diagnostic attributes
--> $DIR/broken_format.rs:6:49 --> $DIR/broken_format.rs:6:49
| |
LL | #[diagnostic::on_unimplemented(message = "Test {}")] LL | #[diagnostic::on_unimplemented(message = "Test {}")]
| ^ | ^ remove this format argument
| |
= help: only named format arguments with the name of one of the generic types are allowed in this context = help: you can print empty braces by escaping them
warning: invalid format specifier warning: format specifiers are not permitted in diagnostic attributes
--> $DIR/broken_format.rs:10:50 --> $DIR/broken_format.rs:10:50
| |
LL | #[diagnostic::on_unimplemented(message = "Test {1:}")] LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
| ^ | ^ remove this format specifier
|
= help: no format specifier are supported in this position
warning: positional format arguments are not allowed here warning: indexed format arguments are not permitted in diagnostic attributes
--> $DIR/broken_format.rs:10:49 --> $DIR/broken_format.rs:10:49
| |
LL | #[diagnostic::on_unimplemented(message = "Test {1:}")] LL | #[diagnostic::on_unimplemented(message = "Test {1:}")]
| ^ | ^ remove this format argument
|
= help: only named format arguments with the name of one of the generic types are allowed in this context
warning: invalid format specifier warning: format specifiers are not permitted in diagnostic attributes
--> $DIR/broken_format.rs:15:53 --> $DIR/broken_format.rs:15:53
| |
LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")] LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")]
| ^^^^ | ^^^^ remove this format specifier
|
= help: no format specifier are supported in this position
warning: invalid format specifier warning: format specifiers are not permitted in diagnostic attributes
--> $DIR/broken_format.rs:19:53 --> $DIR/broken_format.rs:19:53
| |
LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")] LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")]
| ^^ | ^^ remove this format specifier
|
= help: no format specifier are supported in this position
warning: invalid format specifier warning: format specifiers are not permitted in diagnostic attributes
--> $DIR/broken_format.rs:23:53 --> $DIR/broken_format.rs:23:53
| |
LL | #[diagnostic::on_unimplemented(message = "Test {Self:}")] LL | #[diagnostic::on_unimplemented(message = "Test {Self:}")]
| ^ | ^ remove this format specifier
|
= help: no format specifier are supported in this position
error[E0277]: {{Test } thing error[E0277]: {{Test } thing
--> $DIR/broken_format.rs:36:13 --> $DIR/broken_format.rs:36:13
@@ -1,32 +1,35 @@
#![feature(diagnostic_on_unknown)] #![feature(diagnostic_on_unknown)]
#[diagnostic::on_unknown(message = "foo {}")] #[diagnostic::on_unknown(message = "foo {}")]
//~^ WARN: format arguments are not allowed here //~^ WARN: positional arguments are not permitted in diagnostic attributes
use std::does_not_exist; use std::does_not_exist;
//~^ ERROR: foo {} //~^ ERROR: foo {}
#[diagnostic::on_unknown(message = "foo {A}")] #[diagnostic::on_unknown(message = "foo {A}")]
//~^ WARN: format arguments are not allowed here //~^ WARN: this format argument is not allowed in `#[diagnostic::on_unknown]`
use std::does_not_exist2; use std::does_not_exist2;
//~^ ERROR: foo {} //~^ ERROR: foo {A}
#[diagnostic::on_unknown(label = "foo {}")] #[diagnostic::on_unknown(label = "foo {}")]
//~^ WARN: format arguments are not allowed here //~^ WARN: positional arguments are not permitted in diagnostic attributes
use std::does_not_exist3; use std::does_not_exist3;
//~^ ERROR: unresolved import `std::does_not_exist3` //~^ ERROR: unresolved import `std::does_not_exist3`
#[diagnostic::on_unknown(label = "foo {A}")] #[diagnostic::on_unknown(label = "foo {A}")]
//~^ WARN: format arguments are not allowed here //~^ WARN: this format argument is not allowed in `#[diagnostic::on_unknown]`
use std::does_not_exist4; use std::does_not_exist4;
//~^ ERROR: unresolved import `std::does_not_exist4` //~^ ERROR: unresolved import `std::does_not_exist4`
#[diagnostic::on_unknown(note = "foo {}")] #[diagnostic::on_unknown(note = "foo {}")]
//~^ WARN: format arguments are not allowed here //~^ WARN: positional arguments are not permitted in diagnostic attributes
use std::does_not_exist5; use std::does_not_exist5;
//~^ ERROR: unresolved import `std::does_not_exist5` //~^ ERROR: unresolved import `std::does_not_exist5`
#[diagnostic::on_unknown(note = "foo {A}")] #[diagnostic::on_unknown(note = "foo {Self} {ItemContext} {Trait} {A}")]
//~^ WARN: format arguments are not allowed here //~^ WARN: this format argument is not allowed in `#[diagnostic::on_unknown]`
//~| WARN: this format argument is not allowed in `#[diagnostic::on_unknown]`
//~| WARN: this format argument is not allowed in `#[diagnostic::on_unknown]`
//~| WARN: this format argument is not allowed in `#[diagnostic::on_unknown]`
use std::does_not_exist6; use std::does_not_exist6;
//~^ ERROR: unresolved import `std::does_not_exist6` //~^ ERROR: unresolved import `std::does_not_exist6`
@@ -6,7 +6,7 @@ LL | use std::does_not_exist;
| |
= note: unresolved import `std::does_not_exist` = note: unresolved import `std::does_not_exist`
error[E0432]: foo {} error[E0432]: foo {A}
--> $DIR/incorrect_format_string.rs:10:5 --> $DIR/incorrect_format_string.rs:10:5
| |
LL | use std::does_not_exist2; LL | use std::does_not_exist2;
@@ -24,7 +24,7 @@ error[E0432]: unresolved import `std::does_not_exist4`
--> $DIR/incorrect_format_string.rs:20:5 --> $DIR/incorrect_format_string.rs:20:5
| |
LL | use std::does_not_exist4; LL | use std::does_not_exist4;
| ^^^^^^^^^^^^^^^^^^^^ foo {} | ^^^^^^^^^^^^^^^^^^^^ foo {A}
error[E0432]: unresolved import `std::does_not_exist5` error[E0432]: unresolved import `std::does_not_exist5`
--> $DIR/incorrect_format_string.rs:25:5 --> $DIR/incorrect_format_string.rs:25:5
@@ -35,62 +35,86 @@ LL | use std::does_not_exist5;
= note: foo {} = note: foo {}
error[E0432]: unresolved import `std::does_not_exist6` error[E0432]: unresolved import `std::does_not_exist6`
--> $DIR/incorrect_format_string.rs:30:5 --> $DIR/incorrect_format_string.rs:33:5
| |
LL | use std::does_not_exist6; LL | use std::does_not_exist6;
| ^^^^^^^^^^^^^^^^^^^^ no `does_not_exist6` in the root | ^^^^^^^^^^^^^^^^^^^^ no `does_not_exist6` in the root
| |
= note: foo {} = note: foo {Self} {ItemContext} {Trait} {A}
warning: format arguments are not allowed here warning: positional arguments are not permitted in diagnostic attributes
--> $DIR/incorrect_format_string.rs:3:42 --> $DIR/incorrect_format_string.rs:3:42
| |
LL | #[diagnostic::on_unknown(message = "foo {}")] LL | #[diagnostic::on_unknown(message = "foo {}")]
| ^ | ^ remove this format argument
| |
= help: consider removing this format argument = help: you can print empty braces by escaping them
= note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default = note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
warning: format arguments are not allowed here warning: this format argument is not allowed in `#[diagnostic::on_unknown]`
--> $DIR/incorrect_format_string.rs:8:42 --> $DIR/incorrect_format_string.rs:8:42
| |
LL | #[diagnostic::on_unknown(message = "foo {A}")] LL | #[diagnostic::on_unknown(message = "foo {A}")]
| ^ | ^ remove this format argument
| |
= help: consider removing this format argument = note: only `This` is allowed as a format argument, referring to the failed import
warning: format arguments are not allowed here warning: positional arguments are not permitted in diagnostic attributes
--> $DIR/incorrect_format_string.rs:13:40 --> $DIR/incorrect_format_string.rs:13:40
| |
LL | #[diagnostic::on_unknown(label = "foo {}")] LL | #[diagnostic::on_unknown(label = "foo {}")]
| ^ | ^ remove this format argument
| |
= help: consider removing this format argument = help: you can print empty braces by escaping them
warning: format arguments are not allowed here warning: this format argument is not allowed in `#[diagnostic::on_unknown]`
--> $DIR/incorrect_format_string.rs:18:40 --> $DIR/incorrect_format_string.rs:18:40
| |
LL | #[diagnostic::on_unknown(label = "foo {A}")] LL | #[diagnostic::on_unknown(label = "foo {A}")]
| ^ | ^ remove this format argument
| |
= help: consider removing this format argument = note: only `This` is allowed as a format argument, referring to the failed import
warning: format arguments are not allowed here warning: positional arguments are not permitted in diagnostic attributes
--> $DIR/incorrect_format_string.rs:23:39 --> $DIR/incorrect_format_string.rs:23:39
| |
LL | #[diagnostic::on_unknown(note = "foo {}")] LL | #[diagnostic::on_unknown(note = "foo {}")]
| ^ | ^ remove this format argument
| |
= help: consider removing this format argument = help: you can print empty braces by escaping them
warning: format arguments are not allowed here warning: this format argument is not allowed in `#[diagnostic::on_unknown]`
--> $DIR/incorrect_format_string.rs:28:39 --> $DIR/incorrect_format_string.rs:28:39
| |
LL | #[diagnostic::on_unknown(note = "foo {A}")] LL | #[diagnostic::on_unknown(note = "foo {Self} {ItemContext} {Trait} {A}")]
| ^ | ^^^^ remove this format argument
| |
= help: consider removing this format argument = note: only `This` is allowed as a format argument, referring to the failed import
error: aborting due to 6 previous errors; 6 warnings emitted warning: this format argument is not allowed in `#[diagnostic::on_unknown]`
--> $DIR/incorrect_format_string.rs:28:46
|
LL | #[diagnostic::on_unknown(note = "foo {Self} {ItemContext} {Trait} {A}")]
| ^^^^^^^^^^^ remove this format argument
|
= note: only `This` is allowed as a format argument, referring to the failed import
warning: this format argument is not allowed in `#[diagnostic::on_unknown]`
--> $DIR/incorrect_format_string.rs:28:60
|
LL | #[diagnostic::on_unknown(note = "foo {Self} {ItemContext} {Trait} {A}")]
| ^^^^^ remove this format argument
|
= note: only `This` is allowed as a format argument, referring to the failed import
warning: this format argument is not allowed in `#[diagnostic::on_unknown]`
--> $DIR/incorrect_format_string.rs:28:68
|
LL | #[diagnostic::on_unknown(note = "foo {Self} {ItemContext} {Trait} {A}")]
| ^ remove this format argument
|
= note: only `This` is allowed as a format argument, referring to the failed import
error: aborting due to 6 previous errors; 9 warnings emitted
For more information about this error, try `rustc --explain E0432`. For more information about this error, try `rustc --explain E0432`.
@@ -0,0 +1,45 @@
#![feature(diagnostic_on_unknown)]
#![crate_type = "lib"]
pub mod foo {}
#[diagnostic::on_unknown(note = "the name of this item is a single ident: `{This}`")]
use foo::Foo;
//~^ERROR unresolved import `foo::Foo`
//~|NOTE the name of this item is a single ident: `Foo`
//~|NOTE no `Foo` in `foo`
#[diagnostic::on_unknown(note = "the name of this item is a single ident: `{This}`")]
use foo::foo::Foo;
//~^ERROR unresolved import `foo::foo`
//~|NOTE the name of this item is a single ident: `foo`
//~|NOTE could not find `foo` in `foo`
#[diagnostic::on_unknown(note = "the name of this item is two idents: `{This}`")]
use foo::{Bar, Foo};
//~^ERROR unresolved imports `foo::Bar`, `foo::Foo`
//~|NOTE the name of this item is two idents: `Bar, Foo`
//~|NOTE no `Foo` in `foo`
//~|NOTE no `Bar` in `foo`
#[diagnostic::on_unknown(note = "the name of this item is many idents: `{This}`")]
use foo::{
Foo,
//~^ERROR unresolved imports `foo::Foo`, `foo::bar`
//~|NOTE the name of this item is many idents: `Foo, bar`
//~|NOTE no `Foo` in `foo`
bar::{Baz, Biz},
//~^NOTE could not find `bar` in `foo`
};
#[diagnostic::on_unknown(note = "the name of this is: `{This}`")]
pub use doesnt_exist::*;
//~^ERROR unresolved import `doesnt_exist`
//~|NOTE use of unresolved module or unlinked crate `doesnt_exist`
//~|NOTE the name of this is: `doesnt_exist`
#[diagnostic::on_unknown(note = "the name of this item is a single ident: `{This}`")]
use foo::Foo as DoNotUseForThisParam;
//~^ERROR unresolved import `foo::Foo`
//~|NOTE the name of this item is a single ident: `Foo`
//~|NOTE no `Foo` in `foo`
@@ -0,0 +1,60 @@
error[E0432]: unresolved import `foo::Foo`
--> $DIR/this_format_argument.rs:7:5
|
LL | use foo::Foo;
| ^^^^^^^^ no `Foo` in `foo`
|
= note: the name of this item is a single ident: `Foo`
error[E0432]: unresolved import `foo::foo`
--> $DIR/this_format_argument.rs:13:10
|
LL | use foo::foo::Foo;
| ^^^ could not find `foo` in `foo`
|
= note: the name of this item is a single ident: `foo`
error[E0432]: unresolved imports `foo::Bar`, `foo::Foo`
--> $DIR/this_format_argument.rs:19:11
|
LL | use foo::{Bar, Foo};
| ^^^ ^^^ no `Foo` in `foo`
| |
| no `Bar` in `foo`
|
= note: the name of this item is two idents: `Bar, Foo`
error[E0432]: unresolved imports `foo::Foo`, `foo::bar`
--> $DIR/this_format_argument.rs:27:5
|
LL | Foo,
| ^^^ no `Foo` in `foo`
...
LL | bar::{Baz, Biz},
| ^^^ could not find `bar` in `foo`
|
= note: the name of this item is many idents: `Foo, bar`
error[E0432]: unresolved import `doesnt_exist`
--> $DIR/this_format_argument.rs:36:9
|
LL | pub use doesnt_exist::*;
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `doesnt_exist`
|
= note: the name of this is: `doesnt_exist`
help: you might be missing a crate named `doesnt_exist`, add it to your project and import it in your code
|
LL + extern crate doesnt_exist;
|
error[E0432]: unresolved import `foo::Foo`
--> $DIR/this_format_argument.rs:42:5
|
LL | use foo::Foo as DoNotUseForThisParam;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `Foo` in `foo`
|
= note: the name of this item is a single ident: `Foo`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0432`.
@@ -7,7 +7,7 @@ pub mod foo {
message = "first message", message = "first message",
label = "first label", label = "first label",
note = "custom note", note = "custom note",
note = "custom note 2" note = "custom note 2",
)] )]
use foo::Foo; use foo::Foo;
//~^ERROR first message //~^ERROR first message
@@ -3,7 +3,10 @@
#[diagnostic::on_unmatch_args( #[diagnostic::on_unmatch_args(
message = "{T}! is missing arguments", message = "{T}! is missing arguments",
//~^ WARN unknown parameter `T` //~^ WARN this format argument is not allowed in `#[diagnostic::on_unmatch_args]`
//~| NOTE only `This` is allowed as a format argument
//~| NOTE remove this format argument
//~| NOTE `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
)] )]
macro_rules! pair { macro_rules! pair {
($ty:ty, $value:expr) => {}; ($ty:ty, $value:expr) => {};
@@ -1,10 +1,10 @@
warning: unknown parameter `T` warning: this format argument is not allowed in `#[diagnostic::on_unmatch_args]`
--> $DIR/report_warning_on_invalid_formats.rs:5:17 --> $DIR/report_warning_on_invalid_formats.rs:5:17
| |
LL | message = "{T}! is missing arguments", LL | message = "{T}! is missing arguments",
| ^ | ^ remove this format argument
| |
= help: use `{This}` to refer to the macro name = note: only `This` is allowed as a format argument, referring to the macro's name
= note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default = note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
warning: 1 warning emitted warning: 1 warning emitted
+2 -1
View File
@@ -23,7 +23,8 @@ trait NoContent {}
trait ParameterNotPresent<A, B> {} trait ParameterNotPresent<A, B> {}
#[rustc_on_unimplemented(label = "Unimplemented error on `{Self}` with params `<{A},{B},{}>`")] #[rustc_on_unimplemented(label = "Unimplemented error on `{Self}` with params `<{A},{B},{}>`")]
//~^ WARN positional format arguments are not allowed here //~^ WARN positional arguments are not permitted in diagnostic attributes
//~| NOTE remove this format argument
trait NoPositionalArgs<A, B> {} trait NoPositionalArgs<A, B> {}
#[rustc_on_unimplemented(lorem = "")] #[rustc_on_unimplemented(lorem = "")]
+21 -21
View File
@@ -1,59 +1,59 @@
error[E0232]: invalid flag in `on`-clause error[E0232]: invalid flag in `on`-clause
--> $DIR/bad-annotation.rs:45:44 --> $DIR/bad-annotation.rs:46:44
| |
LL | #[rustc_on_unimplemented(message = "x", on(desugared, message = "y"))] LL | #[rustc_on_unimplemented(message = "x", on(desugared, message = "y"))]
| ^^^^^^^^^ expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `desugared` | ^^^^^^^^^ expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `desugared`
error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]` error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]`
--> $DIR/bad-annotation.rs:50:26 --> $DIR/bad-annotation.rs:51:26
| |
LL | #[rustc_on_unimplemented(on(), message = "y")] LL | #[rustc_on_unimplemented(on(), message = "y")]
| ^^^^ empty `on`-clause here | ^^^^ empty `on`-clause here
error[E0232]: literals inside `on`-clauses are not supported error[E0232]: literals inside `on`-clauses are not supported
--> $DIR/bad-annotation.rs:70:29 --> $DIR/bad-annotation.rs:71:29
| |
LL | #[rustc_on_unimplemented(on("y", message = "y"))] LL | #[rustc_on_unimplemented(on("y", message = "y"))]
| ^^^ unexpected literal here | ^^^ unexpected literal here
error[E0232]: literals inside `on`-clauses are not supported error[E0232]: literals inside `on`-clauses are not supported
--> $DIR/bad-annotation.rs:75:29 --> $DIR/bad-annotation.rs:76:29
| |
LL | #[rustc_on_unimplemented(on(42, message = "y"))] LL | #[rustc_on_unimplemented(on(42, message = "y"))]
| ^^ unexpected literal here | ^^ unexpected literal here
error[E0232]: expected a single predicate in `not(..)` error[E0232]: expected a single predicate in `not(..)`
--> $DIR/bad-annotation.rs:80:32 --> $DIR/bad-annotation.rs:81:32
| |
LL | #[rustc_on_unimplemented(on(not(a, b), message = "y"))] LL | #[rustc_on_unimplemented(on(not(a, b), message = "y"))]
| ^^^^^^ unexpected quantity of predicates here | ^^^^^^ unexpected quantity of predicates here
error[E0232]: expected a single predicate in `not(..)` error[E0232]: expected a single predicate in `not(..)`
--> $DIR/bad-annotation.rs:85:32 --> $DIR/bad-annotation.rs:86:32
| |
LL | #[rustc_on_unimplemented(on(not(), message = "y"))] LL | #[rustc_on_unimplemented(on(not(), message = "y"))]
| ^^ unexpected quantity of predicates here | ^^ unexpected quantity of predicates here
error[E0232]: expected an identifier inside this `on`-clause error[E0232]: expected an identifier inside this `on`-clause
--> $DIR/bad-annotation.rs:90:29 --> $DIR/bad-annotation.rs:91:29
| |
LL | #[rustc_on_unimplemented(on(thing::What, message = "y"))] LL | #[rustc_on_unimplemented(on(thing::What, message = "y"))]
| ^^^^^^^^^^^ expected an identifier here, not `thing::What` | ^^^^^^^^^^^ expected an identifier here, not `thing::What`
error[E0232]: expected an identifier inside this `on`-clause error[E0232]: expected an identifier inside this `on`-clause
--> $DIR/bad-annotation.rs:95:29 --> $DIR/bad-annotation.rs:96:29
| |
LL | #[rustc_on_unimplemented(on(thing::What = "value", message = "y"))] LL | #[rustc_on_unimplemented(on(thing::What = "value", message = "y"))]
| ^^^^^^^^^^^ expected an identifier here, not `thing::What` | ^^^^^^^^^^^ expected an identifier here, not `thing::What`
error[E0232]: this predicate is invalid error[E0232]: this predicate is invalid
--> $DIR/bad-annotation.rs:100:29 --> $DIR/bad-annotation.rs:101:29
| |
LL | #[rustc_on_unimplemented(on(aaaaaaaaaaaaaa(a, b), message = "y"))] LL | #[rustc_on_unimplemented(on(aaaaaaaaaaaaaa(a, b), message = "y"))]
| ^^^^^^^^^^^^^^ expected one of `any`, `all` or `not` here, not `aaaaaaaaaaaaaa` | ^^^^^^^^^^^^^^ expected one of `any`, `all` or `not` here, not `aaaaaaaaaaaaaa`
error[E0232]: invalid flag in `on`-clause error[E0232]: invalid flag in `on`-clause
--> $DIR/bad-annotation.rs:105:29 --> $DIR/bad-annotation.rs:106:29
| |
LL | #[rustc_on_unimplemented(on(something, message = "y"))] LL | #[rustc_on_unimplemented(on(something, message = "y"))]
| ^^^^^^^^^ expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something` | ^^^^^^^^^ expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something`
@@ -67,13 +67,13 @@ LL | #[rustc_on_unimplemented(label = "Unimplemented error on `{Self}` with para
= note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default = note: `#[warn(malformed_diagnostic_format_literals)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
warning: there is no parameter `_Self` on trait `InvalidName` warning: there is no parameter `_Self` on trait `InvalidName`
--> $DIR/bad-annotation.rs:110:29 --> $DIR/bad-annotation.rs:111:29
| |
LL | #[rustc_on_unimplemented(on(_Self = "y", message = "y"))] LL | #[rustc_on_unimplemented(on(_Self = "y", message = "y"))]
| ^^^^^^^^^^^ | ^^^^^^^^^^^
warning: there is no parameter `abc` on trait `InvalidName2` warning: there is no parameter `abc` on trait `InvalidName2`
--> $DIR/bad-annotation.rs:114:29 --> $DIR/bad-annotation.rs:115:29
| |
LL | #[rustc_on_unimplemented(on(abc = "y", message = "y"))] LL | #[rustc_on_unimplemented(on(abc = "y", message = "y"))]
| ^^^^^^^^^ | ^^^^^^^^^
@@ -87,16 +87,16 @@ LL | #[rustc_on_unimplemented]
= help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented> = help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented>
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
warning: positional format arguments are not allowed here warning: positional arguments are not permitted in diagnostic attributes
--> $DIR/bad-annotation.rs:25:90 --> $DIR/bad-annotation.rs:25:90
| |
LL | #[rustc_on_unimplemented(label = "Unimplemented error on `{Self}` with params `<{A},{B},{}>`")] LL | #[rustc_on_unimplemented(label = "Unimplemented error on `{Self}` with params `<{A},{B},{}>`")]
| ^ | ^ remove this format argument
| |
= help: only named format arguments with the name of one of the generic types are allowed in this context = help: you can print empty braces by escaping them
warning: malformed `rustc_on_unimplemented` attribute warning: malformed `rustc_on_unimplemented` attribute
--> $DIR/bad-annotation.rs:29:26 --> $DIR/bad-annotation.rs:30:26
| |
LL | #[rustc_on_unimplemented(lorem = "")] LL | #[rustc_on_unimplemented(lorem = "")]
| ^^^^^^^^^^ invalid option found here | ^^^^^^^^^^ invalid option found here
@@ -104,7 +104,7 @@ LL | #[rustc_on_unimplemented(lorem = "")]
= help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented> = help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented>
warning: malformed `rustc_on_unimplemented` attribute warning: malformed `rustc_on_unimplemented` attribute
--> $DIR/bad-annotation.rs:34:26 --> $DIR/bad-annotation.rs:35:26
| |
LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))] LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
| ^^^^^^^^^^^^^^^^^^^ invalid option found here | ^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -112,7 +112,7 @@ LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
= help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented> = help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented>
warning: `message` is ignored due to previous definition of `message` warning: `message` is ignored due to previous definition of `message`
--> $DIR/bad-annotation.rs:39:41 --> $DIR/bad-annotation.rs:40:41
| |
LL | #[rustc_on_unimplemented(message = "x", message = "y")] LL | #[rustc_on_unimplemented(message = "x", message = "y")]
| ------------- ^^^^^^^^^^^^^ `message` is later redundantly declared here | ------------- ^^^^^^^^^^^^^ `message` is later redundantly declared here
@@ -120,7 +120,7 @@ LL | #[rustc_on_unimplemented(message = "x", message = "y")]
| `message` is first declared here | `message` is first declared here
warning: malformed `rustc_on_unimplemented` attribute warning: malformed `rustc_on_unimplemented` attribute
--> $DIR/bad-annotation.rs:55:26 --> $DIR/bad-annotation.rs:56:26
| |
LL | #[rustc_on_unimplemented(on = "x", message = "y")] LL | #[rustc_on_unimplemented(on = "x", message = "y")]
| ^^^^^^^^ invalid option found here | ^^^^^^^^ invalid option found here
@@ -128,7 +128,7 @@ LL | #[rustc_on_unimplemented(on = "x", message = "y")]
= help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented> = help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented>
warning: malformed `rustc_on_unimplemented` attribute warning: malformed `rustc_on_unimplemented` attribute
--> $DIR/bad-annotation.rs:60:26 --> $DIR/bad-annotation.rs:61:26
| |
LL | #[rustc_on_unimplemented(on(Self = "y"), message = "y")] LL | #[rustc_on_unimplemented(on(Self = "y"), message = "y")]
| ^^^^^^^^^^^^^^ invalid option found here | ^^^^^^^^^^^^^^ invalid option found here
@@ -136,7 +136,7 @@ LL | #[rustc_on_unimplemented(on(Self = "y"), message = "y")]
= help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented> = help: see <https://rustc-dev-guide.rust-lang.org/diagnostics.html#rustc_on_unimplemented>
warning: malformed `rustc_on_unimplemented` attribute warning: malformed `rustc_on_unimplemented` attribute
--> $DIR/bad-annotation.rs:65:46 --> $DIR/bad-annotation.rs:66:46
| |
LL | #[rustc_on_unimplemented(on(from_desugaring, on(from_desugaring, message = "x")), message = "y")] LL | #[rustc_on_unimplemented(on(from_desugaring, on(from_desugaring, message = "x")), message = "y")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here