improve the diagnostics for when a multi-statement closure has no inferred result type.

Previously:

error: generic parameter 'T' could not be inferred
now:
error: unable to infer closure return type in current context

There is still more to do, but this fixes:
<rdar://problem/23570873> QoI: Poor error calling map without being able to infer "U" (closure result inference)
This commit is contained in:
Chris Lattner
2016-07-29 17:48:28 -07:00
parent e7f01c657f
commit 764d0fc371
4 changed files with 54 additions and 12 deletions

View File

@@ -6116,6 +6116,24 @@ static void noteArchetypeSource(const TypeLoc &loc, ArchetypeType *archetype,
}
/// Check the specified closure to see if it is a multi-statement closure with
/// an uninferred type. If so, diagnose the problem with an error and return
/// true.
static bool checkMultistatementClosureForAmbiguity(ClosureExpr *closure,
TypeChecker &tc) {
if (closure->hasSingleExpressionBody() ||
closure->hasExplicitResultType())
return false;
auto closureType = closure->getType()->getAs<AnyFunctionType>();
if (!closureType || !isUnresolvedOrTypeVarType(closureType->getResult()))
return false;
tc.diagnose(closure->getLoc(), diag::cannot_infer_closure_result_type);
return true;
}
/// Emit an error message about an unbound generic parameter existing, and
/// emit notes referring to the target of a diagnostic, e.g., the function
/// or parameter being used.
@@ -6140,6 +6158,21 @@ static void diagnoseUnboundArchetype(Expr *overallExpr,
ND->getDeclaredType());
return;
}
// A very common cause of this diagnostic is a situation where a closure expr
// has no inferred type, due to being a multiline closure. Check to see if
// this is the case and (if so), speculatively diagnose that as the problem.
bool didDiagnose = false;
overallExpr->forEachChildExpr([&](Expr *subExpr) -> Expr*{
auto closure = dyn_cast<ClosureExpr>(subExpr);
if (!didDiagnose && closure)
didDiagnose = checkMultistatementClosureForAmbiguity(closure, tc);
return subExpr;
});
if (didDiagnose) return;
// Otherwise, emit an error message on the expr we have, and emit a note
// about where the archetype came from.
@@ -6225,16 +6258,11 @@ void FailureDiagnosis::diagnoseAmbiguity(Expr *E) {
// Unresolved/Anonymous ClosureExprs are common enough that we should give
// them tailored diagnostics.
if (auto CE = dyn_cast<ClosureExpr>(E->getValueProvidingExpr())) {
auto CFTy = CE->getType()->getAs<AnyFunctionType>();
// If this is a multi-statement closure with no explicit result type, emit
// a note to clue the developer in.
if (!CE->hasExplicitResultType() && CFTy &&
isUnresolvedOrTypeVarType(CFTy->getResult())) {
diagnose(CE->getLoc(), diag::cannot_infer_closure_result_type);
if (checkMultistatementClosureForAmbiguity(CE, CS->getTypeChecker()))
return;
}
diagnose(E->getLoc(), diag::cannot_infer_closure_type)
.highlight(E->getSourceRange());
return;