mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Rollup merge of #132056 - weiznich:diagnostic_do_not_recommend_final_tests, r=compiler-errors
Stabilize `#[diagnostic::do_not_recommend]`
This PR 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 its 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 include:
* 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
r? ``@compiler-errors``
This PR also adds a few more tests, makes sure that all the tests are run for the old and new trait solver and adds a check that the attribute does not contain arguments.
This commit is contained in:
commit
e018796012
@ -178,6 +178,8 @@ declare_features! (
|
||||
(accepted, destructuring_assignment, "1.59.0", Some(71126)),
|
||||
/// Allows using the `#[diagnostic]` attribute tool namespace
|
||||
(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 = "...")]`.
|
||||
(accepted, doc_alias, "1.48.0", Some(50146)),
|
||||
/// Allows `..` in tuple (struct) patterns.
|
||||
|
@ -1187,10 +1187,9 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>>
|
||||
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 {
|
||||
sym::on_unimplemented => true,
|
||||
sym::do_not_recommend => features.do_not_recommend(),
|
||||
sym::on_unimplemented | sym::do_not_recommend => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -462,8 +462,6 @@ declare_features! (
|
||||
(unstable, deprecated_suggestion, "1.61.0", Some(94785)),
|
||||
/// Allows deref patterns.
|
||||
(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(...))]`.
|
||||
(unstable, doc_auto_cfg, "1.58.0", Some(43781)),
|
||||
/// Allows `#[doc(cfg(...))]`.
|
||||
|
@ -357,6 +357,9 @@ passes_ignored_derived_impls =
|
||||
passes_implied_feature_not_exist =
|
||||
feature `{$implied_by}` implying `{$feature}` does not exist
|
||||
|
||||
passes_incorrect_do_not_recommend_args =
|
||||
`#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
|
||||
passes_incorrect_do_not_recommend_location =
|
||||
`#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
|
||||
|
@ -115,7 +115,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
for attr in attrs {
|
||||
match attr.path().as_slice() {
|
||||
[sym::diagnostic, sym::do_not_recommend, ..] => {
|
||||
self.check_do_not_recommend(attr.span, hir_id, target)
|
||||
self.check_do_not_recommend(attr.span, hir_id, target, attr, item)
|
||||
}
|
||||
[sym::diagnostic, sym::on_unimplemented, ..] => {
|
||||
self.check_diagnostic_on_unimplemented(attr.span, hir_id, target)
|
||||
@ -348,8 +348,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
}
|
||||
|
||||
/// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl.
|
||||
fn check_do_not_recommend(&self, attr_span: Span, hir_id: HirId, target: Target) {
|
||||
if !matches!(target, Target::Impl) {
|
||||
fn check_do_not_recommend(
|
||||
&self,
|
||||
attr_span: Span,
|
||||
hir_id: HirId,
|
||||
target: Target,
|
||||
attr: &Attribute,
|
||||
item: Option<ItemLike<'_>>,
|
||||
) {
|
||||
if !matches!(target, Target::Impl)
|
||||
|| matches!(
|
||||
item,
|
||||
Some(ItemLike::Item(hir::Item { kind: hir::ItemKind::Impl(_impl),.. }))
|
||||
if _impl.of_trait.is_none()
|
||||
)
|
||||
{
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
hir_id,
|
||||
@ -357,6 +370,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||
errors::IncorrectDoNotRecommendLocation,
|
||||
);
|
||||
}
|
||||
if !attr.is_word() {
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr_span,
|
||||
errors::DoNotRecommendDoesNotExpectArgs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
|
||||
|
@ -20,6 +20,10 @@ use crate::lang_items::Duplicate;
|
||||
#[diag(passes_incorrect_do_not_recommend_location)]
|
||||
pub(crate) struct IncorrectDoNotRecommendLocation;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_incorrect_do_not_recommend_args)]
|
||||
pub(crate) struct DoNotRecommendDoesNotExpectArgs;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_autodiff_attr)]
|
||||
pub(crate) struct AutoDiffAttr {
|
||||
|
@ -689,8 +689,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
||||
&& let [namespace, attribute, ..] = &*path.segments
|
||||
&& namespace.ident.name == sym::diagnostic
|
||||
&& !(attribute.ident.name == sym::on_unimplemented
|
||||
|| (attribute.ident.name == sym::do_not_recommend
|
||||
&& self.tcx.features().do_not_recommend()))
|
||||
|| attribute.ident.name == sym::do_not_recommend)
|
||||
{
|
||||
let distance =
|
||||
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
|
||||
|
@ -108,12 +108,12 @@
|
||||
// Library features:
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(bootstrap, feature(coverage_attribute))]
|
||||
#![cfg_attr(bootstrap, feature(do_not_recommend))]
|
||||
#![feature(array_ptr_get)]
|
||||
#![feature(asm_experimental_arch)]
|
||||
#![feature(const_eval_select)]
|
||||
#![feature(const_typed_swap)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(do_not_recommend)]
|
||||
#![feature(internal_impls_macro)]
|
||||
#![feature(ip)]
|
||||
#![feature(is_ascii_octdigit)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
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");
|
||||
| ^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
|
||||
|
@ -1,5 +1,5 @@
|
||||
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");
|
||||
| ----- ^^^^^ 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`
|
||||
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
|
||||
| ----- required by a bound in this associated function
|
||||
@ -17,7 +17,7 @@ LL | T: AsExpression<Self::SqlType>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
|
||||
|
||||
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");
|
||||
| ^^^^^ 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`
|
||||
|
||||
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");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected `Text`, found `Integer`
|
||||
|
@ -2,8 +2,6 @@
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(do_not_recommend)]
|
||||
|
||||
pub trait Expression {
|
||||
type SqlType;
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
#![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
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
error[E0277]: the trait bound `(): Foo` is not satisfied
|
||||
--> $DIR/do_not_apply_attribute_without_feature_flag.rs:19: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:16: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`.
|
@ -0,0 +1,22 @@
|
||||
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
--> $DIR/does_not_acccept_args.rs:10:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend(not_accepted)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
--> $DIR/does_not_acccept_args.rs:14:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
--> $DIR/does_not_acccept_args.rs:18:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend(not_accepted(42))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
@ -0,0 +1,22 @@
|
||||
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
--> $DIR/does_not_acccept_args.rs:10:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend(not_accepted)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
--> $DIR/does_not_acccept_args.rs:14:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend(not_accepted = "foo")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
--> $DIR/does_not_acccept_args.rs:18:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend(not_accepted(42))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
@ -0,0 +1,22 @@
|
||||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
trait Foo {}
|
||||
trait Bar {}
|
||||
trait Baz {}
|
||||
|
||||
#[diagnostic::do_not_recommend(not_accepted)]
|
||||
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
impl<T> Foo for T where T: Send {}
|
||||
|
||||
#[diagnostic::do_not_recommend(not_accepted = "foo")]
|
||||
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
impl<T> Bar for T where T: Send {}
|
||||
|
||||
#[diagnostic::do_not_recommend(not_accepted(42))]
|
||||
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
impl<T> Baz for T where T: Send {}
|
||||
|
||||
fn main() {}
|
@ -1,17 +0,0 @@
|
||||
#![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
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
error[E0277]: the trait bound `u8: Bar` is not satisfied
|
||||
--> $DIR/feature-gate-do_not_recommend.rs:15: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:12: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`.
|
@ -1,5 +1,5 @@
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:4:1
|
||||
--> $DIR/incorrect-locations.rs:6:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,46 +7,52 @@ LL | #[diagnostic::do_not_recommend]
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:8:1
|
||||
--> $DIR/incorrect-locations.rs:10:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:12:1
|
||||
--> $DIR/incorrect-locations.rs:14:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:16:1
|
||||
--> $DIR/incorrect-locations.rs:18:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:20:1
|
||||
--> $DIR/incorrect-locations.rs:22:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:24:1
|
||||
--> $DIR/incorrect-locations.rs:26:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:28:1
|
||||
--> $DIR/incorrect-locations.rs:30:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:32:1
|
||||
--> $DIR/incorrect-locations.rs:34:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: 8 warnings emitted
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:38:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: 9 warnings emitted
|
||||
|
@ -0,0 +1,58 @@
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:6:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[warn(unknown_or_malformed_diagnostic_attributes)]` on by default
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:10:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:14:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:18:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:22:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:26:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:30:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:34:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` can only be placed on trait implementations
|
||||
--> $DIR/incorrect-locations.rs:38:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: 9 warnings emitted
|
||||
|
@ -1,5 +1,7 @@
|
||||
//@ check-pass
|
||||
#![feature(do_not_recommend)]
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
|
||||
@ -17,6 +19,10 @@ type Type = ();
|
||||
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
|
||||
enum Enum {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
|
||||
impl Enum {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
//~^WARN `#[diagnostic::do_not_recommend]` can only be placed
|
||||
extern "C" {}
|
||||
|
@ -0,0 +1,15 @@
|
||||
error[E0277]: the trait bound `(): Root` is not satisfied
|
||||
--> $DIR/nested.rs:21:18
|
||||
|
|
||||
LL | needs_root::<()>();
|
||||
| ^^ the trait `Root` is not implemented for `()`
|
||||
|
|
||||
note: required by a bound in `needs_root`
|
||||
--> $DIR/nested.rs:18:18
|
||||
|
|
||||
LL | fn needs_root<T: Root>() {}
|
||||
| ^^^^ required by this bound in `needs_root`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,15 @@
|
||||
error[E0277]: the trait bound `(): Root` is not satisfied
|
||||
--> $DIR/nested.rs:21:18
|
||||
|
|
||||
LL | needs_root::<()>();
|
||||
| ^^ the trait `Root` is not implemented for `()`
|
||||
|
|
||||
note: required by a bound in `needs_root`
|
||||
--> $DIR/nested.rs:18:18
|
||||
|
|
||||
LL | fn needs_root<T: Root>() {}
|
||||
| ^^^^ required by this bound in `needs_root`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
23
tests/ui/diagnostic_namespace/do_not_recommend/nested.rs
Normal file
23
tests/ui/diagnostic_namespace/do_not_recommend/nested.rs
Normal file
@ -0,0 +1,23 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
trait Root {}
|
||||
trait DontRecommend {}
|
||||
trait Other {}
|
||||
trait Child {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
impl<T> Root for T where T: DontRecommend {}
|
||||
|
||||
impl<T> DontRecommend for T where T: Other {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
impl<T> Other for T where T: Child {}
|
||||
|
||||
fn needs_root<T: Root>() {}
|
||||
|
||||
fn main() {
|
||||
needs_root::<()>();
|
||||
//~^ ERROR the trait bound `(): Root` is not satisfied
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
error[E0277]: the trait bound `*mut (): Foo` is not satisfied
|
||||
--> $DIR/simple.rs:17:17
|
||||
--> $DIR/simple.rs:15:17
|
||||
|
|
||||
LL | needs_foo::<*mut ()>();
|
||||
| ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
|
||||
|
|
||||
note: required by a bound in `needs_foo`
|
||||
--> $DIR/simple.rs:12:17
|
||||
--> $DIR/simple.rs:10:17
|
||||
|
|
||||
LL | fn needs_foo<T: Foo>() {}
|
||||
| ^^^ required by this bound in `needs_foo`
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0277]: the trait bound `*mut (): Foo` is not satisfied
|
||||
--> $DIR/simple.rs:17:17
|
||||
--> $DIR/simple.rs:15:17
|
||||
|
|
||||
LL | needs_foo::<*mut ()>();
|
||||
| ^^^^^^^ the trait `Foo` is not implemented for `*mut ()`
|
||||
|
|
||||
note: required by a bound in `needs_foo`
|
||||
--> $DIR/simple.rs:12:17
|
||||
--> $DIR/simple.rs:10:17
|
||||
|
|
||||
LL | fn needs_foo<T: Foo>() {}
|
||||
| ^^^ required by this bound in `needs_foo`
|
||||
|
@ -2,8 +2,6 @@
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(do_not_recommend)]
|
||||
|
||||
trait Foo {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0277]: the trait bound `(): Root` is not satisfied
|
||||
--> $DIR/stacked.rs:19:18
|
||||
--> $DIR/stacked.rs:17:18
|
||||
|
|
||||
LL | needs_root::<()>();
|
||||
| ^^ the trait `Root` is not implemented for `()`
|
||||
|
|
||||
note: required by a bound in `needs_root`
|
||||
--> $DIR/stacked.rs:16:18
|
||||
--> $DIR/stacked.rs:14:18
|
||||
|
|
||||
LL | fn needs_root<T: Root>() {}
|
||||
| ^^^^ required by this bound in `needs_root`
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0277]: the trait bound `(): Root` is not satisfied
|
||||
--> $DIR/stacked.rs:19:18
|
||||
--> $DIR/stacked.rs:17:18
|
||||
|
|
||||
LL | needs_root::<()>();
|
||||
| ^^ the trait `Root` is not implemented for `()`
|
||||
|
|
||||
note: required by a bound in `needs_root`
|
||||
--> $DIR/stacked.rs:16:18
|
||||
--> $DIR/stacked.rs:14:18
|
||||
|
|
||||
LL | fn needs_root<T: Root>() {}
|
||||
| ^^^^ required by this bound in `needs_root`
|
||||
|
@ -2,8 +2,6 @@
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(do_not_recommend)]
|
||||
|
||||
trait Root {}
|
||||
trait DontRecommend {}
|
||||
trait Other {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
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(());
|
||||
| ----- ^^ the trait `Foo` is not implemented for `()`
|
||||
@ -8,7 +8,7 @@ LL | check(());
|
||||
|
|
||||
= help: the trait `Foo` is implemented for `i32`
|
||||
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) {}
|
||||
| ^^^ required by this bound in `check`
|
||||
|
@ -1,5 +1,5 @@
|
||||
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(());
|
||||
| ----- ^^ the trait `Foo` is not implemented for `()`
|
||||
@ -8,7 +8,7 @@ LL | check(());
|
||||
|
|
||||
= help: the trait `Foo` is implemented for `i32`
|
||||
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) {}
|
||||
| ^^^ required by this bound in `check`
|
||||
|
@ -2,8 +2,6 @@
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(do_not_recommend)]
|
||||
|
||||
trait Foo {}
|
||||
|
||||
#[diagnostic::do_not_recommend]
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0277]: Very important message!
|
||||
--> $DIR/type_mismatch.rs:25:14
|
||||
--> $DIR/type_mismatch.rs:23:14
|
||||
|
|
||||
LL | verify::<u8>();
|
||||
| ^^ the trait `TheImportantOne` is not implemented for `u8`
|
||||
|
|
||||
note: required by a bound in `verify`
|
||||
--> $DIR/type_mismatch.rs:22:14
|
||||
--> $DIR/type_mismatch.rs:20:14
|
||||
|
|
||||
LL | fn verify<T: TheImportantOne>() {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `verify`
|
||||
|
@ -1,11 +1,11 @@
|
||||
error[E0277]: Very important message!
|
||||
--> $DIR/type_mismatch.rs:25:14
|
||||
--> $DIR/type_mismatch.rs:23:14
|
||||
|
|
||||
LL | verify::<u8>();
|
||||
| ^^ the trait `TheImportantOne` is not implemented for `u8`
|
||||
|
|
||||
note: required by a bound in `verify`
|
||||
--> $DIR/type_mismatch.rs:22:14
|
||||
--> $DIR/type_mismatch.rs:20:14
|
||||
|
|
||||
LL | fn verify<T: TheImportantOne>() {}
|
||||
| ^^^^^^^^^^^^^^^ required by this bound in `verify`
|
||||
|
@ -2,8 +2,6 @@
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(do_not_recommend)]
|
||||
|
||||
#[diagnostic::on_unimplemented(message = "Very important message!")]
|
||||
trait TheImportantOne {}
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
#![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() {}
|
@ -1,14 +0,0 @@
|
||||
error: unknown diagnostic attribute
|
||||
--> $DIR/unstable-feature.rs:4:15
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/unstable-feature.rs:1:9
|
||||
|
|
||||
LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -0,0 +1,10 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/with_lifetime.rs:17:5
|
||||
|
|
||||
LL | fn foo<'a>(a: &'a ()) {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | needs_root::<&'a ()>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -0,0 +1,10 @@
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/with_lifetime.rs:17:5
|
||||
|
|
||||
LL | fn foo<'a>(a: &'a ()) {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | needs_root::<&'a ()>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -0,0 +1,23 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
trait Root {}
|
||||
trait DontRecommend {}
|
||||
|
||||
impl<T> Root for T where T: DontRecommend {}
|
||||
|
||||
// this has no effect yet for resolving the trait error below
|
||||
#[diagnostic::do_not_recommend]
|
||||
impl<T> DontRecommend for &'static T {}
|
||||
|
||||
fn needs_root<T: Root>() {}
|
||||
|
||||
fn foo<'a>(a: &'a ()) {
|
||||
needs_root::<&'a ()>();
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(&());
|
||||
}
|
Loading…
Reference in New Issue
Block a user