From 2d438d6993017ae2b991cd92ea243112e2357c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 22 Aug 2019 10:15:57 -0700 Subject: [PATCH 1/2] Correctly suggest adding bounds to `impl Trait` argument --- src/librustc_typeck/check/method/suggest.rs | 14 +++++++++++-- ...ait-with-missing-trait-bounds-in-arg.fixed | 20 +++++++++++++++++++ ...-trait-with-missing-trait-bounds-in-arg.rs | 20 +++++++++++++++++++ ...it-with-missing-trait-bounds-in-arg.stderr | 15 ++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs create mode 100644 src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 53024d97c3b13..9f4fed23697ab 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -743,8 +743,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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 impl_trait = false; if let Node::GenericParam(ref param) = hir.get(id) { - has_bounds = !param.bounds.is_empty(); + match param.kind { + hir::GenericParamKind::Type { synthetic: Some(_), .. } => { + impl_trait = true; // #63706 + has_bounds = param.bounds.len() > 1; + } + _ => { + has_bounds = !param.bounds.is_empty(); + } + } } let sp = hir.span(id); // `sp` only covers `T`, change it so that it covers @@ -765,8 +774,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp, &msg[..], candidates.iter().map(|t| format!( - "{}: {}{}", + "{}{} {}{}", param, + if impl_trait { " +" } else { ":" }, self.tcx.def_path_str(t.def_id), if has_bounds { " +"} else { "" }, )), diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed new file mode 100644 index 0000000000000..5109511f95a6b --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.fixed @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo + Bar) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs new file mode 100644 index 0000000000000..cd05b77386192 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.rs @@ -0,0 +1,20 @@ +// run-rustfix + +trait Foo {} + +trait Bar { + fn hello(&self) {} +} + +struct S; + +impl Foo for S {} +impl Bar for S {} + +fn test(foo: impl Foo) { + foo.hello(); //~ ERROR E0599 +} + +fn main() { + test(S); +} diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr new file mode 100644 index 0000000000000..48c2503e8eb32 --- /dev/null +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `hello` found for type `impl Foo` in the current scope + --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9 + | +LL | foo.hello(); + | ^^^^^ + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `hello`, perhaps you need to restrict type parameter `impl Foo` with it: + | +LL | fn test(foo: impl Foo + Bar) { + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 055f7e2ec23f36e522e318a64eab414caba55e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Aug 2019 13:45:18 -0700 Subject: [PATCH 2/2] Extend comment --- src/librustc_typeck/check/method/suggest.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9f4fed23697ab..440e7e5d0e314 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -747,7 +747,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Node::GenericParam(ref param) = hir.get(id) { match param.kind { hir::GenericParamKind::Type { synthetic: Some(_), .. } => { - impl_trait = true; // #63706 + // We've found `fn foo(x: impl Trait)` instead of + // `fn foo(x: T)`. We want to suggest the correct + // `fn foo(x: impl Trait + TraitBound)` instead of + // `fn foo(x: T)`. (#63706) + impl_trait = true; has_bounds = param.bounds.len() > 1; } _ => {