about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTyler Mandry <tmandry@gmail.com>2019-10-11 15:09:58 -0700
committerGitHub <noreply@github.com>2019-10-11 15:09:58 -0700
commit811bd38ae1f183981e5ec1dc1fe096bd17929825 (patch)
tree530717690caef362c49aaaa7daedab0faeea48d7
parent976a57a4af70039223559d371e300da035813583 (diff)
parentc97d71538a3f91cad1c530d7ba4456aa595122aa (diff)
downloadrust-811bd38ae1f183981e5ec1dc1fe096bd17929825.tar.gz
rust-811bd38ae1f183981e5ec1dc1fe096bd17929825.zip
Rollup merge of #65289 - varkor:issue-65284, r=estebank
Fix suggested bound addition diagnostic

Fixes #65284.
-rw-r--r--src/librustc_typeck/check/method/suggest.rs36
-rw-r--r--src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs11
-rw-r--r--src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr15
3 files changed, 41 insertions, 21 deletions
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index ebeb9ba25c6..96cc5aa1dc2 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -809,31 +809,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         // Get the `hir::Param` to verify whether it already has any bounds.
                         // We do this to avoid suggesting code that ends up as `T: FooBar`,
                         // instead we suggest `T: Foo + Bar` in that case.
-                        let mut has_bounds = false;
+                        let mut has_bounds = None;
                         let mut impl_trait = false;
                         if let Node::GenericParam(ref param) = hir.get(id) {
-                            match param.kind {
-                                hir::GenericParamKind::Type { synthetic: Some(_), .. } => {
-                                    // We've found `fn foo(x: impl Trait)` instead of
-                                    // `fn foo<T>(x: T)`. We want to suggest the correct
-                                    // `fn foo(x: impl Trait + TraitBound)` instead of
-                                    // `fn foo<T: TraitBound>(x: T)`. (#63706)
-                                    impl_trait = true;
-                                    has_bounds = param.bounds.len() > 1;
-                                }
-                                _ => {
-                                    has_bounds = !param.bounds.is_empty();
-                                }
+                            let kind = &param.kind;
+                            if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = kind {
+                                // We've found `fn foo(x: impl Trait)` instead of
+                                // `fn foo<T>(x: T)`. We want to suggest the correct
+                                // `fn foo(x: impl Trait + TraitBound)` instead of
+                                // `fn foo<T: TraitBound>(x: T)`. (See #63706.)
+                                impl_trait = true;
+                                has_bounds = param.bounds.get(1);
+                            } else {
+                                has_bounds = param.bounds.get(0);
                             }
                         }
                         let sp = hir.span(id);
-                        // `sp` only covers `T`, change it so that it covers
-                        // `T:` when appropriate
-                        let sp = if has_bounds {
-                            sp.to(self.tcx
-                                .sess
-                                .source_map()
-                                .next_point(self.tcx.sess.source_map().next_point(sp)))
+                        // `sp` only covers `T`, change it so that it covers `T:` when appropriate.
+                        let sp = if let Some(first_bound) = has_bounds {
+                            sp.until(first_bound.span())
                         } else {
                             sp
                         };
@@ -849,7 +843,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 param,
                                 if impl_trait { " +" } else { ":" },
                                 self.tcx.def_path_str(t.def_id),
-                                if has_bounds { " +"} else { "" },
+                                if has_bounds.is_some() { " + " } else { "" },
                             )),
                             Applicability::MaybeIncorrect,
                         );
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
new file mode 100644
index 00000000000..e0eaafdfc2f
--- /dev/null
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs
@@ -0,0 +1,11 @@
+trait Foo {
+    fn foo(&self);
+}
+
+trait Bar {}
+
+fn do_stuff<T : Bar>(t : T) {
+    t.foo() //~ ERROR no method named `foo` found for type `T` in the current scope
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
new file mode 100644
index 00000000000..24bf60abf6a
--- /dev/null
+++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `foo` found for type `T` in the current scope
+  --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7
+   |
+LL |     t.foo()
+   |       ^^^ method not found in `T`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `foo`, perhaps you need to restrict type parameter `T` with it:
+   |
+LL | fn do_stuff<T: Foo + Bar>(t : T) {
+   |             ^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.