@@ -374,6 +374,14 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
374
374
" not a representative" );
375
375
assert (!typeVar->getImpl ().getFixedType (nullptr ) && " has a fixed type" );
376
376
377
+ // Determines whether this type variable represents an object
378
+ // of the optional type extracted by force unwrap.
379
+ bool isOptionalObject = false ;
380
+ if (auto *locator = typeVar->getImpl ().getLocator ()) {
381
+ auto *anchor = locator->getAnchor ();
382
+ isOptionalObject = anchor && isa<ForceValueExpr>(anchor);
383
+ }
384
+
377
385
// Gather the constraints associated with this type variable.
378
386
llvm::SetVector<Constraint *> constraints;
379
387
getConstraintGraph ().gatherConstraints (
@@ -425,6 +433,18 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
425
433
if (exactTypes.insert (type->getCanonicalType ()).second ) {
426
434
result.addPotentialBinding (*binding);
427
435
436
+ // Result of force unwrap is always connected to its base
437
+ // optional type via `OptionalObject` constraint which
438
+ // preserves l-valueness, so in case where object type got
439
+ // inferred before optional type (because it got the
440
+ // type from context e.g. parameter type of a function call),
441
+ // we need to test type with and without l-value after
442
+ // delaying bindings for as long as possible.
443
+ if (isOptionalObject && !type->is <LValueType>()) {
444
+ result.addPotentialBinding (binding->withType (LValueType::get (type)));
445
+ result.FullyBound = true ;
446
+ }
447
+
428
448
if (auto *locator = typeVar->getImpl ().getLocator ()) {
429
449
auto path = locator->getPath ();
430
450
auto voidType = getASTContext ().TheEmptyTupleType ;
0 commit comments