From c2916be8d78ae46a29b56806a55fdf0a14f4cee9 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 23 Apr 2026 21:59:41 +0200 Subject: [PATCH] Permit `{This}` in diagnostic attribute format literals --- .../src/attributes/diagnostic/mod.rs | 126 ++++++++++++------ compiler/rustc_attr_parsing/src/errors.rs | 48 ++++--- compiler/rustc_hir/src/lints.rs | 2 +- compiler/rustc_lint_defs/src/lib.rs | 7 - compiler/rustc_passes/src/check_attr.rs | 18 +-- compiler/rustc_passes/src/errors.rs | 7 - compiler/rustc_resolve/src/imports.rs | 9 +- .../traits/on_unimplemented.rs | 1 - .../diagnostic_namespace/multiline_spans.rs | 8 +- .../multiline_spans.stderr | 24 ++-- .../on_move/on_move_with_format.rs | 5 + .../on_move/on_move_with_format.stderr | 15 ++- .../on_unimplemented/broken_format.rs | 12 +- .../on_unimplemented/broken_format.stderr | 36 ++--- .../on_unknown/incorrect_format_string.rs | 19 +-- .../on_unknown/incorrect_format_string.stderr | 72 ++++++---- .../on_unknown/this_format_argument.rs | 45 +++++++ .../on_unknown/this_format_argument.stderr | 60 +++++++++ .../on_unknown/unknown_import.rs | 2 +- .../report_warning_on_invalid_formats.rs | 5 +- .../report_warning_on_invalid_formats.stderr | 6 +- tests/ui/on-unimplemented/bad-annotation.rs | 3 +- .../ui/on-unimplemented/bad-annotation.stderr | 42 +++--- 23 files changed, 368 insertions(+), 204 deletions(-) create mode 100644 tests/ui/diagnostic_namespace/on_unknown/this_format_argument.rs create mode 100644 tests/ui/diagnostic_namespace/on_unknown/this_format_argument.stderr diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs index 53491a0a959a..ee99e2904c80 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs @@ -6,7 +6,6 @@ Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, NameValue, OnUnimplementedCondition, Piece, Predicate, }; -use rustc_hir::lints::FormatWarning; use rustc_macros::Diagnostic; use rustc_parse_format::{ Argument, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, Position, @@ -19,9 +18,8 @@ use crate::context::{AcceptContext, Stage}; use crate::errors::{ - DisallowedPlaceholder, DisallowedPositionalArgument, IgnoredDiagnosticOption, - InvalidFormatSpecifier, MalFormedDiagnosticAttributeLint, MissingOptionsForDiagnosticAttribute, - NonMetaItemDiagnosticAttribute, WrappedParserError, + FormatWarning, IgnoredDiagnosticOption, MalFormedDiagnosticAttributeLint, + MissingOptionsForDiagnosticAttribute, NonMetaItemDiagnosticAttribute, WrappedParserError, }; use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser}; @@ -88,6 +86,29 @@ fn allowed_options(&self) -> &'static str { Self::DiagnosticOnUnmatchArgs => DEFAULT, } } + + fn allowed_format_arguments(&self) -> &'static str { + match self { + Self::RustcOnUnimplemented => { + "see 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( @@ -257,22 +278,13 @@ fn parse_directive_items<'p, S: Stage>( match parse_format_string(input.name, snippet, input.span, mode) { Ok((f, warnings)) => { for warning in warnings { - let (FormatWarning::InvalidSpecifier { span, .. } - | FormatWarning::PositionalArgument { span, .. } - | FormatWarning::DisallowedPlaceholder { span }) = warning; + let (FormatWarning::InvalidSpecifier { span } + | FormatWarning::PositionalArgument { span } + | FormatWarning::IndexedArgument { span } + | FormatWarning::DisallowedPlaceholder { span, .. }) = warning; cx.emit_dyn_lint( MALFORMED_DIAGNOSTIC_FORMAT_LITERALS, - move |dcx, level| match warning { - FormatWarning::PositionalArgument { .. } => { - DisallowedPositionalArgument.into_diag(dcx, level) - } - FormatWarning::InvalidSpecifier { .. } => { - InvalidFormatSpecifier.into_diag(dcx, level) - } - FormatWarning::DisallowedPlaceholder { .. } => { - DisallowedPlaceholder.into_diag(dcx, level) - } - }, + move |dcx, level| warning.into_diag(dcx, level), span, ); } @@ -422,38 +434,74 @@ fn parse_arg( is_source_literal: bool, ) -> FormatArg { 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 { // Something like "hello {name}" Position::ArgumentNamed(name) => match (mode, Symbol::intern(name)) { - // Only `#[rustc_on_unimplemented]` can use these - (Mode::RustcOnUnimplemented { .. }, sym::ItemContext) => FormatArg::ItemContext, - (Mode::RustcOnUnimplemented { .. } | Mode::DiagnosticOnUnmatchArgs, sym::This) => { - FormatArg::This + (Mode::RustcOnUnimplemented, sym::ItemContext) => FormatArg::ItemContext, + + // Like `{This}`, but sugared. + // 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 Position::ArgumentIs(idx) => { - warnings.push(FormatWarning::PositionalArgument { - span, - help: format!("use `{{{idx}}}` to print a number in braces"), - }); + warnings.push(FormatWarning::IndexedArgument { span }); FormatArg::AsIs(Symbol::intern(&format!("{{{idx}}}"))) } Position::ArgumentImplicitlyIs(_) => { - warnings.push(FormatWarning::PositionalArgument { - span, - help: String::from("use `{{}}` to print empty braces"), - }); + warnings.push(FormatWarning::PositionalArgument { span }); FormatArg::AsIs(sym::empty_braces) } } @@ -473,7 +521,7 @@ fn warn_on_format_spec( .as_ref() .map(|inner| slice_span(input_span, inner.clone(), is_source_literal)) .unwrap_or(input_span); - warnings.push(FormatWarning::InvalidSpecifier { span, name: spec.ty.into() }) + warnings.push(FormatWarning::InvalidSpecifier { span }) } } diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index 95d0e82f472c..e35f73de35ec 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -357,23 +357,6 @@ pub(crate) struct MalFormedDiagnosticAttributeLint { 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)] #[diag("{$description}")] 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" )] 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, + }, +} diff --git a/compiler/rustc_hir/src/lints.rs b/compiler/rustc_hir/src/lints.rs index d7bd9f874dd2..cdafca37a504 100644 --- a/compiler/rustc_hir/src/lints.rs +++ b/compiler/rustc_hir/src/lints.rs @@ -1,8 +1,8 @@ use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_error_messages::MultiSpan; use rustc_errors::{Diag, DiagCtxtHandle, Level}; +pub use rustc_lint_defs::AttributeLintKind; use rustc_lint_defs::LintId; -pub use rustc_lint_defs::{AttributeLintKind, FormatWarning}; use crate::HirId; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 0a9c0669a5bd..8cbd2456fccd 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -658,13 +658,6 @@ pub enum AttributeLintKind { 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; /// Declares a static item of type `&'static Lint`. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d11825016baf..ebf0f06f7173 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -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::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 , .. }) => { self.check_diagnostic_on_move(hir_id, directive.as_deref()) }, @@ -256,6 +253,7 @@ fn check_attributes( | AttributeKind::NoMangle(..) | AttributeKind::NoStd { .. } | AttributeKind::OnUnknown { .. } + | AttributeKind::OnUnmatchArgs { .. } | AttributeKind::Optimize(..) | AttributeKind::PanicRuntime | AttributeKind::PatchableFunctionEntry { .. } @@ -562,20 +560,6 @@ fn check_diagnostic_on_const( // ...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]` fn check_diagnostic_on_move(&self, hir_id: HirId, directive: Option<&Directive>) { if let Some(directive) = directive { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 5300267573e6..a916b4670fde 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1303,10 +1303,3 @@ pub(crate) struct UnknownFormatParameterForOnUnimplementedAttr { pub(crate) struct OnMoveMalformedFormatLiterals { 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, -} diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 4cb9a653e010..d8ab279ef7a9 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -2,6 +2,7 @@ use std::mem; +use itertools::Itertools; use rustc_ast::{Item, NodeId}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; @@ -879,8 +880,14 @@ fn throw_unresolved_import_error( let (message, label, notes) = // 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) { + let this = errors.iter().map(|(_import, err)| { + + // Is this unwrap_or reachable? + err.segment.unwrap_or(kw::Underscore) + }).join(", "); + let args = FormatArgs { - this: paths.join(", "), + this, // Unused this_sugared: String::new(), // Unused diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index b6ea4ddc6324..a65e612b93e9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -4,7 +4,6 @@ use rustc_hir::attrs::diagnostic::{ConditionOptions, CustomDiagnostic, FormatArgs}; use rustc_hir::def_id::LocalDefId; use rustc_hir::find_attr; -pub use rustc_hir::lints::FormatWarning; use rustc_middle::ty::print::PrintTraitRefExt; use rustc_middle::ty::{self, GenericParamDef, GenericParamDefKind}; use rustc_span::Symbol; diff --git a/tests/ui/diagnostic_namespace/multiline_spans.rs b/tests/ui/diagnostic_namespace/multiline_spans.rs index e0876b19df07..09aba104806f 100644 --- a/tests/ui/diagnostic_namespace/multiline_spans.rs +++ b/tests/ui/diagnostic_namespace/multiline_spans.rs @@ -31,17 +31,17 @@ pub trait MultiLine4 {} #[diagnostic::on_unimplemented(message = "here is a big \ 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 MultiLineFmt {} #[diagnostic::on_unimplemented(message = "here is a big \ 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 {} #[diagnostic::on_unimplemented(message = "here is a big \ 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 {} @@ -51,5 +51,5 @@ pub trait MultiLineFmt3 {} \ \ 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 {} diff --git a/tests/ui/diagnostic_namespace/multiline_spans.stderr b/tests/ui/diagnostic_namespace/multiline_spans.stderr index 0e4bb864b965..e5cfcfd18394 100644 --- a/tests/ui/diagnostic_namespace/multiline_spans.stderr +++ b/tests/ui/diagnostic_namespace/multiline_spans.stderr @@ -36,37 +36,29 @@ LL | multiline string {unknown}")] | = 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 | LL | ... {Self:+}")] - | ^^ - | - = help: no format specifier are supported in this position + | ^^ remove this format specifier -error: invalid format specifier +error: format specifiers are not permitted in diagnostic attributes --> $DIR/multiline_spans.rs:38:64 | LL | ... multiline string {Self:X}")] - | ^^ - | - = help: no format specifier are supported in this position + | ^^ remove this format specifier -error: invalid format specifier +error: format specifiers are not permitted in diagnostic attributes --> $DIR/multiline_spans.rs:43:27 | LL | multiline string {Self:#}")] - | ^^ - | - = help: no format specifier are supported in this position + | ^^ remove this format specifier -error: invalid format specifier +error: format specifiers are not permitted in diagnostic attributes --> $DIR/multiline_spans.rs:53:27 | LL | multiline string {Self:?}")] - | ^^ - | - = help: no format specifier are supported in this position + | ^^ remove this format specifier error: aborting due to 8 previous errors diff --git a/tests/ui/diagnostic_namespace/on_move/on_move_with_format.rs b/tests/ui/diagnostic_namespace/on_move/on_move_with_format.rs index f2025c2b2271..54035d1d0ea6 100644 --- a/tests/ui/diagnostic_namespace/on_move/on_move_with_format.rs +++ b/tests/ui/diagnostic_namespace/on_move/on_move_with_format.rs @@ -1,3 +1,4 @@ +//@ dont-require-annotations: NOTE #![feature(diagnostic_on_move)] #[diagnostic::on_move( @@ -10,6 +11,7 @@ #[diagnostic::on_move( message="Foo for {X}", label="Bar for {X}", + note = "This is `{This}`", )] struct MyType { _x: X, @@ -21,12 +23,15 @@ fn takes_mytype(_: MyType) {} fn main() { let foo = Foo; + //~^ NOTE Bar for Foo takes_foo(foo); let bar = foo; //~^ERROR Foo for Foo let mytype = MyType { _x: 0 }; + //~^ NOTE Bar for i32 takes_mytype(mytype); let baz = mytype; //~^ERROR Foo for i32 + //~|NOTE This is `MyType` } diff --git a/tests/ui/diagnostic_namespace/on_move/on_move_with_format.stderr b/tests/ui/diagnostic_namespace/on_move/on_move_with_format.stderr index 6868f1571be8..821a502dbcd6 100644 --- a/tests/ui/diagnostic_namespace/on_move/on_move_with_format.stderr +++ b/tests/ui/diagnostic_namespace/on_move/on_move_with_format.stderr @@ -1,22 +1,23 @@ 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; | --- Bar for Foo +LL | LL | takes_foo(foo); | --- value moved here LL | let bar = foo; | ^^^ 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 - --> $DIR/on_move_with_format.rs:18:17 + --> $DIR/on_move_with_format.rs:20:17 | LL | fn takes_foo(_: Foo) {} | --------- ^^^ this parameter takes ownership of the value | | | in this function 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; | ^^^^^^^^^^ consider implementing `Clone` for this type @@ -25,24 +26,26 @@ LL | takes_foo(foo); | --- you could clone this value 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 }; | ------ Bar for i32 +LL | LL | takes_mytype(mytype); | ------ value moved here LL | let baz = mytype; | ^^^^^^ 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 - --> $DIR/on_move_with_format.rs:20:23 + --> $DIR/on_move_with_format.rs:22:23 | LL | fn takes_mytype(_: MyType) {} | ------------ ^^^^^^^^^ this parameter takes ownership of the value | | | in this function note: if `MyType` 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 { | ^^^^^^^^^^^^^^^^ consider implementing `Clone` for this type diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs index 56255a25b3f3..640115765fd6 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs +++ b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.rs @@ -4,24 +4,24 @@ trait ImportantTrait1 {} #[diagnostic::on_unimplemented(message = "Test {}")] -//~^WARN positional format arguments are not allowed here +//~^WARN positional arguments are not permitted in diagnostic attributes trait ImportantTrait2 {} #[diagnostic::on_unimplemented(message = "Test {1:}")] -//~^WARN positional format arguments are not allowed here -//~|WARN invalid format specifier [malformed_diagnostic_format_literals] +//~^WARN indexed format arguments are not permitted in diagnostic attributes +//~|WARN format specifiers are not permitted in diagnostic attributes [malformed_diagnostic_format_literals] trait ImportantTrait3 {} #[diagnostic::on_unimplemented(message = "Test {Self:123}")] -//~^WARN invalid format specifier +//~^WARN format specifiers are not permitted in diagnostic attributes trait ImportantTrait4 {} #[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 {} #[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 {} diff --git a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr index a6ab2f245a3e..983f871dde10 100644 --- a/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr +++ b/tests/ui/diagnostic_namespace/on_unimplemented/broken_format.stderr @@ -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 -warning: positional format arguments are not allowed here +warning: positional arguments are not permitted in diagnostic attributes --> $DIR/broken_format.rs:6:49 | 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 | LL | #[diagnostic::on_unimplemented(message = "Test {1:}")] - | ^ - | - = help: no format specifier are supported in this position + | ^ remove this format specifier -warning: positional format arguments are not allowed here +warning: indexed format arguments are not permitted in diagnostic attributes --> $DIR/broken_format.rs:10:49 | LL | #[diagnostic::on_unimplemented(message = "Test {1:}")] - | ^ - | - = help: only named format arguments with the name of one of the generic types are allowed in this context + | ^ remove this format argument -warning: invalid format specifier +warning: format specifiers are not permitted in diagnostic attributes --> $DIR/broken_format.rs:15:53 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:123}")] - | ^^^^ - | - = help: no format specifier are supported in this position + | ^^^^ remove this format specifier -warning: invalid format specifier +warning: format specifiers are not permitted in diagnostic attributes --> $DIR/broken_format.rs:19:53 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:!}")] - | ^^ - | - = help: no format specifier are supported in this position + | ^^ remove this format specifier -warning: invalid format specifier +warning: format specifiers are not permitted in diagnostic attributes --> $DIR/broken_format.rs:23:53 | LL | #[diagnostic::on_unimplemented(message = "Test {Self:}")] - | ^ - | - = help: no format specifier are supported in this position + | ^ remove this format specifier error[E0277]: {{Test } thing --> $DIR/broken_format.rs:36:13 diff --git a/tests/ui/diagnostic_namespace/on_unknown/incorrect_format_string.rs b/tests/ui/diagnostic_namespace/on_unknown/incorrect_format_string.rs index cdf0f1e89efc..82fcf11712db 100644 --- a/tests/ui/diagnostic_namespace/on_unknown/incorrect_format_string.rs +++ b/tests/ui/diagnostic_namespace/on_unknown/incorrect_format_string.rs @@ -1,32 +1,35 @@ #![feature(diagnostic_on_unknown)] #[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; //~^ ERROR: foo {} #[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; -//~^ ERROR: foo {} +//~^ ERROR: foo {A} #[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; //~^ ERROR: unresolved import `std::does_not_exist3` #[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; //~^ ERROR: unresolved import `std::does_not_exist4` #[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; //~^ ERROR: unresolved import `std::does_not_exist5` -#[diagnostic::on_unknown(note = "foo {A}")] -//~^ WARN: format arguments are not allowed here +#[diagnostic::on_unknown(note = "foo {Self} {ItemContext} {Trait} {A}")] +//~^ 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; //~^ ERROR: unresolved import `std::does_not_exist6` diff --git a/tests/ui/diagnostic_namespace/on_unknown/incorrect_format_string.stderr b/tests/ui/diagnostic_namespace/on_unknown/incorrect_format_string.stderr index 2b942338ffb4..9c2d5b0269f8 100644 --- a/tests/ui/diagnostic_namespace/on_unknown/incorrect_format_string.stderr +++ b/tests/ui/diagnostic_namespace/on_unknown/incorrect_format_string.stderr @@ -6,7 +6,7 @@ LL | use 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 | 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 | LL | use std::does_not_exist4; - | ^^^^^^^^^^^^^^^^^^^^ foo {} + | ^^^^^^^^^^^^^^^^^^^^ foo {A} error[E0432]: unresolved import `std::does_not_exist5` --> $DIR/incorrect_format_string.rs:25:5 @@ -35,62 +35,86 @@ LL | use std::does_not_exist5; = note: foo {} 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; | ^^^^^^^^^^^^^^^^^^^^ 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 | 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 -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 | 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 | 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 | 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 | 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 | -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`. diff --git a/tests/ui/diagnostic_namespace/on_unknown/this_format_argument.rs b/tests/ui/diagnostic_namespace/on_unknown/this_format_argument.rs new file mode 100644 index 000000000000..80ab7b973e8c --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unknown/this_format_argument.rs @@ -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` diff --git a/tests/ui/diagnostic_namespace/on_unknown/this_format_argument.stderr b/tests/ui/diagnostic_namespace/on_unknown/this_format_argument.stderr new file mode 100644 index 000000000000..aa6fd49d21c4 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_unknown/this_format_argument.stderr @@ -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`. diff --git a/tests/ui/diagnostic_namespace/on_unknown/unknown_import.rs b/tests/ui/diagnostic_namespace/on_unknown/unknown_import.rs index f2b0f059bb0a..d09a87dcfea1 100644 --- a/tests/ui/diagnostic_namespace/on_unknown/unknown_import.rs +++ b/tests/ui/diagnostic_namespace/on_unknown/unknown_import.rs @@ -7,7 +7,7 @@ pub mod foo { message = "first message", label = "first label", note = "custom note", - note = "custom note 2" + note = "custom note 2", )] use foo::Foo; //~^ERROR first message diff --git a/tests/ui/diagnostic_namespace/on_unmatch_args/report_warning_on_invalid_formats.rs b/tests/ui/diagnostic_namespace/on_unmatch_args/report_warning_on_invalid_formats.rs index 65cf18168638..1fcaca8300f8 100644 --- a/tests/ui/diagnostic_namespace/on_unmatch_args/report_warning_on_invalid_formats.rs +++ b/tests/ui/diagnostic_namespace/on_unmatch_args/report_warning_on_invalid_formats.rs @@ -3,7 +3,10 @@ #[diagnostic::on_unmatch_args( 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 { ($ty:ty, $value:expr) => {}; diff --git a/tests/ui/diagnostic_namespace/on_unmatch_args/report_warning_on_invalid_formats.stderr b/tests/ui/diagnostic_namespace/on_unmatch_args/report_warning_on_invalid_formats.stderr index 2f631337c441..fd68ad5570f3 100644 --- a/tests/ui/diagnostic_namespace/on_unmatch_args/report_warning_on_invalid_formats.stderr +++ b/tests/ui/diagnostic_namespace/on_unmatch_args/report_warning_on_invalid_formats.stderr @@ -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 | 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 warning: 1 warning emitted diff --git a/tests/ui/on-unimplemented/bad-annotation.rs b/tests/ui/on-unimplemented/bad-annotation.rs index 5350bf91de94..7fec70df3a73 100644 --- a/tests/ui/on-unimplemented/bad-annotation.rs +++ b/tests/ui/on-unimplemented/bad-annotation.rs @@ -23,7 +23,8 @@ trait NoContent {} trait ParameterNotPresent {} #[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 {} #[rustc_on_unimplemented(lorem = "")] diff --git a/tests/ui/on-unimplemented/bad-annotation.stderr b/tests/ui/on-unimplemented/bad-annotation.stderr index 058014fd4e08..88666f359719 100644 --- a/tests/ui/on-unimplemented/bad-annotation.stderr +++ b/tests/ui/on-unimplemented/bad-annotation.stderr @@ -1,59 +1,59 @@ 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"))] | ^^^^^^^^^ expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `desugared` 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")] | ^^^^ empty `on`-clause here 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"))] | ^^^ unexpected literal here 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"))] | ^^ unexpected literal here 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"))] | ^^^^^^ unexpected quantity of predicates here 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"))] | ^^ unexpected quantity of predicates here 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"))] | ^^^^^^^^^^^ expected an identifier here, not `thing::What` 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"))] | ^^^^^^^^^^^ expected an identifier here, not `thing::What` 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"))] | ^^^^^^^^^^^^^^ expected one of `any`, `all` or `not` here, not `aaaaaaaaaaaaaa` 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"))] | ^^^^^^^^^ 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 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"))] | ^^^^^^^^^^^ 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"))] | ^^^^^^^^^ @@ -87,16 +87,16 @@ LL | #[rustc_on_unimplemented] = help: see = 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 | 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 - --> $DIR/bad-annotation.rs:29:26 + --> $DIR/bad-annotation.rs:30:26 | LL | #[rustc_on_unimplemented(lorem = "")] | ^^^^^^^^^^ invalid option found here @@ -104,7 +104,7 @@ LL | #[rustc_on_unimplemented(lorem = "")] = help: see 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)))] | ^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -112,7 +112,7 @@ LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))] = help: see 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")] | ------------- ^^^^^^^^^^^^^ `message` is later redundantly declared here @@ -120,7 +120,7 @@ LL | #[rustc_on_unimplemented(message = "x", message = "y")] | `message` is first declared here 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")] | ^^^^^^^^ invalid option found here @@ -128,7 +128,7 @@ LL | #[rustc_on_unimplemented(on = "x", message = "y")] = help: see 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")] | ^^^^^^^^^^^^^^ invalid option found here @@ -136,7 +136,7 @@ LL | #[rustc_on_unimplemented(on(Self = "y"), message = "y")] = help: see 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")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here