@@ -350,6 +350,14 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
350
350
" not a representative" );
351
351
assert (!typeVar->getImpl ().getFixedType (nullptr ) && " has a fixed type" );
352
352
353
+ // Determines whether this type variable represents an object
354
+ // of the optional type extracted by force unwrap.
355
+ bool isOptionalObject = false ;
356
+ if (auto *locator = typeVar->getImpl ().getLocator ()) {
357
+ auto *anchor = locator->getAnchor ();
358
+ isOptionalObject = anchor && isa<ForceValueExpr>(anchor);
359
+ }
360
+
353
361
// Gather the constraints associated with this type variable.
354
362
llvm::SetVector<Constraint *> constraints;
355
363
getConstraintGraph ().gatherConstraints (
@@ -401,6 +409,18 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
401
409
if (exactTypes.insert (type->getCanonicalType ()).second ) {
402
410
result.addPotentialBinding (*binding);
403
411
412
+ // Result of force unwrap is always connected to its base
413
+ // optional type via `OptionalObject` constraint which
414
+ // preserves l-valueness, so in case where object type got
415
+ // inferred before optional type (because it got the
416
+ // type from context e.g. parameter type of a function call),
417
+ // we need to test type with and without l-value after
418
+ // delaying bindings for as long as possible.
419
+ if (isOptionalObject && !type->is <LValueType>()) {
420
+ result.FullyBound = true ;
421
+ result.PotentiallyIncomplete = true ;
422
+ }
423
+
404
424
if (auto *locator = typeVar->getImpl ().getLocator ()) {
405
425
auto path = locator->getPath ();
406
426
auto voidType = getASTContext ().TheEmptyTupleType ;
0 commit comments