diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 53024d97c3b13..440e7e5d0e314 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -743,8 +743,21 @@ 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(_), .. } => { + // 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; + } + _ => { + has_bounds = !param.bounds.is_empty(); + } + } } let sp = hir.span(id); // `sp` only covers `T`, change it so that it covers @@ -765,8 +778,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`.