Skip to content

Commit 27d5db1

Browse files
committed
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.
1 parent e1f45a1 commit 27d5db1

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17761776
true
17771777
};
17781778

1779+
// we filter before checking if `impl_candidates` is empty
1780+
// to get the fallback solution if we filtered out any impls
1781+
let impl_candidates = impl_candidates
1782+
.into_iter()
1783+
.cloned()
1784+
.filter(|cand| {
1785+
!self.tcx.has_attrs_with_path(
1786+
cand.impl_def_id,
1787+
&[sym::diagnostic, sym::do_not_recommend],
1788+
)
1789+
})
1790+
.collect::<Vec<_>>();
1791+
17791792
let def_id = trait_ref.def_id();
17801793
if impl_candidates.is_empty() {
17811794
if self.tcx.trait_is_auto(def_id)
@@ -1788,6 +1801,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17881801
let mut impl_candidates: Vec<_> = self
17891802
.tcx
17901803
.all_impls(def_id)
1804+
// ignore `do_not_recommend` items
1805+
.filter(|def_id| {
1806+
!self
1807+
.tcx
1808+
.has_attrs_with_path(*def_id, &[sym::diagnostic, sym::do_not_recommend])
1809+
})
17911810
// Ignore automatically derived impls and `!Trait` impls.
17921811
.filter_map(|def_id| self.tcx.impl_trait_header(def_id))
17931812
.filter_map(|header| {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: the trait bound `(): Foo` is not satisfied
2+
--> $DIR/supress_suggestions_in_help.rs:23:11
3+
|
4+
LL | check(());
5+
| ----- ^^ the trait `Foo` is not implemented for `()`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Foo` is implemented for `i32`
10+
note: required by a bound in `check`
11+
--> $DIR/supress_suggestions_in_help.rs:20:18
12+
|
13+
LL | fn check(a: impl Foo) {}
14+
| ^^^ required by this bound in `check`
15+
16+
error: aborting due to 1 previous error
17+
18+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: the trait bound `(): Foo` is not satisfied
2+
--> $DIR/supress_suggestions_in_help.rs:23:11
3+
|
4+
LL | check(());
5+
| ----- ^^ the trait `Foo` is not implemented for `()`
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Foo` is implemented for `i32`
10+
note: required by a bound in `check`
11+
--> $DIR/supress_suggestions_in_help.rs:20:18
12+
|
13+
LL | fn check(a: impl Foo) {}
14+
| ^^^ required by this bound in `check`
15+
16+
error: aborting due to 1 previous error
17+
18+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
5+
#![feature(do_not_recommend)]
6+
7+
trait Foo {}
8+
9+
#[diagnostic::do_not_recommend]
10+
impl<A> Foo for (A,) {}
11+
12+
#[diagnostic::do_not_recommend]
13+
impl<A, B> Foo for (A, B) {}
14+
15+
#[diagnostic::do_not_recommend]
16+
impl<A, B, C> Foo for (A, B, C) {}
17+
18+
impl Foo for i32 {}
19+
20+
fn check(a: impl Foo) {}
21+
22+
fn main() {
23+
check(());
24+
//~^ ERROR the trait bound `(): Foo` is not satisfied
25+
}

0 commit comments

Comments
 (0)