mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user