Allows #[diagnostic::do_not_recommend]
to supress trait impls in suggestions as well
This commit changes the error reporting mechanism for not implemented traits to skip impl marked as `#[diagnostic::do_not_recommend]` in the help part of the error message ("the following other types implement trait `Foo`:"). The main use case here is to allow crate authors to skip non-meaningful confusing suggestions. A common example for this are fully generic impls on tuples.
This commit is contained in:
parent
e1f45a1442
commit
27d5db166e
4 changed files with 80 additions and 0 deletions
|
@ -1776,6 +1776,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// we filter before checking if `impl_candidates` is empty
|
||||||
|
// to get the fallback solution if we filtered out any impls
|
||||||
|
let impl_candidates = impl_candidates
|
||||||
|
.into_iter()
|
||||||
|
.cloned()
|
||||||
|
.filter(|cand| {
|
||||||
|
!self.tcx.has_attrs_with_path(
|
||||||
|
cand.impl_def_id,
|
||||||
|
&[sym::diagnostic, sym::do_not_recommend],
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let def_id = trait_ref.def_id();
|
let def_id = trait_ref.def_id();
|
||||||
if impl_candidates.is_empty() {
|
if impl_candidates.is_empty() {
|
||||||
if self.tcx.trait_is_auto(def_id)
|
if self.tcx.trait_is_auto(def_id)
|
||||||
|
@ -1788,6 +1801,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||||
let mut impl_candidates: Vec<_> = self
|
let mut impl_candidates: Vec<_> = self
|
||||||
.tcx
|
.tcx
|
||||||
.all_impls(def_id)
|
.all_impls(def_id)
|
||||||
|
// ignore `do_not_recommend` items
|
||||||
|
.filter(|def_id| {
|
||||||
|
!self
|
||||||
|
.tcx
|
||||||
|
.has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend])
|
||||||
|
})
|
||||||
// Ignore automatically derived impls and `!Trait` impls.
|
// Ignore automatically derived impls and `!Trait` impls.
|
||||||
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
|
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
|
||||||
.filter_map(|header| {
|
.filter_map(|header| {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
error[E0277]: the trait bound `(): Foo` is not satisfied
|
||||||
|
--> $DIR/supress_suggestions_in_help.rs:23:11
|
||||||
|
|
|
||||||
|
LL | check(());
|
||||||
|
| ----- ^^ the trait `Foo` is not implemented for `()`
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
= help: the trait `Foo` is implemented for `i32`
|
||||||
|
note: required by a bound in `check`
|
||||||
|
--> $DIR/supress_suggestions_in_help.rs:20: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`.
|
|
@ -0,0 +1,18 @@
|
||||||
|
error[E0277]: the trait bound `(): Foo` is not satisfied
|
||||||
|
--> $DIR/supress_suggestions_in_help.rs:23:11
|
||||||
|
|
|
||||||
|
LL | check(());
|
||||||
|
| ----- ^^ the trait `Foo` is not implemented for `()`
|
||||||
|
| |
|
||||||
|
| required by a bound introduced by this call
|
||||||
|
|
|
||||||
|
= help: the trait `Foo` is implemented for `i32`
|
||||||
|
note: required by a bound in `check`
|
||||||
|
--> $DIR/supress_suggestions_in_help.rs:20: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`.
|
|
@ -0,0 +1,25 @@
|
||||||
|
//@ revisions: current next
|
||||||
|
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
|
#![feature(do_not_recommend)]
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue