@@ -551,6 +551,14 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
551
551
// / a subscript and offer a fixit if the inputs are compatible.
552
552
bool diagnoseSubscriptMisuse (ApplyExpr *callExpr);
553
553
554
+ // / Try to diagnose common errors involving implicitly non-escaping parameters
555
+ // / of function type, giving more specific and simpler diagnostics, attaching
556
+ // / notes on the parameter, and offering fixits to insert @escaping. Returns
557
+ // / true if it detects and issues an error, false if it does nothing.
558
+ bool diagnoseNonEscapingParameterToEscaping (Expr *expr, Type srcType,
559
+ Type dstType,
560
+ ContextualTypePurpose dstPurpose);
561
+
554
562
bool visitExpr (Expr *E);
555
563
bool visitIdentityExpr (IdentityExpr *E);
556
564
bool visitTryExpr (TryExpr *E);
@@ -1441,12 +1449,14 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){
1441
1449
return true ;
1442
1450
}
1443
1451
1444
- if (srcFT->isNoEscape () && !destFT->isNoEscape ()) {
1445
- diagnose (expr->getLoc (), diag::noescape_functiontype_mismatch,
1446
- fromType, toType)
1447
- .highlight (expr->getSourceRange ());
1452
+ auto destPurpose = CTP_Unused;
1453
+ if (constraint->getKind () == ConstraintKind::ArgumentConversion ||
1454
+ constraint->getKind () == ConstraintKind::OperatorArgumentConversion)
1455
+ destPurpose = CTP_CallArgument;
1456
+
1457
+ if (diagnoseNonEscapingParameterToEscaping (anchor, fromType, toType,
1458
+ destPurpose))
1448
1459
return true ;
1449
- }
1450
1460
}
1451
1461
1452
1462
// If this is a callee that mismatches an expected return type, we can emit a
@@ -2344,9 +2354,8 @@ static bool addTypeCoerceFixit(InFlightDiagnostic &diag, ConstraintSystem &CS,
2344
2354
// / of function type, giving more specific and simpler diagnostics, attaching
2345
2355
// / notes on the parameter, and offering fixits to insert @escaping. Returns
2346
2356
// / true if it detects and issues an error, false if it does nothing.
2347
- static bool tryDiagnoseNonEscapingParameterToEscaping (
2348
- Expr *expr, Type srcType, Type dstType, ContextualTypePurpose dstPurpose,
2349
- ConstraintSystem &CS) {
2357
+ bool FailureDiagnosis::diagnoseNonEscapingParameterToEscaping (
2358
+ Expr *expr, Type srcType, Type dstType, ContextualTypePurpose dstPurpose) {
2350
2359
assert (expr);
2351
2360
// Need to be referencing a parameter of function type
2352
2361
auto declRef = dyn_cast<DeclRefExpr>(expr);
@@ -2684,8 +2693,8 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
2684
2693
}
2685
2694
2686
2695
// Try for better/more specific diagnostics for non-escaping to @escaping
2687
- if (tryDiagnoseNonEscapingParameterToEscaping (expr, exprType, contextualType,
2688
- CTP, CS ))
2696
+ if (diagnoseNonEscapingParameterToEscaping (expr, exprType, contextualType,
2697
+ CTP))
2689
2698
return true ;
2690
2699
2691
2700
// Don't attempt fixits if we have an unsolved type variable, since
@@ -5482,21 +5491,52 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
5482
5491
}
5483
5492
}
5484
5493
5494
+ auto isFailingConstraintRelevant = [&]() -> bool {
5495
+ auto *constraint = CS.failedConstraint ;
5496
+ if (!constraint)
5497
+ return false ;
5498
+
5499
+ auto *locator = constraint->getLocator ();
5500
+ return locator && locator->getAnchor () == callExpr;
5501
+ };
5502
+
5485
5503
// If there is a failing constraint associated with current constraint
5486
5504
// system which points to the argument/parameter mismatch, let's use
5487
5505
// that information while re-typechecking argument expression, this
5488
5506
// makes it a lot easier to determine contextual mismatch.
5489
- if (CS. failedConstraint && !hasTrailingClosure) {
5507
+ if (isFailingConstraintRelevant () && !hasTrailingClosure) {
5490
5508
auto *constraint = CS.failedConstraint ;
5491
5509
if (constraint->getKind () == ConstraintKind::ApplicableFunction) {
5492
- if (auto *locator = constraint->getLocator ()) {
5493
- if (locator->getAnchor () == callExpr) {
5494
- auto calleeType = CS.simplifyType (constraint->getSecondType ());
5495
- if (auto *fnType = calleeType->getAs <FunctionType>())
5496
- argType = AnyFunctionType::composeInput (fnType->getASTContext (),
5497
- fnType->getParams (),
5510
+ auto calleeType = CS.simplifyType (constraint->getSecondType ());
5511
+ if (auto *fnType = calleeType->getAs <FunctionType>())
5512
+ argType = AnyFunctionType::composeInput (fnType->getASTContext (),
5513
+ fnType->getParams (),
5514
+ /* canonicalVararg=*/ false );
5515
+ } else if (constraint->getKind () == ConstraintKind::ArgumentConversion ||
5516
+ constraint->getKind () ==
5517
+ ConstraintKind::OperatorArgumentConversion) {
5518
+ using PathEltKind = ConstraintLocator::PathElementKind;
5519
+ // Dig up type variable which represents the overload choice that fit
5520
+ // this call expression after simplifying `ApplicableFunction` constraint.
5521
+ for (auto *typeVar : CS.getTypeVariables ()) {
5522
+ auto *locator = typeVar->getImpl ().getLocator ();
5523
+ auto path = locator->getPath ();
5524
+
5525
+ // Check whether this type variable in anchored at current
5526
+ // expression and path ends with `apply function`, which means
5527
+ // that it's related to `ApplicableFunction` constraint.
5528
+ if (locator->getAnchor () != callExpr || path.empty () ||
5529
+ path.back ().getKind () != PathEltKind::ApplyFunction)
5530
+ continue ;
5531
+
5532
+ if (auto type = typeVar->getImpl ().getFixedType (nullptr )) {
5533
+ fnType = type;
5534
+ if (auto *FT = fnType->getAs <AnyFunctionType>())
5535
+ argType = AnyFunctionType::composeInput (FT->getASTContext (),
5536
+ FT->getParams (),
5498
5537
/* canonicalVararg=*/ false );
5499
5538
}
5539
+ break ;
5500
5540
}
5501
5541
}
5502
5542
}
0 commit comments