@@ -6330,15 +6330,14 @@ visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E) {
6330
6330
6331
6331
6332
6332
bool FailureDiagnosis::visitClosureExpr (ClosureExpr *CE) {
6333
+ auto contextualType = CS->getContextualType ();
6333
6334
Type expectedResultType;
6334
-
6335
+
6335
6336
// If we have a contextual type available for this closure, apply it to the
6336
6337
// ParamDecls in our parameter list. This ensures that any uses of them get
6337
6338
// appropriate types.
6338
- if (CS->getContextualType () &&
6339
- CS->getContextualType ()->is <AnyFunctionType>()) {
6340
-
6341
- auto fnType = CS->getContextualType ()->castTo <AnyFunctionType>();
6339
+ if (contextualType && contextualType->is <AnyFunctionType>()) {
6340
+ auto fnType = contextualType->getAs <AnyFunctionType>();
6342
6341
auto *params = CE->getParameters ();
6343
6342
Type inferredArgType = fnType->getInput ();
6344
6343
@@ -6393,12 +6392,24 @@ bool FailureDiagnosis::visitClosureExpr(ClosureExpr *CE) {
6393
6392
return true ;
6394
6393
}
6395
6394
6395
+ // Coerce parameter types here only if there are no unresolved
6396
6396
if (CS->TC .coerceParameterListToType (params, CE, fnType))
6397
6397
return true ;
6398
6398
6399
+ for (auto param : *params) {
6400
+ auto paramType = param->getType ();
6401
+ // If this is unresolved 'inout' parameter, it's better to drop
6402
+ // 'inout' from type but keep 'mutability' classifier because that
6403
+ // might help to diagnose actual problem e.g. type inference and
6404
+ // doesn't give us much information anyway.
6405
+ if (paramType->is <InOutType>() && paramType->hasUnresolvedType ()) {
6406
+ param->setType (CS->getASTContext ().TheUnresolvedType );
6407
+ param->setInterfaceType (param->getType ());
6408
+ }
6409
+ }
6410
+
6399
6411
expectedResultType = fnType->getResult ();
6400
6412
} else {
6401
-
6402
6413
// Defend against type variables from our constraint system leaking into
6403
6414
// recursive constraints systems formed when checking the body of the
6404
6415
// closure. These typevars come into them when the body does name
@@ -6417,36 +6428,67 @@ bool FailureDiagnosis::visitClosureExpr(ClosureExpr *CE) {
6417
6428
if (!CE->hasSingleExpressionBody ())
6418
6429
return false ;
6419
6430
6420
- // If the closure had an expected result type, use it.
6421
- if (CE->hasExplicitResultType ())
6422
- expectedResultType = CE->getExplicitResultTypeLoc ().getType ();
6423
-
6424
6431
// When we're type checking a single-expression closure, we need to reset the
6425
6432
// DeclContext to this closure for the recursive type checking. Otherwise,
6426
6433
// if there is a closure in the subexpression, we can violate invariants.
6427
6434
{
6428
6435
llvm::SaveAndRestore<DeclContext*> SavedDC (CS->DC , CE);
6429
-
6430
- auto CTP = expectedResultType ? CTP_ClosureResult : CTP_Unused;
6431
6436
6432
6437
// Explicitly disallow to produce solutions with unresolved type variables,
6433
6438
// because there is no auxiliary logic which would handle that and it's
6434
6439
// better to allow failure diagnosis to run directly on the closure body.
6435
6440
// Note that presence of contextual type implicitly forbids such solutions,
6436
6441
// but it's not always reset.
6442
+
6443
+ if (expectedResultType && !CE->hasExplicitResultType ()) {
6444
+ ExprCleaner cleaner (CE);
6445
+
6446
+ auto closure = CE->getSingleExpressionBody ();
6447
+ ConcreteDeclRef decl = nullptr ;
6448
+ // Let's try to compute result type without mutating AST and
6449
+ // using expected (contextual) result type, that's going to help
6450
+ // diagnose situations where contextual type expected one result
6451
+ // type but actual closure produces a different one without explicitly
6452
+ // declaring it (e.g. by using anonymous parameters).
6453
+ auto type = CS->TC .getTypeOfExpressionWithoutApplying (
6454
+ closure, CS->DC , decl, FreeTypeVariableBinding::Disallow);
6455
+
6456
+ Type resultType = type.hasValue () ? *type : Type ();
6457
+
6458
+ // Following situations are possible:
6459
+ // * No result type - possible structurable problem in the body;
6460
+ // * Function result type - possible use of function without calling it,
6461
+ // which is properly diagnosed by actual type-check call.
6462
+ if (resultType && !resultType->getRValueType ()->is <AnyFunctionType>()) {
6463
+ if (!resultType->isEqual (expectedResultType)) {
6464
+ diagnose (closure->getEndLoc (), diag::cannot_convert_closure_result,
6465
+ resultType, expectedResultType);
6466
+ return true ;
6467
+ }
6468
+ }
6469
+ }
6470
+
6471
+ // If the closure had an expected result type, use it.
6472
+ if (CE->hasExplicitResultType ())
6473
+ expectedResultType = CE->getExplicitResultTypeLoc ().getType ();
6474
+
6475
+ // If we couldn't diagnose anything related to the contextual result type
6476
+ // let's run proper type-check with expected type and try to verify it.
6477
+
6478
+ auto CTP = expectedResultType ? CTP_ClosureResult : CTP_Unused;
6437
6479
if (!typeCheckChildIndependently (CE->getSingleExpressionBody (),
6438
6480
expectedResultType, CTP, TCCOptions (),
6439
6481
nullptr , false ))
6440
6482
return true ;
6441
6483
}
6442
-
6484
+
6443
6485
// If the body of the closure looked ok, then look for a contextual type
6444
6486
// error. This is necessary because FailureDiagnosis::diagnoseExprFailure
6445
6487
// doesn't do this for closures.
6446
- if (CS-> getContextualType () &&
6447
- !CS-> getContextualType ()-> isEqual (CE-> getType ())) {
6448
-
6449
- auto fnType = CS-> getContextualType ()-> getAs <AnyFunctionType>() ;
6488
+ if (contextualType) {
6489
+ auto fnType = contextualType-> getAs <AnyFunctionType>();
6490
+ if (!fnType || fnType-> isEqual (CE-> getType ()))
6491
+ return false ;
6450
6492
6451
6493
// If the closure had an explicitly written return type incompatible with
6452
6494
// the contextual type, diagnose that.
0 commit comments