Auto merge of #84244 - ABouttefeux:closure-return-conflict-suggest, r=estebank

fix incomplete diagnostic notes when closure returns conflicting for genric type

fixes #84128
Correctly report the span on for conflicting return type in closures
This commit is contained in:
bors 2021-04-17 07:17:31 +00:00
commit 080d30235f
4 changed files with 60 additions and 22 deletions

View File

@ -1492,28 +1492,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) {
self.add_impl_trait_explanation(&mut err, cause, fcx, expected, sp, fn_output);
}
if let Some(sp) = fcx.ret_coercion_span.get() {
// If the closure has an explicit return type annotation,
// then a type error may occur at the first return expression we
// see in the closure (if it conflicts with the declared
// return type). Skip adding a note in this case, since it
// would be incorrect.
if !err.span.primary_spans().iter().any(|&span| span == sp) {
let hir = fcx.tcx.hir();
let body_owner = hir.body_owned_by(hir.enclosing_body_owner(fcx.body_id));
if fcx.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) {
err.span_note(
sp,
&format!(
"return type inferred to be `{}` here",
fcx.resolve_vars_if_possible(expected)
),
);
}
}
}
err
}

View File

@ -37,6 +37,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.suggest_missing_parentheses(err, expr);
self.note_need_for_fn_pointer(err, expected, expr_ty);
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
self.report_closure_infered_return_type(err, expected)
}
// Requires that the two types unify, and prints an error message if
@ -1061,4 +1062,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => false,
}
}
// Report the type inferred by the return statement.
fn report_closure_infered_return_type(
&self,
err: &mut DiagnosticBuilder<'_>,
expected: Ty<'tcx>,
) {
if let Some(sp) = self.ret_coercion_span.get() {
// If the closure has an explicit return type annotation,
// then a type error may occur at the first return expression we
// see in the closure (if it conflicts with the declared
// return type). Skip adding a note in this case, since it
// would be incorrect.
if !err.span.primary_spans().iter().any(|&span| span == sp) {
let hir = self.tcx.hir();
let body_owner = hir.body_owned_by(hir.enclosing_body_owner(self.body_id));
if self.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) {
err.span_note(
sp,
&format!(
"return type inferred to be `{}` here",
self.resolve_vars_if_possible(expected)
),
);
}
}
}
}
}

View File

@ -0,0 +1,16 @@
// test for issue 84128
// missing suggestion for similar ADT type with diffetent generic paramenter
// on closure ReturnNoExpression
struct Foo<T>(T);
fn main() {
|| {
if false {
return Foo(0);
}
Foo(())
//~^ ERROR mismatched types [E0308]
};
}

View File

@ -0,0 +1,15 @@
error[E0308]: mismatched types
--> $DIR/issue-84128.rs:13:13
|
LL | Foo(())
| ^^ expected integer, found `()`
|
note: return type inferred to be `{integer}` here
--> $DIR/issue-84128.rs:10:20
|
LL | return Foo(0);
| ^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.