about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2019-10-11 00:51:36 +0100
committervarkor <github@varkor.com>2019-10-11 00:51:36 +0100
commitc97d71538a3f91cad1c530d7ba4456aa595122aa (patch)
treefc31599006d1373d6f51562404f3fbde934b986c
parent2748a9fd93dd1a00a4521f4f16de5befbf77f6cd (diff)
downloadrust-c97d71538a3f91cad1c530d7ba4456aa595122aa.tar.gz
rust-c97d71538a3f91cad1c530d7ba4456aa595122aa.zip
Fix issue 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 b4b84b61fd6..80cdcf566be 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -785,31 +785,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
                         };
@@ -825,7 +819,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`.