Skip to content

Commit 22a0e4f

Browse files
committed
Do not incorrectly suggest restricting implied bounds
When we have already suggested bounds that imply the about to be suggested bound, skip them.
1 parent 81ba427 commit 22a0e4f

File tree

3 files changed

+38
-16
lines changed

3 files changed

+38
-16
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+35-13
Original file line numberDiff line numberDiff line change
@@ -505,19 +505,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
505505
}
506506
_ => None,
507507
};
508-
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
509-
if let Some(g) = kind.generics() {
510-
let key = (
511-
g.tail_span_for_predicate_suggestion(),
512-
g.add_where_or_trailing_comma(),
513-
);
514-
type_params
515-
.entry(key)
516-
.or_insert_with(FxHashSet::default)
517-
.insert(obligation.to_owned());
518-
}
508+
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
509+
&& let Some(g) = kind.generics()
510+
{
511+
let key = (
512+
g.tail_span_for_predicate_suggestion(),
513+
g.add_where_or_trailing_comma(),
514+
);
515+
type_params
516+
.entry(key)
517+
.or_insert_with(FxHashSet::default)
518+
.insert(obligation.to_owned());
519+
return true;
519520
}
520521
}
522+
false
521523
};
522524
let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
523525
let msg = format!(
@@ -732,19 +734,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
732734
unsatisfied_bounds = true;
733735
}
734736

737+
let mut suggested_bounds = FxHashSet::default();
735738
// The requirements that didn't have an `impl` span to show.
736739
let mut bound_list = unsatisfied_predicates
737740
.iter()
738741
.filter_map(|(pred, parent_pred, _cause)| {
742+
let mut suggested = false;
739743
format_pred(*pred).map(|(p, self_ty)| {
740-
collect_type_param_suggestions(self_ty, *pred, &p);
744+
if let Some(parent) = parent_pred && suggested_bounds.contains(parent) {
745+
// We don't suggest `PartialEq` when we already suggest `Eq`.
746+
} else if !suggested_bounds.contains(pred) {
747+
if collect_type_param_suggestions(self_ty, *pred, &p) {
748+
suggested = true;
749+
suggested_bounds.insert(pred);
750+
}
751+
}
741752
(
742753
match parent_pred {
743754
None => format!("`{}`", &p),
744755
Some(parent_pred) => match format_pred(*parent_pred) {
745756
None => format!("`{}`", &p),
746757
Some((parent_p, _)) => {
747-
collect_type_param_suggestions(self_ty, *parent_pred, &p);
758+
if !suggested
759+
&& !suggested_bounds.contains(pred)
760+
&& !suggested_bounds.contains(parent_pred)
761+
{
762+
if collect_type_param_suggestions(
763+
self_ty,
764+
*parent_pred,
765+
&p,
766+
) {
767+
suggested_bounds.insert(pred);
768+
}
769+
}
748770
format!("`{}`\nwhich is required by `{}`", p, parent_p)
749771
}
750772
},

tests/ui/missing-trait-bounds/issue-35677.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::collections::HashSet;
44
use std::hash::Hash;
55

6-
fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash, T: PartialEq {
6+
fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash {
77
this.is_subset(other)
88
//~^ ERROR the method
99
}

tests/ui/missing-trait-bounds/issue-35677.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ LL | this.is_subset(other)
1111
`T: Hash`
1212
help: consider restricting the type parameters to satisfy the trait bounds
1313
|
14-
LL | fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash, T: PartialEq {
15-
| ++++++++++++++++++++++++++++++++++
14+
LL | fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash {
15+
| ++++++++++++++++++++
1616

1717
error: aborting due to previous error
1818

0 commit comments

Comments
 (0)