do away with _Self and TraitName and check generic params for rustc_on_unimplemented

This commit is contained in:
mejrs
2025-05-17 15:15:53 +02:00
parent c9b6ccc11c
commit 9ffd0bf75a
14 changed files with 152 additions and 138 deletions

View File

@@ -398,7 +398,6 @@ symbols! {
Wrapping, Wrapping,
Yield, Yield,
_DECLS, _DECLS,
_Self,
__D, __D,
__H, __H,
__S, __S,

View File

@@ -337,6 +337,8 @@ trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not = expected
.label = unexpected quantity of predicates here .label = unexpected quantity of predicates here
trait_selection_rustc_on_unimplemented_invalid_flag = invalid flag in `on`-clause trait_selection_rustc_on_unimplemented_invalid_flag = invalid flag in `on`-clause
.label = expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}` .label = expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`
trait_selection_rustc_on_unimplemented_invalid_name = invalid name in `on`-clause
.label = expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}`
trait_selection_rustc_on_unimplemented_invalid_predicate = this predicate is invalid trait_selection_rustc_on_unimplemented_invalid_predicate = this predicate is invalid
.label = expected one of `any`, `all` or `not` here, not `{$invalid_pred}` .label = expected one of `any`, `all` or `not` here, not `{$invalid_pred}`
trait_selection_rustc_on_unimplemented_missing_value = this attribute must have a value trait_selection_rustc_on_unimplemented_missing_value = this attribute must have a value

View File

@@ -429,7 +429,19 @@ impl<'tcx> OnUnimplementedDirective {
.next() .next()
.ok_or_else(|| tcx.dcx().emit_err(InvalidOnClause::Empty { span }))?; .ok_or_else(|| tcx.dcx().emit_err(InvalidOnClause::Empty { span }))?;
match OnUnimplementedCondition::parse(cond) { let generics: Vec<Symbol> = tcx
.generics_of(item_def_id)
.own_params
.iter()
.filter_map(|param| {
if matches!(param.kind, GenericParamDefKind::Lifetime) {
None
} else {
Some(param.name)
}
})
.collect();
match OnUnimplementedCondition::parse(cond, &generics) {
Ok(condition) => Some(condition), Ok(condition) => Some(condition),
Err(e) => return Err(tcx.dcx().emit_err(e)), Err(e) => return Err(tcx.dcx().emit_err(e)),
} }

View File

@@ -26,9 +26,12 @@ impl OnUnimplementedCondition {
}) })
} }
pub(crate) fn parse(input: &MetaItemInner) -> Result<Self, InvalidOnClause> { pub(crate) fn parse(
input: &MetaItemInner,
generics: &[Symbol],
) -> Result<Self, InvalidOnClause> {
let span = input.span(); let span = input.span();
let pred = Predicate::parse(input)?; let pred = Predicate::parse(input, generics)?;
Ok(OnUnimplementedCondition { span, pred }) Ok(OnUnimplementedCondition { span, pred })
} }
} }
@@ -52,7 +55,7 @@ enum Predicate {
} }
impl Predicate { impl Predicate {
fn parse(input: &MetaItemInner) -> Result<Self, InvalidOnClause> { fn parse(input: &MetaItemInner, generics: &[Symbol]) -> Result<Self, InvalidOnClause> {
let meta_item = match input { let meta_item = match input {
MetaItemInner::MetaItem(meta_item) => meta_item, MetaItemInner::MetaItem(meta_item) => meta_item,
MetaItemInner::Lit(lit) => { MetaItemInner::Lit(lit) => {
@@ -69,10 +72,10 @@ impl Predicate {
match meta_item.kind { match meta_item.kind {
MetaItemKind::List(ref mis) => match predicate.name { MetaItemKind::List(ref mis) => match predicate.name {
sym::any => Ok(Predicate::Any(Predicate::parse_sequence(mis)?)), sym::any => Ok(Predicate::Any(Predicate::parse_sequence(mis, generics)?)),
sym::all => Ok(Predicate::All(Predicate::parse_sequence(mis)?)), sym::all => Ok(Predicate::All(Predicate::parse_sequence(mis, generics)?)),
sym::not => match &**mis { sym::not => match &**mis {
[one] => Ok(Predicate::Not(Box::new(Predicate::parse(one)?))), [one] => Ok(Predicate::Not(Box::new(Predicate::parse(one, generics)?))),
[first, .., last] => Err(InvalidOnClause::ExpectedOnePredInNot { [first, .., last] => Err(InvalidOnClause::ExpectedOnePredInNot {
span: first.span().to(last.span()), span: first.span().to(last.span()),
}), }),
@@ -83,7 +86,7 @@ impl Predicate {
} }
}, },
MetaItemKind::NameValue(MetaItemLit { symbol, .. }) => { MetaItemKind::NameValue(MetaItemLit { symbol, .. }) => {
let name = Name::parse(predicate); let name = Name::parse(predicate, generics)?;
let value = FilterFormatString::parse(symbol); let value = FilterFormatString::parse(symbol);
let kv = NameValue { name, value }; let kv = NameValue { name, value };
Ok(Predicate::Match(kv)) Ok(Predicate::Match(kv))
@@ -95,8 +98,11 @@ impl Predicate {
} }
} }
fn parse_sequence(sequence: &[MetaItemInner]) -> Result<Vec<Self>, InvalidOnClause> { fn parse_sequence(
sequence.iter().map(Predicate::parse).collect() sequence: &[MetaItemInner],
generics: &[Symbol],
) -> Result<Vec<Self>, InvalidOnClause> {
sequence.iter().map(|item| Predicate::parse(item, generics)).collect()
} }
fn eval(&self, eval: &mut impl FnMut(FlagOrNv<'_>) -> bool) -> bool { fn eval(&self, eval: &mut impl FnMut(FlagOrNv<'_>) -> bool) -> bool {
@@ -156,14 +162,13 @@ enum Name {
} }
impl Name { impl Name {
fn parse(Ident { name, .. }: Ident) -> Self { fn parse(Ident { name, span }: Ident, generics: &[Symbol]) -> Result<Self, InvalidOnClause> {
match name { match name {
sym::_Self | kw::SelfUpper => Name::SelfUpper, kw::SelfUpper => Ok(Name::SelfUpper),
sym::from_desugaring => Name::FromDesugaring, sym::from_desugaring => Ok(Name::FromDesugaring),
sym::cause => Name::Cause, sym::cause => Ok(Name::Cause),
// FIXME(mejrs) Perhaps we should start checking that generic if generics.contains(&generic) => Ok(Name::GenericArg(generic)),
// this actually is a valid generic parameter? invalid_name => Err(InvalidOnClause::InvalidName { invalid_name, span }),
generic => Name::GenericArg(generic),
} }
} }
} }

View File

@@ -2,8 +2,8 @@ use std::fmt;
use std::ops::Range; use std::ops::Range;
use errors::*; use errors::*;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::print::TraitRefPrintSugared; use rustc_middle::ty::print::TraitRefPrintSugared;
use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
use rustc_parse_format::{ use rustc_parse_format::{
Alignment, Argument, Count, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, Alignment, Argument, Count, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece,
Position, Position,
@@ -232,48 +232,16 @@ fn parse_arg<'tcx>(
) -> FormatArg { ) -> FormatArg {
let (Ctx::RustcOnUnimplemented { tcx, trait_def_id } let (Ctx::RustcOnUnimplemented { tcx, trait_def_id }
| Ctx::DiagnosticOnUnimplemented { tcx, trait_def_id }) = ctx; | Ctx::DiagnosticOnUnimplemented { tcx, trait_def_id }) = ctx;
let trait_name = tcx.item_ident(*trait_def_id);
let generics = tcx.generics_of(trait_def_id);
let span = slice_span(input_span, arg.position_span.clone()); let span = slice_span(input_span, arg.position_span.clone());
match arg.position { match arg.position {
// Something like "hello {name}" // Something like "hello {name}"
Position::ArgumentNamed(name) => match (ctx, Symbol::intern(name)) { Position::ArgumentNamed(name) => match (ctx, Symbol::intern(name)) {
// accepted, but deprecated
(Ctx::RustcOnUnimplemented { .. }, sym::_Self) => {
warnings
.push(FormatWarning::FutureIncompat { span, help: String::from("use {Self}") });
FormatArg::SelfUpper
}
(
Ctx::RustcOnUnimplemented { .. },
sym::from_desugaring
| sym::crate_local
| sym::direct
| sym::cause
| sym::float
| sym::integer_
| sym::integral,
) => {
warnings.push(FormatWarning::FutureIncompat {
span,
help: String::from("don't use this in a format string"),
});
FormatArg::AsIs(String::new())
}
// Only `#[rustc_on_unimplemented]` can use these // Only `#[rustc_on_unimplemented]` can use these
(Ctx::RustcOnUnimplemented { .. }, sym::ItemContext) => FormatArg::ItemContext, (Ctx::RustcOnUnimplemented { .. }, sym::ItemContext) => FormatArg::ItemContext,
(Ctx::RustcOnUnimplemented { .. }, sym::This) => FormatArg::This, (Ctx::RustcOnUnimplemented { .. }, sym::This) => FormatArg::This,
(Ctx::RustcOnUnimplemented { .. }, sym::Trait) => FormatArg::Trait, (Ctx::RustcOnUnimplemented { .. }, sym::Trait) => FormatArg::Trait,
// `{ThisTraitsName}`. Some attrs in std use this, but I'd like to change it to the more general `{This}`
// because that'll be simpler to parse and extend in the future
(Ctx::RustcOnUnimplemented { .. }, name) if name == trait_name.name => {
warnings
.push(FormatWarning::FutureIncompat { span, help: String::from("use {This}") });
FormatArg::This
}
// Any attribute can use these // Any attribute can use these
( (
Ctx::RustcOnUnimplemented { .. } | Ctx::DiagnosticOnUnimplemented { .. }, Ctx::RustcOnUnimplemented { .. } | Ctx::DiagnosticOnUnimplemented { .. },
@@ -282,7 +250,10 @@ fn parse_arg<'tcx>(
( (
Ctx::RustcOnUnimplemented { .. } | Ctx::DiagnosticOnUnimplemented { .. }, Ctx::RustcOnUnimplemented { .. } | Ctx::DiagnosticOnUnimplemented { .. },
generic_param, generic_param,
) if generics.own_params.iter().any(|param| param.name == generic_param) => { ) if tcx.generics_of(trait_def_id).own_params.iter().any(|param| {
!matches!(param.kind, GenericParamDefKind::Lifetime) && param.name == generic_param
}) =>
{
FormatArg::GenericParam { generic_param } FormatArg::GenericParam { generic_param }
} }
@@ -375,39 +346,4 @@ pub mod errors {
#[diag(trait_selection_missing_options_for_on_unimplemented_attr)] #[diag(trait_selection_missing_options_for_on_unimplemented_attr)]
#[help] #[help]
pub struct MissingOptionsForOnUnimplementedAttr; pub struct MissingOptionsForOnUnimplementedAttr;
#[derive(LintDiagnostic)]
#[diag(trait_selection_ignored_diagnostic_option)]
pub struct IgnoredDiagnosticOption {
pub option_name: &'static str,
#[label]
pub span: Span,
#[label(trait_selection_other_label)]
pub prev_span: Span,
}
impl IgnoredDiagnosticOption {
pub fn maybe_emit_warning<'tcx>(
tcx: TyCtxt<'tcx>,
item_def_id: DefId,
new: Option<Span>,
old: Option<Span>,
option_name: &'static str,
) {
if let (Some(new_item), Some(old_item)) = (new, old) {
if let Some(item_def_id) = item_def_id.as_local() {
tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
tcx.local_def_id_to_hir_id(item_def_id),
new_item,
IgnoredDiagnosticOption {
span: new_item,
prev_span: old_item,
option_name,
},
);
}
}
}
}
} }

View File

@@ -72,6 +72,13 @@ pub enum InvalidOnClause {
span: Span, span: Span,
invalid_flag: Symbol, invalid_flag: Symbol,
}, },
#[diag(trait_selection_rustc_on_unimplemented_invalid_name, code = E0232)]
InvalidName {
#[primary_span]
#[label]
span: Span,
invalid_name: Symbol,
},
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]

View File

@@ -21,7 +21,7 @@ fn foo() {}
fn bar() {} fn bar() {}
// No warning: // No warning:
#[rustc_on_unimplemented(on(_Self = "&str", label = "`a"), on(_Self = "alloc::string::String", label = "a"))] #[rustc_on_unimplemented(on(Self = "&str", label = "`a"), on(Self = "alloc::string::String", label = "a"))]
trait Abc {} trait Abc {}
#[proc_macro_attr::duplicated_attr()] // Should not warn! #[proc_macro_attr::duplicated_attr()] // Should not warn!

View File

@@ -3,7 +3,7 @@
//@ reference: attributes.diagnostic.on_unimplemented.syntax //@ reference: attributes.diagnostic.on_unimplemented.syntax
//@ reference: attributes.diagnostic.on_unimplemented.invalid-formats //@ reference: attributes.diagnostic.on_unimplemented.invalid-formats
#[diagnostic::on_unimplemented( #[diagnostic::on_unimplemented(
on(_Self = "&str"), on(Self = "&str"),
//~^WARN malformed `on_unimplemented` attribute //~^WARN malformed `on_unimplemented` attribute
//~|WARN malformed `on_unimplemented` attribute //~|WARN malformed `on_unimplemented` attribute
message = "trait has `{Self}` and `{T}` as params", message = "trait has `{Self}` and `{T}` as params",
@@ -41,7 +41,7 @@ impl Bar for i32 {}
//~|WARN there is no parameter `integral` on trait `Baz` //~|WARN there is no parameter `integral` on trait `Baz`
//~|WARN there is no parameter `integer` on trait `Baz` //~|WARN there is no parameter `integer` on trait `Baz`
//~|WARN there is no parameter `integer` on trait `Baz` //~|WARN there is no parameter `integer` on trait `Baz`
label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
//~^WARN there is no parameter `float` on trait `Baz` //~^WARN there is no parameter `float` on trait `Baz`
//~|WARN there is no parameter `float` on trait `Baz` //~|WARN there is no parameter `float` on trait `Baz`
//~|WARN there is no parameter `_Self` on trait `Baz` //~|WARN there is no parameter `_Self` on trait `Baz`
@@ -52,6 +52,8 @@ impl Bar for i32 {}
//~|WARN there is no parameter `Trait` on trait `Baz` //~|WARN there is no parameter `Trait` on trait `Baz`
//~|WARN there is no parameter `ItemContext` on trait `Baz` //~|WARN there is no parameter `ItemContext` on trait `Baz`
//~|WARN there is no parameter `ItemContext` on trait `Baz` //~|WARN there is no parameter `ItemContext` on trait `Baz`
//~|WARN there is no parameter `This` on trait `Baz`
//~|WARN there is no parameter `This` on trait `Baz`
)] )]
trait Baz {} trait Baz {}

View File

@@ -9,8 +9,8 @@ LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl
warning: malformed `on_unimplemented` attribute warning: malformed `on_unimplemented` attribute
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5
| |
LL | on(_Self = "&str"), LL | on(Self = "&str"),
| ^^^^^^^^^^^^^^^^^^ invalid option found here | ^^^^^^^^^^^^^^^^^ invalid option found here
| |
= help: only `message`, `note` and `label` are allowed as options = help: only `message`, `note` and `label` are allowed as options
@@ -81,7 +81,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
warning: there is no parameter `float` on trait `Baz` warning: there is no parameter `float` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:15 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:15
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^ | ^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
@@ -89,7 +89,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `_Self` on trait `Baz` warning: there is no parameter `_Self` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:22 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:22
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^ | ^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
@@ -97,7 +97,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `crate_local` on trait `Baz` warning: there is no parameter `crate_local` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:29 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:29
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^^^^^^^ | ^^^^^^^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
@@ -105,7 +105,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `Trait` on trait `Baz` warning: there is no parameter `Trait` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:42 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:42
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^ | ^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
@@ -113,16 +113,24 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `ItemContext` on trait `Baz` warning: there is no parameter `ItemContext` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:49 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:49
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^^^^^^^ | ^^^^^^^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
warning: there is no parameter `This` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:62
|
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^
|
= help: expect either a generic argument name or `{Self}` as format argument
warning: malformed `on_unimplemented` attribute warning: malformed `on_unimplemented` attribute
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5
| |
LL | on(_Self = "&str"), LL | on(Self = "&str"),
| ^^^^^^^^^^^^^^^^^^ invalid option found here | ^^^^^^^^^^^^^^^^^ invalid option found here
| |
= help: only `message`, `note` and `label` are allowed as options = help: only `message`, `note` and `label` are allowed as options
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
@@ -146,7 +154,7 @@ LL | append_const_msg
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: trait has `()` and `i32` as params error[E0277]: trait has `()` and `i32` as params
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:63:15 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15
| |
LL | takes_foo(()); LL | takes_foo(());
| --------- ^^ trait has `()` and `i32` as params | --------- ^^ trait has `()` and `i32` as params
@@ -161,7 +169,7 @@ help: this trait has no implementations, consider adding one
LL | trait Foo<T> {} LL | trait Foo<T> {}
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
note: required by a bound in `takes_foo` note: required by a bound in `takes_foo`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:22 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:60:22
| |
LL | fn takes_foo(_: impl Foo<i32>) {} LL | fn takes_foo(_: impl Foo<i32>) {}
| ^^^^^^^^ required by this bound in `takes_foo` | ^^^^^^^^ required by this bound in `takes_foo`
@@ -176,7 +184,7 @@ LL | #[diagnostic::on_unimplemented = "Message"]
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: the trait bound `(): Bar` is not satisfied error[E0277]: the trait bound `(): Bar` is not satisfied
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:65:15 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:67:15
| |
LL | takes_bar(()); LL | takes_bar(());
| --------- ^^ the trait `Bar` is not implemented for `()` | --------- ^^ the trait `Bar` is not implemented for `()`
@@ -185,7 +193,7 @@ LL | takes_bar(());
| |
= help: the trait `Bar` is implemented for `i32` = help: the trait `Bar` is implemented for `i32`
note: required by a bound in `takes_bar` note: required by a bound in `takes_bar`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:59:22 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:61:22
| |
LL | fn takes_bar(_: impl Bar) {} LL | fn takes_bar(_: impl Bar) {}
| ^^^ required by this bound in `takes_bar` | ^^^ required by this bound in `takes_bar`
@@ -238,7 +246,7 @@ LL | message = "{from_desugaring}{direct}{cause}{integral}{integer}",
warning: there is no parameter `float` on trait `Baz` warning: there is no parameter `float` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:15 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:15
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^ | ^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
@@ -247,7 +255,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `_Self` on trait `Baz` warning: there is no parameter `_Self` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:22 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:22
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^ | ^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
@@ -256,7 +264,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `crate_local` on trait `Baz` warning: there is no parameter `crate_local` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:29 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:29
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^^^^^^^ | ^^^^^^^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
@@ -265,7 +273,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `Trait` on trait `Baz` warning: there is no parameter `Trait` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:42 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:42
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^ | ^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
@@ -274,32 +282,41 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `ItemContext` on trait `Baz` warning: there is no parameter `ItemContext` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:49 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:49
| |
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}" LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^^^^^^^^ | ^^^^^^^^^^^
| |
= help: expect either a generic argument name or `{Self}` as format argument = help: expect either a generic argument name or `{Self}` as format argument
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
warning: there is no parameter `This` on trait `Baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:44:62
|
LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}{This}"
| ^^^^
|
= help: expect either a generic argument name or `{Self}` as format argument
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer} error[E0277]: {from_desugaring}{direct}{cause}{integral}{integer}
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:67:15 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:69:15
| |
LL | takes_baz(()); LL | takes_baz(());
| --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext} | --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}{This}
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
= help: the trait `Baz` is not implemented for `()` = help: the trait `Baz` is not implemented for `()`
help: this trait has no implementations, consider adding one help: this trait has no implementations, consider adding one
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:56:1 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:58:1
| |
LL | trait Baz {} LL | trait Baz {}
| ^^^^^^^^^ | ^^^^^^^^^
note: required by a bound in `takes_baz` note: required by a bound in `takes_baz`
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:60:22 --> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:62:22
| |
LL | fn takes_baz(_: impl Baz) {} LL | fn takes_baz(_: impl Baz) {}
| ^^^ required by this bound in `takes_baz` | ^^^ required by this bound in `takes_baz`
error: aborting due to 3 previous errors; 29 warnings emitted error: aborting due to 3 previous errors; 31 warnings emitted
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View File

@@ -14,11 +14,15 @@ struct Bar {}
//~|WARN malformed `on_unimplemented` attribute //~|WARN malformed `on_unimplemented` attribute
trait Baz {} trait Baz {}
#[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] #[diagnostic::on_unimplemented(message = "Boom", on(Self = "i32", message = "whatever"))]
//~^WARN malformed `on_unimplemented` attribute //~^WARN malformed `on_unimplemented` attribute
//~|WARN malformed `on_unimplemented` attribute //~|WARN malformed `on_unimplemented` attribute
trait Boom {} trait Boom {}
#[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
//~^WARN malformed `on_unimplemented` attribute
trait _Self {}
#[diagnostic::on_unimplemented = "boom"] #[diagnostic::on_unimplemented = "boom"]
//~^WARN malformed `on_unimplemented` attribute //~^WARN malformed `on_unimplemented` attribute
trait Doom {} trait Doom {}

View File

@@ -25,13 +25,21 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
warning: malformed `on_unimplemented` attribute warning: malformed `on_unimplemented` attribute
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50
| |
LL | #[diagnostic::on_unimplemented(message = "Boom", on(Self = "i32", message = "whatever"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
|
= help: only `message`, `note` and `label` are allowed as options
warning: malformed `on_unimplemented` attribute
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:22:50
|
LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
| |
= help: only `message`, `note` and `label` are allowed as options = help: only `message`, `note` and `label` are allowed as options
warning: malformed `on_unimplemented` attribute warning: malformed `on_unimplemented` attribute
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:22:32 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:32
| |
LL | #[diagnostic::on_unimplemented = "boom"] LL | #[diagnostic::on_unimplemented = "boom"]
| ^^^^^^^^ invalid option found here | ^^^^^^^^ invalid option found here
@@ -39,7 +47,7 @@ LL | #[diagnostic::on_unimplemented = "boom"]
= help: only `message`, `note` and `label` are allowed as options = help: only `message`, `note` and `label` are allowed as options
warning: missing options for `on_unimplemented` attribute warning: missing options for `on_unimplemented` attribute
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:30:1
| |
LL | #[diagnostic::on_unimplemented] LL | #[diagnostic::on_unimplemented]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +55,7 @@ LL | #[diagnostic::on_unimplemented]
= help: at least one of the `message`, `note` and `label` options are expected = help: at least one of the `message`, `note` and `label` options are expected
warning: there is no parameter `DoesNotExist` on trait `Test` warning: there is no parameter `DoesNotExist` on trait `Test`
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:44 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:44
| |
LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
@@ -64,7 +72,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: the trait bound `i32: Foo` is not satisfied error[E0277]: the trait bound `i32: Foo` is not satisfied
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:14 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:14
| |
LL | take_foo(1_i32); LL | take_foo(1_i32);
| -------- ^^^^^ the trait `Foo` is not implemented for `i32` | -------- ^^^^^ the trait `Foo` is not implemented for `i32`
@@ -77,7 +85,7 @@ help: this trait has no implementations, consider adding one
LL | trait Foo {} LL | trait Foo {}
| ^^^^^^^^^ | ^^^^^^^^^
note: required by a bound in `take_foo` note: required by a bound in `take_foo`
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:36:21 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:21
| |
LL | fn take_foo(_: impl Foo) {} LL | fn take_foo(_: impl Foo) {}
| ^^^ required by this bound in `take_foo` | ^^^ required by this bound in `take_foo`
@@ -92,7 +100,7 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: Boom error[E0277]: Boom
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:45:14 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:14
| |
LL | take_baz(1_i32); LL | take_baz(1_i32);
| -------- ^^^^^ the trait `Baz` is not implemented for `i32` | -------- ^^^^^ the trait `Baz` is not implemented for `i32`
@@ -105,7 +113,7 @@ help: this trait has no implementations, consider adding one
LL | trait Baz {} LL | trait Baz {}
| ^^^^^^^^^ | ^^^^^^^^^
note: required by a bound in `take_baz` note: required by a bound in `take_baz`
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:37:21 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:41:21
| |
LL | fn take_baz(_: impl Baz) {} LL | fn take_baz(_: impl Baz) {}
| ^^^ required by this bound in `take_baz` | ^^^ required by this bound in `take_baz`
@@ -113,14 +121,14 @@ LL | fn take_baz(_: impl Baz) {}
warning: malformed `on_unimplemented` attribute warning: malformed `on_unimplemented` attribute
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:17:50
| |
LL | #[diagnostic::on_unimplemented(message = "Boom", on(_Self = "i32", message = "whatever"))] LL | #[diagnostic::on_unimplemented(message = "Boom", on(Self = "i32", message = "whatever"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
| |
= help: only `message`, `note` and `label` are allowed as options = help: only `message`, `note` and `label` are allowed as options
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: Boom error[E0277]: Boom
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:47:15 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15
| |
LL | take_boom(1_i32); LL | take_boom(1_i32);
| --------- ^^^^^ the trait `Boom` is not implemented for `i32` | --------- ^^^^^ the trait `Boom` is not implemented for `i32`
@@ -133,13 +141,13 @@ help: this trait has no implementations, consider adding one
LL | trait Boom {} LL | trait Boom {}
| ^^^^^^^^^^ | ^^^^^^^^^^
note: required by a bound in `take_boom` note: required by a bound in `take_boom`
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:22 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:42:22
| |
LL | fn take_boom(_: impl Boom) {} LL | fn take_boom(_: impl Boom) {}
| ^^^^ required by this bound in `take_boom` | ^^^^ required by this bound in `take_boom`
warning: missing options for `on_unimplemented` attribute warning: missing options for `on_unimplemented` attribute
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:1 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:30:1
| |
LL | #[diagnostic::on_unimplemented] LL | #[diagnostic::on_unimplemented]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +156,7 @@ LL | #[diagnostic::on_unimplemented]
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: the trait bound `i32: Whatever` is not satisfied error[E0277]: the trait bound `i32: Whatever` is not satisfied
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:49:19 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:53:19
| |
LL | take_whatever(1_i32); LL | take_whatever(1_i32);
| ------------- ^^^^^ the trait `Whatever` is not implemented for `i32` | ------------- ^^^^^ the trait `Whatever` is not implemented for `i32`
@@ -156,18 +164,18 @@ LL | take_whatever(1_i32);
| required by a bound introduced by this call | required by a bound introduced by this call
| |
help: this trait has no implementations, consider adding one help: this trait has no implementations, consider adding one
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:29:1 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:33:1
| |
LL | trait Whatever {} LL | trait Whatever {}
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
note: required by a bound in `take_whatever` note: required by a bound in `take_whatever`
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:39:26 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:43:26
| |
LL | fn take_whatever(_: impl Whatever) {} LL | fn take_whatever(_: impl Whatever) {}
| ^^^^^^^^ required by this bound in `take_whatever` | ^^^^^^^^ required by this bound in `take_whatever`
warning: there is no parameter `DoesNotExist` on trait `Test` warning: there is no parameter `DoesNotExist` on trait `Test`
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:31:44 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:35:44
| |
LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")] LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^
@@ -176,7 +184,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: {DoesNotExist} error[E0277]: {DoesNotExist}
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:51:15 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:55:15
| |
LL | take_test(()); LL | take_test(());
| --------- ^^ the trait `Test` is not implemented for `()` | --------- ^^ the trait `Test` is not implemented for `()`
@@ -184,16 +192,16 @@ LL | take_test(());
| required by a bound introduced by this call | required by a bound introduced by this call
| |
help: this trait has no implementations, consider adding one help: this trait has no implementations, consider adding one
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:34:1 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:38:1
| |
LL | trait Test {} LL | trait Test {}
| ^^^^^^^^^^ | ^^^^^^^^^^
note: required by a bound in `take_test` note: required by a bound in `take_test`
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:40:22 --> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:44:22
| |
LL | fn take_test(_: impl Test) {} LL | fn take_test(_: impl Test) {}
| ^^^^ required by this bound in `take_test` | ^^^^ required by this bound in `take_test`
error: aborting due to 5 previous errors; 12 warnings emitted error: aborting due to 5 previous errors; 13 warnings emitted
For more information about this error, try `rustc --explain E0277`. For more information about this error, try `rustc --explain E0277`.

View File

@@ -59,7 +59,7 @@ trait EmptyOn {}
//~^^^ NOTE expected value here //~^^^ NOTE expected value here
trait ExpectedPredicateInOn {} trait ExpectedPredicateInOn {}
#[rustc_on_unimplemented(on(x = "y"), message = "y")] #[rustc_on_unimplemented(on(Self = "y"), message = "y")]
trait OnWithoutDirectives {} trait OnWithoutDirectives {}
#[rustc_on_unimplemented(on(from_desugaring, on(from_desugaring, message = "x")), message = "y")] #[rustc_on_unimplemented(on(from_desugaring, on(from_desugaring, message = "x")), message = "y")]
@@ -107,3 +107,13 @@ trait InvalidPredicate {}
//~^ ERROR invalid flag in `on`-clause //~^ ERROR invalid flag in `on`-clause
//~^^ NOTE expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something` //~^^ NOTE expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something`
trait InvalidFlag {} trait InvalidFlag {}
#[rustc_on_unimplemented(on(_Self = "y", message = "y"))]
//~^ ERROR invalid name in `on`-clause
//~^^ NOTE expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `_Self`
trait InvalidName {}
#[rustc_on_unimplemented(on(abc = "y", message = "y"))]
//~^ ERROR invalid name in `on`-clause
//~^^ NOTE expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `abc`
trait InvalidName2 {}

View File

@@ -125,7 +125,19 @@ error[E0232]: invalid flag in `on`-clause
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`
error: aborting due to 18 previous errors error[E0232]: invalid name in `on`-clause
--> $DIR/bad-annotation.rs:111:29
|
LL | #[rustc_on_unimplemented(on(_Self = "y", message = "y"))]
| ^^^^^ expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `_Self`
error[E0232]: invalid name in `on`-clause
--> $DIR/bad-annotation.rs:116:29
|
LL | #[rustc_on_unimplemented(on(abc = "y", message = "y"))]
| ^^^ expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `abc`
error: aborting due to 20 previous errors
Some errors have detailed explanations: E0230, E0231, E0232. Some errors have detailed explanations: E0230, E0231, E0232.
For more information about an error, try `rustc --explain E0230`. For more information about an error, try `rustc --explain E0230`.

View File

@@ -3,7 +3,7 @@
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
pub mod Bar { pub mod Bar {
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"] #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{This}`"]
pub trait Foo<Bar, Baz, Quux> {} pub trait Foo<Bar, Baz, Quux> {}
} }