diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-07-11 17:01:39 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-11 17:01:39 +0200 |
| commit | a10b4d1463dac935a53441e7cd85fa9df6231a6c (patch) | |
| tree | 944f115d95feff3b55c4d0b4e26e7ccd39a0890e | |
| parent | 73c500b3a759b7fcb70633e091d7a152f797c3cd (diff) | |
| parent | 27d5db166e8e640ab8317cc96b91ffe60270b6c5 (diff) | |
| download | rust-a10b4d1463dac935a53441e7cd85fa9df6231a6c.tar.gz rust-a10b4d1463dac935a53441e7cd85fa9df6231a6c.zip | |
Rollup merge of #127598 - weiznich:diagnostic_do_not_recommend_also_skips_help, r=compiler-errors
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.
Related to https://github.com/rust-lang/rust/issues/51992
r? `@compiler-errors`
4 files changed, 80 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index f7ec5f1ff32..2e6247b4640 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1776,6 +1776,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { 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(); if impl_candidates.is_empty() { if self.tcx.trait_is_auto(def_id) @@ -1788,6 +1801,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut impl_candidates: Vec<_> = self .tcx .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. .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) .filter_map(|header| { diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr new file mode 100644 index 00000000000..629fc59361d --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr @@ -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`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr new file mode 100644 index 00000000000..629fc59361d --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr @@ -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`. diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs new file mode 100644 index 00000000000..ef6f255c351 --- /dev/null +++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.rs @@ -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 +} |
