about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2020-02-02 17:55:11 +0900
committerYuki Okushi <huyuumi.dev@gmail.com>2020-02-02 18:38:23 +0900
commit56ad8bcfe0025618d35c8479797bca5d05e81099 (patch)
treea66f1245757bdd5be7a691dd561c4bdffe92eb0c
parentbc4a3390648dffd88e6d69d06e6d49cf3981e713 (diff)
downloadrust-56ad8bcfe0025618d35c8479797bca5d05e81099.tar.gz
rust-56ad8bcfe0025618d35c8479797bca5d05e81099.zip
Do not suggest duplicate bounds
-rw-r--r--src/librustc_typeck/check/method/suggest.rs42
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-bounds.rs11
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-bounds.stderr11
-rw-r--r--src/test/ui/issues/issue-39559.stderr4
-rw-r--r--src/test/ui/span/issue-7575.stderr13
5 files changed, 49 insertions, 32 deletions
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index e9942fad3bc..490c69b5536 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -853,26 +853,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 } else {
                                     sp
                                 };
-                                // FIXME: contrast `t.def_id` against `param.bounds` to not suggest
-                                // traits already there. That can happen when the cause is that
-                                // we're in a const scope or associated function used as a method.
-                                err.span_suggestions(
-                                    sp,
-                                    &message(format!(
-                                        "restrict type parameter `{}` with",
-                                        param.name.ident(),
-                                    )),
-                                    candidates.iter().map(|t| {
-                                        format!(
-                                            "{}{} {}{}",
+                                let trait_def_ids: FxHashSet<DefId> = param
+                                    .bounds
+                                    .iter()
+                                    .filter_map(|bound| bound.trait_def_id())
+                                    .collect();
+                                if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
+                                    err.span_suggestions(
+                                        sp,
+                                        &message(format!(
+                                            "restrict type parameter `{}` with",
                                             param.name.ident(),
-                                            if impl_trait { " +" } else { ":" },
-                                            self.tcx.def_path_str(t.def_id),
-                                            if has_bounds.is_some() { " + " } else { "" },
-                                        )
-                                    }),
-                                    Applicability::MaybeIncorrect,
-                                );
+                                        )),
+                                        candidates.iter().map(|t| {
+                                            format!(
+                                                "{}{} {}{}",
+                                                param.name.ident(),
+                                                if impl_trait { " +" } else { ":" },
+                                                self.tcx.def_path_str(t.def_id),
+                                                if has_bounds.is_some() { " + " } else { "" },
+                                            )
+                                        }),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
                                 suggested = true;
                             }
                             Node::Item(hir::Item {
diff --git a/src/test/ui/associated-item/associated-item-duplicate-bounds.rs b/src/test/ui/associated-item/associated-item-duplicate-bounds.rs
new file mode 100644
index 00000000000..bec922b0721
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-duplicate-bounds.rs
@@ -0,0 +1,11 @@
+trait Adapter {
+    const LINKS: usize;
+}
+
+struct Foo<A: Adapter> {
+    adapter: A,
+    links: [u32; A::LINKS], // Shouldn't suggest bounds already there.
+    //~^ ERROR: no associated item named `LINKS` found
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr b/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr
new file mode 100644
index 00000000000..ff1ad4c006e
--- /dev/null
+++ b/src/test/ui/associated-item/associated-item-duplicate-bounds.stderr
@@ -0,0 +1,11 @@
+error[E0599]: no associated item named `LINKS` found for type parameter `A` in the current scope
+  --> $DIR/associated-item-duplicate-bounds.rs:7:21
+   |
+LL |     links: [u32; A::LINKS], // Shouldn't suggest bounds already there.
+   |                     ^^^^^ associated item not found in `A`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/issues/issue-39559.stderr b/src/test/ui/issues/issue-39559.stderr
index 0554b232c24..5e8d487f416 100644
--- a/src/test/ui/issues/issue-39559.stderr
+++ b/src/test/ui/issues/issue-39559.stderr
@@ -5,10 +5,6 @@ LL |     entries: [T; D::dim()],
    |                     ^^^ function or associated item not found in `D`
    |
    = help: items from traits can only be used if the type parameter is bounded by the trait
-help: the following trait defines an item `dim`, perhaps you need to restrict type parameter `D` with it:
-   |
-LL | pub struct Vector<T, D: Dim + Dim> {
-   |                      ^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index eb85be039ba..89b36848a28 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -61,7 +61,10 @@ error[E0599]: no method named `is_str` found for type parameter `T` in the curre
   --> $DIR/issue-7575.rs:70:7
    |
 LL |     t.is_str()
-   |       ^^^^^^ this is an associated function, not a method
+   |     --^^^^^^--
+   |     | |
+   |     | this is an associated function, not a method
+   |     help: disambiguate the method call for the candidate: `ManyImplTrait::is_str(t)`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
 note: the candidate is defined in the trait `ManyImplTrait`
@@ -70,14 +73,6 @@ note: the candidate is defined in the trait `ManyImplTrait`
 LL |     fn is_str() -> bool {
    |     ^^^^^^^^^^^^^^^^^^^
    = help: items from traits can only be used if the type parameter is bounded by the trait
-help: disambiguate the method call for the candidate
-   |
-LL |     ManyImplTrait::is_str(t)
-   |
-help: the following trait defines an item `is_str`, perhaps you need to restrict type parameter `T` with it:
-   |
-LL | fn param_bound<T: ManyImplTrait + ManyImplTrait>(t: T) -> bool {
-   |                ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors