diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 964aa8426ea..9fd3a170ece 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -329,7 +329,33 @@ fn compare_predicate_entailment<'tcx>(
);
}
TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
- if let Some(trait_ty) = trait_sig.inputs().get(*i) {
+ if trait_sig.inputs().len() == *i {
+ // Suggestion to change output type. We do not suggest in `async` functions
+ // to avoid complex logic or incorrect output.
+ let impl_m_hir_id =
+ tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
+ match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
+ ImplItemKind::Fn(ref sig, _)
+ if sig.header.asyncness == hir::IsAsync::NotAsync =>
+ {
+ let (span, sugg) = match sig.decl.output {
+ hir::FnRetTy::DefaultReturn(sp) => {
+ (sp, format!(" -> {} ", trait_sig.output()))
+ }
+ hir::FnRetTy::Return(hir_ty) => {
+ (hir_ty.span, trait_sig.output().to_string())
+ }
+ };
+ diag.span_suggestion(
+ span,
+ "change the output type to match the trait",
+ sugg,
+ Applicability::MachineApplicable,
+ );
+ }
+ _ => {}
+ };
+ } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
diag.span_suggestion(
impl_err_span,
"change the parameter type to match the trait",
diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr
index 920f8322813..3c7dc1fc3c9 100644
--- a/src/test/ui/associated-types/defaults-specialization.stderr
+++ b/src/test/ui/associated-types/defaults-specialization.stderr
@@ -15,7 +15,10 @@ LL | fn make() -> Self::Ty {
| -------- type in trait
...
LL | fn make() -> u8 { 0 }
- | ^^ expected associated type, found `u8`
+ | ^^
+ | |
+ | expected associated type, found `u8`
+ | help: change the output type to match the trait: ` as Tr>::Ty`
|
= note: expected fn pointer `fn() -> as Tr>::Ty`
found fn pointer `fn() -> u8`
@@ -30,7 +33,10 @@ LL | default type Ty = bool;
| ----------------------- expected this associated type
LL |
LL | fn make() -> bool { true }
- | ^^^^ expected associated type, found `bool`
+ | ^^^^
+ | |
+ | expected associated type, found `bool`
+ | help: change the output type to match the trait: ` as Tr>::Ty`
|
= note: expected fn pointer `fn() -> as Tr>::Ty`
found fn pointer `fn() -> bool`
diff --git a/src/test/ui/compare-method/bad-self-type.rs b/src/test/ui/compare-method/bad-self-type.rs
index 9eb978664bf..f42a9e49abd 100644
--- a/src/test/ui/compare-method/bad-self-type.rs
+++ b/src/test/ui/compare-method/bad-self-type.rs
@@ -15,9 +15,12 @@ impl Future for MyFuture {
trait T {
fn foo(self);
+ fn bar(self) -> Option<()>;
}
impl T for MyFuture {
fn foo(self: Box) {}
//~^ ERROR method `foo` has an incompatible type for trait
+ fn bar(self) {}
+ //~^ ERROR method `bar` has an incompatible type for trait
}
diff --git a/src/test/ui/compare-method/bad-self-type.stderr b/src/test/ui/compare-method/bad-self-type.stderr
index 4d85ff86df5..74e7c562aa7 100644
--- a/src/test/ui/compare-method/bad-self-type.stderr
+++ b/src/test/ui/compare-method/bad-self-type.stderr
@@ -11,7 +11,7 @@ LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> {
found fn pointer `fn(MyFuture, &mut Context<'_>) -> Poll<_>`
error[E0053]: method `foo` has an incompatible type for trait
- --> $DIR/bad-self-type.rs:21:18
+ --> $DIR/bad-self-type.rs:22:18
|
LL | fn foo(self);
| ---- type in trait
@@ -25,6 +25,21 @@ LL | fn foo(self: Box) {}
= note: expected fn pointer `fn(MyFuture)`
found fn pointer `fn(Box)`
-error: aborting due to 2 previous errors
+error[E0053]: method `bar` has an incompatible type for trait
+ --> $DIR/bad-self-type.rs:24:18
+ |
+LL | fn bar(self) -> Option<()>;
+ | ---------- type in trait
+...
+LL | fn bar(self) {}
+ | ^
+ | |
+ | expected enum `Option`, found `()`
+ | help: change the output type to match the trait: `-> Option<()>`
+ |
+ = note: expected fn pointer `fn(MyFuture) -> Option<()>`
+ found fn pointer `fn(MyFuture)`
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/issues/issue-21332.stderr b/src/test/ui/issues/issue-21332.stderr
index fd132687d71..d92966da17c 100644
--- a/src/test/ui/issues/issue-21332.stderr
+++ b/src/test/ui/issues/issue-21332.stderr
@@ -2,7 +2,10 @@ error[E0053]: method `next` has an incompatible type for trait
--> $DIR/issue-21332.rs:5:27
|
LL | fn next(&mut self) -> Result { Ok(7) }
- | ^^^^^^^^^^^^^^^^ expected enum `Option`, found enum `Result`
+ | ^^^^^^^^^^^^^^^^
+ | |
+ | expected enum `Option`, found enum `Result`
+ | help: change the output type to match the trait: `Option`
|
= note: expected fn pointer `fn(&mut S) -> Option`
found fn pointer `fn(&mut S) -> Result`
diff --git a/src/test/ui/issues/issue-35869.stderr b/src/test/ui/issues/issue-35869.stderr
index c104aa30cb0..71b2a9df095 100644
--- a/src/test/ui/issues/issue-35869.stderr
+++ b/src/test/ui/issues/issue-35869.stderr
@@ -50,7 +50,10 @@ LL | fn qux() -> u8;
| -- type in trait
...
LL | fn qux() -> u16 { 5u16 }
- | ^^^ expected `u8`, found `u16`
+ | ^^^
+ | |
+ | expected `u8`, found `u16`
+ | help: change the output type to match the trait: `u8`
|
= note: expected fn pointer `fn() -> u8`
found fn pointer `fn() -> u16`
diff --git a/src/test/ui/wrong-mul-method-signature.stderr b/src/test/ui/wrong-mul-method-signature.stderr
index 9be07cb1a74..9f8896f01ee 100644
--- a/src/test/ui/wrong-mul-method-signature.stderr
+++ b/src/test/ui/wrong-mul-method-signature.stderr
@@ -26,7 +26,10 @@ error[E0053]: method `mul` has an incompatible type for trait
--> $DIR/wrong-mul-method-signature.rs:52:29
|
LL | fn mul(self, s: f64) -> f64 {
- | ^^^ expected `i32`, found `f64`
+ | ^^^
+ | |
+ | expected `i32`, found `f64`
+ | help: change the output type to match the trait: `i32`
|
= note: expected fn pointer `fn(Vec3, _) -> i32`
found fn pointer `fn(Vec3, _) -> f64`