@@ -2552,6 +2552,103 @@ repairViaBridgingCast(ConstraintSystem &cs, Type fromType, Type toType,
2552
2552
return true ;
2553
2553
}
2554
2554
2555
+ static bool
2556
+ repairViaOptionalUnwrap (ConstraintSystem &cs, Type fromType, Type toType,
2557
+ ConstraintKind matchKind,
2558
+ SmallVectorImpl<RestrictionOrFix> &conversionsOrFixes,
2559
+ ConstraintLocatorBuilder locator) {
2560
+ fromType = fromType->getWithoutSpecifierType ();
2561
+
2562
+ if (!fromType->getOptionalObjectType () || toType->is <TypeVariableType>())
2563
+ return false ;
2564
+
2565
+ // If we have an optional type, try to force-unwrap it.
2566
+ // FIXME: Should we also try '?'?
2567
+ auto *anchor = locator.trySimplifyToExpr ();
2568
+ if (!anchor)
2569
+ return false ;
2570
+
2571
+ // `OptionalEvaluationExpr` doesn't add a new level of
2572
+ // optionality but it could be hiding concrete types
2573
+ // behind itself which we can use to better understand
2574
+ // how many levels of optionality have to be unwrapped.
2575
+ if (auto *OEE = dyn_cast<OptionalEvaluationExpr>(anchor)) {
2576
+ auto type = cs.getType (OEE->getSubExpr ());
2577
+ // If the type of sub-expression is optional, type of the
2578
+ // `OptionalEvaluationExpr` could be safely ignored because
2579
+ // it doesn't add any type information.
2580
+ if (type->getOptionalObjectType ())
2581
+ fromType = type;
2582
+
2583
+ // If this is a conversion from optional chain to some
2584
+ // other type e.g. contextual type or a parameter type,
2585
+ // let's use `Bind` to match object types because
2586
+ // object type of the optinal chain is a type variable.
2587
+ if (matchKind >= ConstraintKind::Conversion)
2588
+ matchKind = ConstraintKind::Bind;
2589
+ }
2590
+
2591
+ if (auto *DRE = dyn_cast<DeclRefExpr>(anchor)) {
2592
+ if (DRE->getDecl ()->isImplicit ()) {
2593
+ // The expression that provides the first type is implicit and never
2594
+ // spelled out in source code, e.g. $match in an expression pattern.
2595
+ // Thus we cannot force unwrap the first type
2596
+ return false ;
2597
+ }
2598
+ }
2599
+
2600
+ if (auto *optTryExpr = dyn_cast<OptionalTryExpr>(anchor)) {
2601
+ auto subExprType = cs.getType (optTryExpr->getSubExpr ());
2602
+ const bool isSwift5OrGreater =
2603
+ cs.getASTContext ().LangOpts .isSwiftVersionAtLeast (5 );
2604
+
2605
+ if (subExprType->getOptionalObjectType ()) {
2606
+ if (isSwift5OrGreater) {
2607
+ // For 'try?' expressions, a ForceOptional fix converts 'try?'
2608
+ // to 'try!'. If the sub-expression is optional, then a force-unwrap
2609
+ // won't change anything in Swift 5+ because 'try?' already avoids
2610
+ // adding an additional layer of Optional there.
2611
+ return false ;
2612
+ }
2613
+ } else {
2614
+ // In cases when sub-expression isn't optional, 'try?'
2615
+ // always adds one level of optinality regardless of
2616
+ // language mode, so we can safely try to bind its
2617
+ // object type to contextual type without risk of
2618
+ // causing more optionality mismatches down the road.
2619
+ matchKind = ConstraintKind::Bind;
2620
+ }
2621
+ }
2622
+
2623
+ auto getObjectTypeAndUnwraps = [](Type type) -> std::pair<Type, unsigned > {
2624
+ SmallVector<Type, 2 > optionals;
2625
+ Type objType = type->lookThroughAllOptionalTypes (optionals);
2626
+ return std::make_pair (objType, optionals.size ());
2627
+ };
2628
+
2629
+ Type fromObjectType, toObjectType;
2630
+ unsigned fromUnwraps, toUnwraps;
2631
+
2632
+ std::tie (fromObjectType, fromUnwraps) = getObjectTypeAndUnwraps (fromType);
2633
+ std::tie (toObjectType, toUnwraps) = getObjectTypeAndUnwraps (toType);
2634
+
2635
+ // If `from` is not less optional than `to`, force unwrap is
2636
+ // not going to help here. In case of object type of `from`
2637
+ // is a type variable, let's assume that it might be optional.
2638
+ if (fromUnwraps <= toUnwraps && !fromObjectType->is <TypeVariableType>())
2639
+ return false ;
2640
+
2641
+ auto result =
2642
+ cs.matchTypes (fromObjectType, toObjectType, matchKind,
2643
+ ConstraintSystem::TypeMatchFlags::TMF_ApplyingFix, locator);
2644
+ if (!result.isSuccess ())
2645
+ return false ;
2646
+
2647
+ conversionsOrFixes.push_back (ForceOptional::create (
2648
+ cs, fromType, toType, cs.getConstraintLocator (locator)));
2649
+ return true ;
2650
+ }
2651
+
2555
2652
// / Attempt to repair typing failures and record fixes if needed.
2556
2653
// / \return true if at least some of the failures has been repaired
2557
2654
// / successfully, which allows type matcher to continue.
@@ -2678,11 +2775,21 @@ bool ConstraintSystem::repairFailures(
2678
2775
if (!anchor)
2679
2776
return false ;
2680
2777
2681
- // Repair a coercion ('as') with a forced checked cast ('as!').
2682
- if (auto *coerceToCheckCastFix = CoerceToCheckedCast::attempt (
2683
- *this , lhs, rhs, getConstraintLocator (locator))) {
2684
- conversionsOrFixes.push_back (coerceToCheckCastFix);
2685
- return true ;
2778
+ if (auto *coercion = dyn_cast<CoerceExpr>(anchor)) {
2779
+ // Let's check whether the sub-expression is an optional type which
2780
+ // is possible to unwrap (either by force or `??`) to satisfy the cast,
2781
+ // otherwise we'd have to fallback to force downcast.
2782
+ if (repairViaOptionalUnwrap (*this , lhs, rhs, matchKind,
2783
+ conversionsOrFixes,
2784
+ getConstraintLocator (coercion->getSubExpr ())))
2785
+ return true ;
2786
+
2787
+ // Repair a coercion ('as') with a forced checked cast ('as!').
2788
+ if (auto *coerceToCheckCastFix = CoerceToCheckedCast::attempt (
2789
+ *this , lhs, rhs, getConstraintLocator (locator))) {
2790
+ conversionsOrFixes.push_back (coerceToCheckCastFix);
2791
+ return true ;
2792
+ }
2686
2793
}
2687
2794
2688
2795
// This could be:
@@ -2805,6 +2912,10 @@ bool ConstraintSystem::repairFailures(
2805
2912
return true ;
2806
2913
}
2807
2914
2915
+ if (repairViaOptionalUnwrap (*this , lhs, rhs, matchKind,
2916
+ conversionsOrFixes, locator))
2917
+ return true ;
2918
+
2808
2919
// Let's try to match source and destination types one more
2809
2920
// time to see whether they line up, if they do - the problem is
2810
2921
// related to immutability, otherwise it's a type mismatch.
@@ -3080,6 +3191,10 @@ bool ConstraintSystem::repairFailures(
3080
3191
if (lhs->hasHole () || rhs->hasHole ())
3081
3192
return true ;
3082
3193
3194
+ if (repairViaOptionalUnwrap (*this , lhs, rhs, matchKind, conversionsOrFixes,
3195
+ locator))
3196
+ break ;
3197
+
3083
3198
conversionsOrFixes.push_back (
3084
3199
AllowArgumentMismatch::create (*this , lhs, rhs, loc));
3085
3200
break ;
@@ -3244,6 +3359,10 @@ bool ConstraintSystem::repairFailures(
3244
3359
if (lhs->is <InOutType>() || rhs->is <InOutType>())
3245
3360
break ;
3246
3361
3362
+ if (repairViaOptionalUnwrap (*this , lhs, rhs, matchKind, conversionsOrFixes,
3363
+ locator))
3364
+ break ;
3365
+
3247
3366
// If there is a deep equality, superclass restriction
3248
3367
// already recorded, let's not add bother ignoring
3249
3368
// contextual type, because actual fix is going to
@@ -3376,6 +3495,10 @@ bool ConstraintSystem::repairFailures(
3376
3495
}
3377
3496
3378
3497
case ConstraintLocator::Condition: {
3498
+ if (repairViaOptionalUnwrap (*this , lhs, rhs, matchKind, conversionsOrFixes,
3499
+ locator))
3500
+ break ;
3501
+
3379
3502
conversionsOrFixes.push_back (IgnoreContextualType::create (
3380
3503
*this , lhs, rhs, getConstraintLocator (locator)));
3381
3504
break ;
@@ -3390,6 +3513,10 @@ bool ConstraintSystem::repairFailures(
3390
3513
if (!(anchor && isa<UnresolvedMemberExpr>(anchor)))
3391
3514
break ;
3392
3515
3516
+ if (repairViaOptionalUnwrap (*this , lhs, rhs, matchKind, conversionsOrFixes,
3517
+ locator))
3518
+ break ;
3519
+
3393
3520
// r-value adjustment is used to connect base type of
3394
3521
// unresolved member to its output type, if there is
3395
3522
// a type mismatch here it's contextual e.g.
@@ -3426,6 +3553,14 @@ bool ConstraintSystem::repairFailures(
3426
3553
break ;
3427
3554
}
3428
3555
3556
+ case ConstraintLocator::OptionalPayload: {
3557
+ if (repairViaOptionalUnwrap (*this , lhs, rhs, matchKind, conversionsOrFixes,
3558
+ locator))
3559
+ return true ;
3560
+
3561
+ break ;
3562
+ }
3563
+
3429
3564
default :
3430
3565
break ;
3431
3566
}
@@ -4239,55 +4374,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
4239
4374
4240
4375
// Attempt fixes iff it's allowed, both types are concrete and
4241
4376
// we are not in the middle of attempting one already.
4242
- bool attemptFixes =
4243
- shouldAttemptFixes () && !flags.contains (TMF_ApplyingFix);
4244
-
4245
- // When we hit this point, we're committed to the set of potential
4246
- // conversions recorded thus far.
4247
- //
4248
- // If we should attempt fixes, add those to the list. They'll only be visited
4249
- // if there are no other possible solutions.
4250
- if (attemptFixes && kind >= ConstraintKind::Conversion) {
4251
- Type objectType1 = type1->getRValueType ();
4252
-
4253
- // If we have an optional type, try to force-unwrap it.
4254
- // FIXME: Should we also try '?'?
4255
- if (objectType1->getOptionalObjectType ()) {
4256
- bool forceUnwrapPossible = true ;
4257
- if (auto declRefExpr =
4258
- dyn_cast_or_null<DeclRefExpr>(locator.trySimplifyToExpr ())) {
4259
- if (declRefExpr->getDecl ()->isImplicit ()) {
4260
- // The expression that provides the first type is implicit and never
4261
- // spelled out in source code, e.g. $match in an expression pattern.
4262
- // Thus we cannot force unwrap the first type
4263
- forceUnwrapPossible = false ;
4264
- }
4265
- }
4266
-
4267
- if (auto optTryExpr =
4268
- dyn_cast_or_null<OptionalTryExpr>(locator.trySimplifyToExpr ())) {
4269
- auto subExprType = getType (optTryExpr->getSubExpr ());
4270
- const bool isSwift5OrGreater =
4271
- getASTContext ().LangOpts .isSwiftVersionAtLeast (5 );
4272
- if (isSwift5OrGreater && (bool )subExprType->getOptionalObjectType ()) {
4273
- // For 'try?' expressions, a ForceOptional fix converts 'try?'
4274
- // to 'try!'. If the sub-expression is optional, then a force-unwrap
4275
- // won't change anything in Swift 5+ because 'try?' already avoids
4276
- // adding an additional layer of Optional there.
4277
- forceUnwrapPossible = false ;
4278
- }
4279
- }
4280
-
4281
- if (forceUnwrapPossible) {
4282
- conversionsOrFixes.push_back (ForceOptional::create (
4283
- *this , objectType1, objectType1->getOptionalObjectType (),
4284
- getConstraintLocator (locator)));
4285
- }
4286
- }
4287
- }
4288
-
4289
- // Attempt to repair any failures identifiable at this point.
4290
- if (attemptFixes) {
4377
+ if (shouldAttemptFixes () && !flags.contains (TMF_ApplyingFix)) {
4291
4378
if (repairFailures (type1, type2, kind, conversionsOrFixes, locator)) {
4292
4379
if (conversionsOrFixes.empty ())
4293
4380
return getTypeMatchSuccess ();
@@ -4617,6 +4704,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
4617
4704
return SolutionKind::Error;
4618
4705
4619
4706
auto protocolTy = protocol->getDeclaredType ();
4707
+
4620
4708
// If this conformance has been fixed already, let's just consider this done.
4621
4709
if (hasFixedRequirement (type, RequirementKind::Conformance, protocolTy))
4622
4710
return SolutionKind::Solved;
@@ -4998,13 +5086,10 @@ ConstraintSystem::simplifyFunctionComponentConstraint(
4998
5086
}
4999
5087
5000
5088
if (unwrapCount > 0 ) {
5001
- auto *fix = ForceOptional::create (*this , simplifiedCopy,
5002
- simplifiedCopy->getOptionalObjectType (),
5089
+ auto *fix = ForceOptional::create (*this , simplifiedCopy, second,
5003
5090
getConstraintLocator (locator));
5004
- while (unwrapCount-- > 0 ) {
5005
- if (recordFix (fix))
5006
- return SolutionKind::Error;
5007
- }
5091
+ if (recordFix (fix, /* impact=*/ unwrapCount))
5092
+ return SolutionKind::Error;
5008
5093
}
5009
5094
5010
5095
return SolutionKind::Solved;
@@ -7308,13 +7393,10 @@ ConstraintSystem::simplifyApplicableFnConstraint(
7308
7393
return SolutionKind::Solved;
7309
7394
7310
7395
// Record any fixes we attempted to get to the correct solution.
7311
- auto *fix = ForceOptional::create (*this , origType2,
7312
- origType2->getOptionalObjectType (),
7396
+ auto *fix = ForceOptional::create (*this , origType2, func1,
7313
7397
getConstraintLocator (locator));
7314
- while (unwrapCount-- > 0 ) {
7315
- if (recordFix (fix))
7316
- return SolutionKind::Error;
7317
- }
7398
+ if (recordFix (fix, /* impact=*/ unwrapCount))
7399
+ return SolutionKind::Error;
7318
7400
7319
7401
return SolutionKind::Solved;
7320
7402
}
@@ -7336,13 +7418,10 @@ ConstraintSystem::simplifyApplicableFnConstraint(
7336
7418
if (unwrapCount == 0 )
7337
7419
return SolutionKind::Solved;
7338
7420
7339
- auto *fix = ForceOptional::create (*this , origType2,
7340
- origType2->getOptionalObjectType (),
7421
+ auto *fix = ForceOptional::create (*this , origType2, func1,
7341
7422
getConstraintLocator (locator));
7342
- while (unwrapCount-- > 0 ) {
7343
- if (recordFix (fix))
7344
- return SolutionKind::Error;
7345
- }
7423
+ if (recordFix (fix, /* impact=*/ unwrapCount))
7424
+ return SolutionKind::Error;
7346
7425
}
7347
7426
7348
7427
return simplified;
@@ -8194,15 +8273,16 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
8194
8273
getDefaultDecompositionOptions (flags) | TMF_ApplyingFix;
8195
8274
switch (fix->getKind ()) {
8196
8275
case FixKind::ForceOptional: {
8197
- // Assume that we've unwrapped the first type.
8198
- auto result =
8199
- matchTypes (type1->getRValueType ()->getOptionalObjectType (), type2,
8200
- matchKind, subflags, locator);
8201
- if (result == SolutionKind::Solved)
8202
- if (recordFix (fix))
8203
- return SolutionKind::Error;
8276
+ SmallVector<Type, 4 > unwraps1;
8277
+ type1->lookThroughAllOptionalTypes (unwraps1);
8204
8278
8205
- return result;
8279
+ SmallVector<Type, 4 > unwraps2;
8280
+ type2->lookThroughAllOptionalTypes (unwraps2);
8281
+
8282
+ auto impact = unwraps1.size () != unwraps2.size ()
8283
+ ? unwraps1.size () - unwraps2.size ()
8284
+ : 1 ;
8285
+ return recordFix (fix, impact) ? SolutionKind::Error : SolutionKind::Solved;
8206
8286
}
8207
8287
8208
8288
case FixKind::UnwrapOptionalBase:
0 commit comments