1
Fork 0

Stabilize #[diagnostic::do_not_recommend]

This commit seeks to stabilize the `#[diagnostic::do_not_recommend]`
attribute.
This attribute was first proposed as `#[do_not_recommend`] attribute in
RFC 2397 (https://github.com/rust-lang/rfcs/pull/2397). It gives the
crate authors the ability to not suggest to the compiler to not show
certain traits in it's error messages. With the presence of the
`#[diagnostic]` tool attribute namespace it was decided to move the
attribute there, as that lowers the amount of guarantees the compiler
needs to give about the exact way this influences error messages. It
turns the attribute into a hint which can be ignored. In addition to the
original proposed functionality this attribute now also hides the marked
trait in help messages ("This trait is implemented by: ").
The attribute does not accept any argument and can only be placed on
trait implementations. If it is placed somewhere else a lint warning is
emitted and the attribute is otherwise ignored. If an argument is
detected a lint warning is emitted and the argument is ignored. This
follows the rules outlined by the diagnostic namespace.

This attribute allows crates like diesel to improve their error messages
drastically. The most common example here is the following error
message:

```
error[E0277]: the trait bound `&str: Expression` is not satisfied
  --> /home/weiznich/Documents/rust/rust/tests/ui/diagnostic_namespace/do_not_recommend.rs:53:15
   |
LL |     SelectInt.check("bar");
   |               ^^^^^ the trait `Expression` is not implemented for `&str`, which is required by `&str: AsExpression<Integer>`
   |
   = help: the following other types implement trait `Expression`:
             Bound<T>
             SelectInt
note: required for `&str` to implement `AsExpression<Integer>`
  --> /home/weiznich/Documents/rust/rust/tests/ui/diagnostic_namespace/do_not_recommend.rs:26:13
   |
LL | impl<T, ST> AsExpression<ST> for T
   |             ^^^^^^^^^^^^^^^^     ^
LL | where
LL |     T: Expression<SqlType = ST>,
   |        ------------------------ unsatisfied trait bound introduced here
```

By applying the new attribute to the wild card trait implementation of
`AsExpression` for `T: Expression` the error message becomes:

```
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
  --> $DIR/as_expression.rs:55:15
   |
LL |     SelectInt.check("bar");
   |               ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
   |
   = help: the trait `AsExpression<Text>` is implemented for `&str`
   = help: for that trait implementation, expected `Text`, found `Integer`
```

which makes it much easier for users to understand that they are facing
a type mismatch.

Other explored example usages included

* This standard library error message: https://github.com/rust-lang/rust/pull/128008
* That bevy derived example:
e1f3068995/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs (No
more tuple pyramids)

Fixes #51992
This commit is contained in:
Georg Semmler 2024-10-23 08:09:15 +02:00
parent ecb6fd8d3a
commit dd31713c53
No known key found for this signature in database
GPG key ID: A87BCEE5205CE489
41 changed files with 55 additions and 235 deletions

View file

@ -178,6 +178,8 @@ declare_features! (
(accepted, destructuring_assignment, "1.59.0", Some(71126)), (accepted, destructuring_assignment, "1.59.0", Some(71126)),
/// Allows using the `#[diagnostic]` attribute tool namespace /// Allows using the `#[diagnostic]` attribute tool namespace
(accepted, diagnostic_namespace, "1.78.0", Some(111996)), (accepted, diagnostic_namespace, "1.78.0", Some(111996)),
/// Controls errors in trait implementations.
(accepted, do_not_recommend, "CURRENT_RUSTC_VERSION", Some(51992)),
/// Allows `#[doc(alias = "...")]`. /// Allows `#[doc(alias = "...")]`.
(accepted, doc_alias, "1.48.0", Some(50146)), (accepted, doc_alias, "1.48.0", Some(50146)),
/// Allows `..` in tuple (struct) patterns. /// Allows `..` in tuple (struct) patterns.

View file

@ -1187,10 +1187,9 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>>
map map
}); });
pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool { pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool {
match sym { match sym {
sym::on_unimplemented => true, sym::on_unimplemented | sym::do_not_recommend => true,
sym::do_not_recommend => features.do_not_recommend(),
_ => false, _ => false,
} }
} }

View file

@ -462,8 +462,6 @@ declare_features! (
(unstable, deprecated_suggestion, "1.61.0", Some(94785)), (unstable, deprecated_suggestion, "1.61.0", Some(94785)),
/// Allows deref patterns. /// Allows deref patterns.
(incomplete, deref_patterns, "1.79.0", Some(87121)), (incomplete, deref_patterns, "1.79.0", Some(87121)),
/// Controls errors in trait implementations.
(unstable, do_not_recommend, "1.67.0", Some(51992)),
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
(unstable, doc_auto_cfg, "1.58.0", Some(43781)), (unstable, doc_auto_cfg, "1.58.0", Some(43781)),
/// Allows `#[doc(cfg(...))]`. /// Allows `#[doc(cfg(...))]`.

View file

@ -689,8 +689,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
&& let [namespace, attribute, ..] = &*path.segments && let [namespace, attribute, ..] = &*path.segments
&& namespace.ident.name == sym::diagnostic && namespace.ident.name == sym::diagnostic
&& !(attribute.ident.name == sym::on_unimplemented && !(attribute.ident.name == sym::on_unimplemented
|| (attribute.ident.name == sym::do_not_recommend || attribute.ident.name == sym::do_not_recommend)
&& self.tcx.features().do_not_recommend()))
{ {
let distance = let distance =
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);

View file

@ -108,12 +108,12 @@
// Library features: // Library features:
// tidy-alphabetical-start // tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(coverage_attribute))] #![cfg_attr(bootstrap, feature(coverage_attribute))]
#![cfg_attr(bootstrap, feature(do_not_recommend))]
#![feature(array_ptr_get)] #![feature(array_ptr_get)]
#![feature(asm_experimental_arch)] #![feature(asm_experimental_arch)]
#![feature(const_eval_select)] #![feature(const_eval_select)]
#![feature(const_typed_swap)] #![feature(const_typed_swap)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(do_not_recommend)]
#![feature(internal_impls_macro)] #![feature(internal_impls_macro)]
#![feature(ip)] #![feature(ip)]
#![feature(is_ascii_octdigit)] #![feature(is_ascii_octdigit)]

View file

@ -1,5 +1,5 @@
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
--> $DIR/as_expression.rs:57:15 --> $DIR/as_expression.rs:55:15
| |
LL | SelectInt.check("bar"); LL | SelectInt.check("bar");
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str` | ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`

View file

@ -1,5 +1,5 @@
error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied error[E0277]: the trait bound `&str: AsExpression<<SelectInt as Expression>::SqlType>` is not satisfied
--> $DIR/as_expression.rs:57:21 --> $DIR/as_expression.rs:55:21
| |
LL | SelectInt.check("bar"); LL | SelectInt.check("bar");
| ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str` | ----- ^^^^^ the trait `AsExpression<<SelectInt as Expression>::SqlType>` is not implemented for `&str`
@ -8,7 +8,7 @@ LL | SelectInt.check("bar");
| |
= help: the trait `AsExpression<Text>` is implemented for `&str` = help: the trait `AsExpression<Text>` is implemented for `&str`
note: required by a bound in `Foo::check` note: required by a bound in `Foo::check`
--> $DIR/as_expression.rs:48:12 --> $DIR/as_expression.rs:46:12
| |
LL | fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression LL | fn check<T>(&self, _: T) -> <T as AsExpression<<Self as Expression>::SqlType>>::Expression
| ----- required by a bound in this associated function | ----- required by a bound in this associated function
@ -17,7 +17,7 @@ LL | T: AsExpression<Self::SqlType>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
--> $DIR/as_expression.rs:57:15 --> $DIR/as_expression.rs:55:15
| |
LL | SelectInt.check("bar"); LL | SelectInt.check("bar");
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str` | ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
@ -27,7 +27,7 @@ LL | SelectInt.check("bar");
= help: for that trait implementation, expected `Text`, found `Integer` = help: for that trait implementation, expected `Text`, found `Integer`
error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text` error[E0271]: type mismatch resolving `<SelectInt as Expression>::SqlType == Text`
--> $DIR/as_expression.rs:57:5 --> $DIR/as_expression.rs:55:5
| |
LL | SelectInt.check("bar"); LL | SelectInt.check("bar");
| ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer` | ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer`

View file

@ -2,8 +2,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
pub trait Expression { pub trait Expression {
type SqlType; type SqlType;
} }

View file

@ -1,25 +0,0 @@
error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/do_not_apply_attribute_without_feature_flag.rs:22:11
|
LL | check(());
| ----- ^^ the trait `Foo` is not implemented for `()`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Foo`:
(A, B)
(A, B, C)
(A,)
note: required by a bound in `check`
--> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:18
|
LL | fn check(a: impl Foo) {}
| ^^^ required by this bound in `check`
help: use a unary tuple instead
|
LL | check(((),));
| + ++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,21 +0,0 @@
error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/do_not_apply_attribute_without_feature_flag.rs:22:11
|
LL | check(());
| ----- ^^ the trait `Foo` is not implemented for `()`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Foo`:
(A, B)
(A, B, C)
(A,)
note: required by a bound in `check`
--> $DIR/do_not_apply_attribute_without_feature_flag.rs:19:18
|
LL | fn check(a: impl Foo) {}
| ^^^ required by this bound in `check`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,24 +0,0 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
#![allow(unknown_or_malformed_diagnostic_attributes)]
trait Foo {}
#[diagnostic::do_not_recommend]
impl<A> Foo for (A,) {}
#[diagnostic::do_not_recommend]
impl<A, B> Foo for (A, B) {}
#[diagnostic::do_not_recommend]
impl<A, B, C> Foo for (A, B, C) {}
impl Foo for i32 {}
fn check(a: impl Foo) {}
fn main() {
check(());
//~^ ERROR the trait bound `(): Foo` is not satisfied
}

View file

@ -1,5 +1,5 @@
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
--> $DIR/does_not_acccept_args.rs:12:1 --> $DIR/does_not_acccept_args.rs:10:1
| |
LL | #[diagnostic::do_not_recommend(not_accepted)] LL | #[diagnostic::do_not_recommend(not_accepted)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -7,13 +7,13 @@ LL | #[diagnostic::do_not_recommend(not_accepted)]
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
--> $DIR/does_not_acccept_args.rs:16:1 --> $DIR/does_not_acccept_args.rs:14:1
| |
LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
--> $DIR/does_not_acccept_args.rs:20:1 --> $DIR/does_not_acccept_args.rs:18:1
| |
LL | #[diagnostic::do_not_recommend(not_accepted(42))] LL | #[diagnostic::do_not_recommend(not_accepted(42))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
--> $DIR/does_not_acccept_args.rs:12:1 --> $DIR/does_not_acccept_args.rs:10:1
| |
LL | #[diagnostic::do_not_recommend(not_accepted)] LL | #[diagnostic::do_not_recommend(not_accepted)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -7,13 +7,13 @@ LL | #[diagnostic::do_not_recommend(not_accepted)]
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
--> $DIR/does_not_acccept_args.rs:16:1 --> $DIR/does_not_acccept_args.rs:14:1
| |
LL | #[diagnostic::do_not_recommend(not_accepted = "foo")] LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
--> $DIR/does_not_acccept_args.rs:20:1 --> $DIR/does_not_acccept_args.rs:18:1
| |
LL | #[diagnostic::do_not_recommend(not_accepted(42))] LL | #[diagnostic::do_not_recommend(not_accepted(42))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -3,8 +3,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
trait Foo {} trait Foo {}
trait Bar {} trait Bar {}
trait Baz {} trait Baz {}

View file

@ -1,15 +0,0 @@
error[E0277]: the trait bound `u8: Bar` is not satisfied
--> $DIR/feature-gate-do_not_recommend.rs:18:11
|
LL | stuff(1u8);
| ^^^ the trait `Bar` is not implemented for `u8`
|
note: required by a bound in `stuff`
--> $DIR/feature-gate-do_not_recommend.rs:15:13
|
LL | fn stuff<T: Bar>(_: T) {}
| ^^^ required by this bound in `stuff`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,17 +0,0 @@
error[E0277]: the trait bound `u8: Bar` is not satisfied
--> $DIR/feature-gate-do_not_recommend.rs:18:11
|
LL | stuff(1u8);
| ----- ^^^ the trait `Bar` is not implemented for `u8`
| |
| required by a bound introduced by this call
|
note: required by a bound in `stuff`
--> $DIR/feature-gate-do_not_recommend.rs:15:13
|
LL | fn stuff<T: Bar>(_: T) {}
| ^^^ required by this bound in `stuff`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,20 +0,0 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
pub trait Foo {}
impl Foo for i32 {}
pub trait Bar {}
#[diagnostic::do_not_recommend]
impl<T: Foo> Bar for T {}
fn stuff<T: Bar>(_: T) {}
fn main() {
stuff(1u8);
//~^ the trait bound `u8: Bar` is not satisfied
}

View file

@ -1,5 +1,5 @@
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:7:1 --> $DIR/incorrect-locations.rs:6:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -7,43 +7,43 @@ LL | #[diagnostic::do_not_recommend]
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:11:1 --> $DIR/incorrect-locations.rs:10:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:15:1 --> $DIR/incorrect-locations.rs:14:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:19:1 --> $DIR/incorrect-locations.rs:18:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:23:1 --> $DIR/incorrect-locations.rs:22:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:27:1 --> $DIR/incorrect-locations.rs:26:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:31:1 --> $DIR/incorrect-locations.rs:30:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:35:1 --> $DIR/incorrect-locations.rs:34:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,5 +1,5 @@
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:7:1 --> $DIR/incorrect-locations.rs:6:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -7,43 +7,43 @@ LL | #[diagnostic::do_not_recommend]
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default = note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:11:1 --> $DIR/incorrect-locations.rs:10:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:15:1 --> $DIR/incorrect-locations.rs:14:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:19:1 --> $DIR/incorrect-locations.rs:18:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:23:1 --> $DIR/incorrect-locations.rs:22:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:27:1 --> $DIR/incorrect-locations.rs:26:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:31:1 --> $DIR/incorrect-locations.rs:30:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
--> $DIR/incorrect-locations.rs:35:1 --> $DIR/incorrect-locations.rs:34:1
| |
LL | #[diagnostic::do_not_recommend] LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -2,7 +2,6 @@
//@ revisions: current next //@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
#[diagnostic::do_not_recommend] #[diagnostic::do_not_recommend]
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed //~^WARN `#[diagnostic::do_not_recommend]` can only be placed

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `(): Root` is not satisfied error[E0277]: the trait bound `(): Root` is not satisfied
--> $DIR/nested.rs:23:18 --> $DIR/nested.rs:21:18
| |
LL | needs_root::<()>(); LL | needs_root::<()>();
| ^^ the trait `Root` is not implemented for `()` | ^^ the trait `Root` is not implemented for `()`
| |
note: required by a bound in `needs_root` note: required by a bound in `needs_root`
--> $DIR/nested.rs:20:18 --> $DIR/nested.rs:18:18
| |
LL | fn needs_root<T: Root>() {} LL | fn needs_root<T: Root>() {}
| ^^^^ required by this bound in `needs_root` | ^^^^ required by this bound in `needs_root`

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `(): Root` is not satisfied error[E0277]: the trait bound `(): Root` is not satisfied
--> $DIR/nested.rs:23:18 --> $DIR/nested.rs:21:18
| |
LL | needs_root::<()>(); LL | needs_root::<()>();
| ^^ the trait `Root` is not implemented for `()` | ^^ the trait `Root` is not implemented for `()`
| |
note: required by a bound in `needs_root` note: required by a bound in `needs_root`
--> $DIR/nested.rs:20:18 --> $DIR/nested.rs:18:18
| |
LL | fn needs_root<T: Root>() {} LL | fn needs_root<T: Root>() {}
| ^^^^ required by this bound in `needs_root` | ^^^^ required by this bound in `needs_root`

View file

@ -2,8 +2,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
trait Root {} trait Root {}
trait DontRecommend {} trait DontRecommend {}
trait Other {} trait Other {}

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `*mut (): Foo` is not satisfied error[E0277]: the trait bound `*mut (): Foo` is not satisfied
--> $DIR/simple.rs:17:17 --> $DIR/simple.rs:15:17
| |
LL | needs_foo::<*mut ()>(); LL | needs_foo::<*mut ()>();
| ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
| |
note: required by a bound in `needs_foo` note: required by a bound in `needs_foo`
--> $DIR/simple.rs:12:17 --> $DIR/simple.rs:10:17
| |
LL | fn needs_foo<T: Foo>() {} LL | fn needs_foo<T: Foo>() {}
| ^^^ required by this bound in `needs_foo` | ^^^ required by this bound in `needs_foo`

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `*mut (): Foo` is not satisfied error[E0277]: the trait bound `*mut (): Foo` is not satisfied
--> $DIR/simple.rs:17:17 --> $DIR/simple.rs:15:17
| |
LL | needs_foo::<*mut ()>(); LL | needs_foo::<*mut ()>();
| ^^^^^^^ the trait `Foo` is not implemented for `*mut ()` | ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
| |
note: required by a bound in `needs_foo` note: required by a bound in `needs_foo`
--> $DIR/simple.rs:12:17 --> $DIR/simple.rs:10:17
| |
LL | fn needs_foo<T: Foo>() {} LL | fn needs_foo<T: Foo>() {}
| ^^^ required by this bound in `needs_foo` | ^^^ required by this bound in `needs_foo`

View file

@ -2,8 +2,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
trait Foo {} trait Foo {}
#[diagnostic::do_not_recommend] #[diagnostic::do_not_recommend]

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `(): Root` is not satisfied error[E0277]: the trait bound `(): Root` is not satisfied
--> $DIR/stacked.rs:19:18 --> $DIR/stacked.rs:17:18
| |
LL | needs_root::<()>(); LL | needs_root::<()>();
| ^^ the trait `Root` is not implemented for `()` | ^^ the trait `Root` is not implemented for `()`
| |
note: required by a bound in `needs_root` note: required by a bound in `needs_root`
--> $DIR/stacked.rs:16:18 --> $DIR/stacked.rs:14:18
| |
LL | fn needs_root<T: Root>() {} LL | fn needs_root<T: Root>() {}
| ^^^^ required by this bound in `needs_root` | ^^^^ required by this bound in `needs_root`

View file

@ -1,11 +1,11 @@
error[E0277]: the trait bound `(): Root` is not satisfied error[E0277]: the trait bound `(): Root` is not satisfied
--> $DIR/stacked.rs:19:18 --> $DIR/stacked.rs:17:18
| |
LL | needs_root::<()>(); LL | needs_root::<()>();
| ^^ the trait `Root` is not implemented for `()` | ^^ the trait `Root` is not implemented for `()`
| |
note: required by a bound in `needs_root` note: required by a bound in `needs_root`
--> $DIR/stacked.rs:16:18 --> $DIR/stacked.rs:14:18
| |
LL | fn needs_root<T: Root>() {} LL | fn needs_root<T: Root>() {}
| ^^^^ required by this bound in `needs_root` | ^^^^ required by this bound in `needs_root`

View file

@ -2,8 +2,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
trait Root {} trait Root {}
trait DontRecommend {} trait DontRecommend {}
trait Other {} trait Other {}

View file

@ -1,5 +1,5 @@
error[E0277]: the trait bound `(): Foo` is not satisfied error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/supress_suggestions_in_help.rs:23:11 --> $DIR/supress_suggestions_in_help.rs:21:11
| |
LL | check(()); LL | check(());
| ----- ^^ the trait `Foo` is not implemented for `()` | ----- ^^ the trait `Foo` is not implemented for `()`
@ -8,7 +8,7 @@ LL | check(());
| |
= help: the trait `Foo` is implemented for `i32` = help: the trait `Foo` is implemented for `i32`
note: required by a bound in `check` note: required by a bound in `check`
--> $DIR/supress_suggestions_in_help.rs:20:18 --> $DIR/supress_suggestions_in_help.rs:18:18
| |
LL | fn check(a: impl Foo) {} LL | fn check(a: impl Foo) {}
| ^^^ required by this bound in `check` | ^^^ required by this bound in `check`

View file

@ -1,5 +1,5 @@
error[E0277]: the trait bound `(): Foo` is not satisfied error[E0277]: the trait bound `(): Foo` is not satisfied
--> $DIR/supress_suggestions_in_help.rs:23:11 --> $DIR/supress_suggestions_in_help.rs:21:11
| |
LL | check(()); LL | check(());
| ----- ^^ the trait `Foo` is not implemented for `()` | ----- ^^ the trait `Foo` is not implemented for `()`
@ -8,7 +8,7 @@ LL | check(());
| |
= help: the trait `Foo` is implemented for `i32` = help: the trait `Foo` is implemented for `i32`
note: required by a bound in `check` note: required by a bound in `check`
--> $DIR/supress_suggestions_in_help.rs:20:18 --> $DIR/supress_suggestions_in_help.rs:18:18
| |
LL | fn check(a: impl Foo) {} LL | fn check(a: impl Foo) {}
| ^^^ required by this bound in `check` | ^^^ required by this bound in `check`

View file

@ -2,8 +2,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
trait Foo {} trait Foo {}
#[diagnostic::do_not_recommend] #[diagnostic::do_not_recommend]

View file

@ -1,11 +1,11 @@
error[E0277]: Very important message! error[E0277]: Very important message!
--> $DIR/type_mismatch.rs:25:14 --> $DIR/type_mismatch.rs:23:14
| |
LL | verify::<u8>(); LL | verify::<u8>();
| ^^ the trait `TheImportantOne` is not implemented for `u8` | ^^ the trait `TheImportantOne` is not implemented for `u8`
| |
note: required by a bound in `verify` note: required by a bound in `verify`
--> $DIR/type_mismatch.rs:22:14 --> $DIR/type_mismatch.rs:20:14
| |
LL | fn verify<T: TheImportantOne>() {} LL | fn verify<T: TheImportantOne>() {}
| ^^^^^^^^^^^^^^^ required by this bound in `verify` | ^^^^^^^^^^^^^^^ required by this bound in `verify`

View file

@ -1,11 +1,11 @@
error[E0277]: Very important message! error[E0277]: Very important message!
--> $DIR/type_mismatch.rs:25:14 --> $DIR/type_mismatch.rs:23:14
| |
LL | verify::<u8>(); LL | verify::<u8>();
| ^^ the trait `TheImportantOne` is not implemented for `u8` | ^^ the trait `TheImportantOne` is not implemented for `u8`
| |
note: required by a bound in `verify` note: required by a bound in `verify`
--> $DIR/type_mismatch.rs:22:14 --> $DIR/type_mismatch.rs:20:14
| |
LL | fn verify<T: TheImportantOne>() {} LL | fn verify<T: TheImportantOne>() {}
| ^^^^^^^^^^^^^^^ required by this bound in `verify` | ^^^^^^^^^^^^^^^ required by this bound in `verify`

View file

@ -2,8 +2,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
#[diagnostic::on_unimplemented(message = "Very important message!")] #[diagnostic::on_unimplemented(message = "Very important message!")]
trait TheImportantOne {} trait TheImportantOne {}

View file

@ -1,14 +0,0 @@
error: unknown diagnostic attribute
--> $DIR/unstable-feature.rs:7:15
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/unstable-feature.rs:4:9
|
LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -1,14 +0,0 @@
error: unknown diagnostic attribute
--> $DIR/unstable-feature.rs:7:15
|
LL | #[diagnostic::do_not_recommend]
| ^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/unstable-feature.rs:4:9
|
LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -1,11 +0,0 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
#![deny(unknown_or_malformed_diagnostic_attributes)]
trait Foo {}
#[diagnostic::do_not_recommend]
//~^ ERROR unknown diagnostic attribute [unknown_or_malformed_diagnostic_attributes]
impl Foo for i32 {}
fn main() {}

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/with_lifetime.rs:19:5 --> $DIR/with_lifetime.rs:17:5
| |
LL | fn foo<'a>(a: &'a ()) { LL | fn foo<'a>(a: &'a ()) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/with_lifetime.rs:19:5 --> $DIR/with_lifetime.rs:17:5
| |
LL | fn foo<'a>(a: &'a ()) { LL | fn foo<'a>(a: &'a ()) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here

View file

@ -2,8 +2,6 @@
//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver //@[next] compile-flags: -Znext-solver
#![feature(do_not_recommend)]
trait Root {} trait Root {}
trait DontRecommend {} trait DontRecommend {}