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,
Yield,
_DECLS,
_Self,
__D,
__H,
__S,

View File

@@ -337,6 +337,8 @@ trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not = expected
.label = unexpected quantity of predicates here
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}`
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
.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

View File

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

View File

@@ -2,8 +2,8 @@ use std::fmt;
use std::ops::Range;
use errors::*;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::print::TraitRefPrintSugared;
use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
use rustc_parse_format::{
Alignment, Argument, Count, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece,
Position,
@@ -232,48 +232,16 @@ fn parse_arg<'tcx>(
) -> FormatArg {
let (Ctx::RustcOnUnimplemented { tcx, trait_def_id }
| 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());
match arg.position {
// Something like "hello {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
(Ctx::RustcOnUnimplemented { .. }, sym::ItemContext) => FormatArg::ItemContext,
(Ctx::RustcOnUnimplemented { .. }, sym::This) => FormatArg::This,
(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
(
Ctx::RustcOnUnimplemented { .. } | Ctx::DiagnosticOnUnimplemented { .. },
@@ -282,7 +250,10 @@ fn parse_arg<'tcx>(
(
Ctx::RustcOnUnimplemented { .. } | Ctx::DiagnosticOnUnimplemented { .. },
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 }
}
@@ -375,39 +346,4 @@ pub mod errors {
#[diag(trait_selection_missing_options_for_on_unimplemented_attr)]
#[help]
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,
invalid_flag: Symbol,
},
#[diag(trait_selection_rustc_on_unimplemented_invalid_name, code = E0232)]
InvalidName {
#[primary_span]
#[label]
span: Span,
invalid_name: Symbol,
},
}
#[derive(Diagnostic)]

View File

@@ -21,7 +21,7 @@ fn foo() {}
fn bar() {}
// 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 {}
#[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.invalid-formats
#[diagnostic::on_unimplemented(
on(_Self = "&str"),
on(Self = "&str"),
//~^WARN malformed `on_unimplemented` attribute
//~|WARN malformed `on_unimplemented` attribute
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 `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 `_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 `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 {}

View File

@@ -9,8 +9,8 @@ LL | #[diagnostic::on_unimplemented(message = "Not allowed to apply it on a impl
warning: malformed `on_unimplemented` attribute
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5
|
LL | on(_Self = "&str"),
| ^^^^^^^^^^^^^^^^^^ invalid option found here
LL | on(Self = "&str"),
| ^^^^^^^^^^^^^^^^^ invalid option found here
|
= 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`
--> $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
@@ -89,7 +89,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `_Self` on trait `Baz`
--> $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
@@ -97,7 +97,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `crate_local` on trait `Baz`
--> $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
@@ -105,7 +105,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `Trait` on trait `Baz`
--> $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
@@ -113,16 +113,24 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `ItemContext` on trait `Baz`
--> $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
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
--> $DIR/do_not_accept_options_of_the_internal_rustc_attribute.rs:6:5
|
LL | on(_Self = "&str"),
| ^^^^^^^^^^^^^^^^^^ invalid option found here
LL | on(Self = "&str"),
| ^^^^^^^^^^^^^^^^^ invalid option found here
|
= help: only `message`, `note` and `label` are allowed as options
= 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`
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(());
| --------- ^^ trait has `()` and `i32` as params
@@ -161,7 +169,7 @@ help: this trait has no implementations, consider adding one
LL | trait Foo<T> {}
| ^^^^^^^^^^^^
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>) {}
| ^^^^^^^^ 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`
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(());
| --------- ^^ the trait `Bar` is not implemented for `()`
@@ -185,7 +193,7 @@ LL | takes_bar(());
|
= help: the trait `Bar` is implemented for `i32`
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) {}
| ^^^ 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`
--> $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
@@ -247,7 +255,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `_Self` on trait `Baz`
--> $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
@@ -256,7 +264,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `crate_local` on trait `Baz`
--> $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
@@ -265,7 +273,7 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `Trait` on trait `Baz`
--> $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
@@ -274,32 +282,41 @@ LL | label = "{float}{_Self}{crate_local}{Trait}{ItemContext}"
warning: there is no parameter `ItemContext` on trait `Baz`
--> $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
= 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}
--> $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(());
| --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}
| --------- ^^ {float}{_Self}{crate_local}{Trait}{ItemContext}{This}
| |
| required by a bound introduced by this call
|
= help: the trait `Baz` is not implemented for `()`
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 {}
| ^^^^^^^^^
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) {}
| ^^^ 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`.

View File

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

View File

@@ -25,13 +25,21 @@ LL | #[diagnostic::on_unimplemented(message = "Boom", unsupported = "Bar")]
warning: malformed `on_unimplemented` attribute
--> $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"))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:32
--> $DIR/do_not_fail_parsing_on_invalid_options_1.rs:26:32
|
LL | #[diagnostic::on_unimplemented = "boom"]
| ^^^^^^^^ invalid option found here
@@ -39,7 +47,7 @@ LL | #[diagnostic::on_unimplemented = "boom"]
= help: only `message`, `note` and `label` are allowed as options
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]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +55,7 @@ LL | #[diagnostic::on_unimplemented]
= help: at least one of the `message`, `note` and `label` options are expected
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}")]
| ^^^^^^^^^^^^
@@ -64,7 +72,7 @@ LL | #[diagnostic::on_unimplemented(unsupported = "foo")]
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
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);
| -------- ^^^^^ the trait `Foo` is not implemented for `i32`
@@ -77,7 +85,7 @@ help: this trait has no implementations, consider adding one
LL | trait 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) {}
| ^^^ 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`
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);
| -------- ^^^^^ the trait `Baz` is not implemented for `i32`
@@ -105,7 +113,7 @@ help: this trait has no implementations, consider adding one
LL | trait 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) {}
| ^^^ required by this bound in `take_baz`
@@ -113,14 +121,14 @@ LL | fn take_baz(_: impl Baz) {}
warning: malformed `on_unimplemented` attribute
--> $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
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
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
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);
| --------- ^^^^^ the trait `Boom` is not implemented for `i32`
@@ -133,13 +141,13 @@ help: this trait has no implementations, consider adding one
LL | trait 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) {}
| ^^^^ required by this bound in `take_boom`
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]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -148,7 +156,7 @@ LL | #[diagnostic::on_unimplemented]
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
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);
| ------------- ^^^^^ 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
|
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 {}
| ^^^^^^^^^^^^^^
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) {}
| ^^^^^^^^ required by this bound in `take_whatever`
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}")]
| ^^^^^^^^^^^^
@@ -176,7 +184,7 @@ LL | #[diagnostic::on_unimplemented(message = "{DoesNotExist}")]
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
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(());
| --------- ^^ the trait `Test` is not implemented for `()`
@@ -184,16 +192,16 @@ LL | take_test(());
| required by a bound introduced by this call
|
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 {}
| ^^^^^^^^^^
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) {}
| ^^^^ 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`.

View File

@@ -59,7 +59,7 @@ trait EmptyOn {}
//~^^^ NOTE expected value here
trait ExpectedPredicateInOn {}
#[rustc_on_unimplemented(on(x = "y"), message = "y")]
#[rustc_on_unimplemented(on(Self = "y"), message = "y")]
trait OnWithoutDirectives {}
#[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
//~^^ NOTE expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `something`
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"))]
| ^^^^^^^^^ 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.
For more information about an error, try `rustc --explain E0230`.

View File

@@ -3,7 +3,7 @@
#![feature(rustc_attrs)]
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> {}
}