]> git.lizzy.rs Git - rust.git/commitdiff
Do not incorrectly suggest restricting implied bounds
authorEsteban Küber <esteban@kuber.com.ar>
Fri, 13 Jan 2023 20:50:34 +0000 (20:50 +0000)
committerEsteban Küber <esteban@kuber.com.ar>
Fri, 13 Jan 2023 20:50:34 +0000 (20:50 +0000)
When we have already suggested bounds that imply the about to be
suggested bound, skip them.

compiler/rustc_hir_typeck/src/method/suggest.rs
tests/ui/missing-trait-bounds/issue-35677.fixed
tests/ui/missing-trait-bounds/issue-35677.stderr

index 338fabca3891984ad5c200e073ac86e751ffc499..f49fde04e8444f0b0ac09600d3c9ea31fad1691a 100644 (file)
@@ -505,19 +505,21 @@ pub fn report_no_match_method_error(
                             }
                             _ => None,
                         };
-                        if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
-                            if let Some(g) = kind.generics() {
-                                let key = (
-                                    g.tail_span_for_predicate_suggestion(),
-                                    g.add_where_or_trailing_comma(),
-                                );
-                                type_params
-                                    .entry(key)
-                                    .or_insert_with(FxHashSet::default)
-                                    .insert(obligation.to_owned());
-                            }
+                        if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
+                            && let Some(g) = kind.generics()
+                        {
+                            let key = (
+                                g.tail_span_for_predicate_suggestion(),
+                                g.add_where_or_trailing_comma(),
+                            );
+                            type_params
+                                .entry(key)
+                                .or_insert_with(FxHashSet::default)
+                                .insert(obligation.to_owned());
+                            return true;
                         }
                     }
+                    false
                 };
             let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
                 let msg = format!(
@@ -732,19 +734,39 @@ pub fn report_no_match_method_error(
                 unsatisfied_bounds = true;
             }
 
+            let mut suggested_bounds = FxHashSet::default();
             // The requirements that didn't have an `impl` span to show.
             let mut bound_list = unsatisfied_predicates
                 .iter()
                 .filter_map(|(pred, parent_pred, _cause)| {
+                    let mut suggested = false;
                     format_pred(*pred).map(|(p, self_ty)| {
-                        collect_type_param_suggestions(self_ty, *pred, &p);
+                        if let Some(parent) = parent_pred && suggested_bounds.contains(parent) {
+                            // We don't suggest `PartialEq` when we already suggest `Eq`.
+                        } else if !suggested_bounds.contains(pred) {
+                            if collect_type_param_suggestions(self_ty, *pred, &p) {
+                                suggested = true;
+                                suggested_bounds.insert(pred);
+                            }
+                        }
                         (
                             match parent_pred {
                                 None => format!("`{}`", &p),
                                 Some(parent_pred) => match format_pred(*parent_pred) {
                                     None => format!("`{}`", &p),
                                     Some((parent_p, _)) => {
-                                        collect_type_param_suggestions(self_ty, *parent_pred, &p);
+                                        if !suggested
+                                            && !suggested_bounds.contains(pred)
+                                            && !suggested_bounds.contains(parent_pred)
+                                        {
+                                            if collect_type_param_suggestions(
+                                                self_ty,
+                                                *parent_pred,
+                                                &p,
+                                            ) {
+                                                suggested_bounds.insert(pred);
+                                            }
+                                        }
                                         format!("`{}`\nwhich is required by `{}`", p, parent_p)
                                     }
                                 },
index c76b6bc9c1851c770abe03b3c1f77e9875dc1555..08174d8d8d53ad476ed5212c055012b1a15136ea 100644 (file)
@@ -3,7 +3,7 @@
 use std::collections::HashSet;
 use std::hash::Hash;
 
-fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash, T: PartialEq {
+fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash {
     this.is_subset(other)
     //~^ ERROR the method
 }
index 067b10b873abfb7aaca25504846c1d9fe07911f2..05d3de80d8449b4b8e7da07684b29174989854a5 100644 (file)
@@ -11,8 +11,8 @@ LL |     this.is_subset(other)
            `T: Hash`
 help: consider restricting the type parameters to satisfy the trait bounds
    |
-LL | fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash, T: PartialEq {
-   |                                                                ++++++++++++++++++++++++++++++++++
+LL | fn is_subset<T>(this: &HashSet<T>, other: &HashSet<T>) -> bool where T: Eq, T: Hash {
+   |                                                                ++++++++++++++++++++
 
 error: aborting due to previous error