Skip to content

Commit 08baf67

Browse files
committed
[ConstraintSystem] Fix a case of too eager force optional unwrap with optional contextual type
If return of optional chaining is assigned to an optional type or discarded there should be no force optional unwrap attempt on it because type variable associated with context can be bound to optional of any depth. Resolves: rdar://problem/57668873
1 parent d8997c6 commit 08baf67

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2662,6 +2662,17 @@ repairViaOptionalUnwrap(ConstraintSystem &cs, Type fromType, Type toType,
26622662
if (fromUnwraps <= toUnwraps && !fromObjectType->is<TypeVariableType>())
26632663
return false;
26642664

2665+
// If the result of optional chaining is converted to
2666+
// an optional contextual type represented by a type
2667+
// variable e.g. `T?`, there can be no optional mismatch
2668+
// because `T` could be bound to an optional of any depth.
2669+
if (isa<OptionalEvaluationExpr>(anchor) && toUnwraps > 0) {
2670+
auto last = locator.last();
2671+
if (last && last->is<LocatorPathElt::ContextualType>() &&
2672+
toObjectType->is<TypeVariableType>())
2673+
return false;
2674+
}
2675+
26652676
auto result =
26662677
cs.matchTypes(fromObjectType, toObjectType, matchKind,
26672678
ConstraintSystem::TypeMatchFlags::TMF_ApplyingFix, locator);

test/Constraints/optional.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,21 @@ func sr_11104() {
402402
bar(["hello"].first)
403403
// expected-error@-1 {{cannot convert value of type 'String?' to expected argument type 'Int'}}
404404
}
405+
406+
// rdar://problem/57668873 - Too eager force optional unwrap fix
407+
408+
@objc class Window {}
409+
410+
@objc protocol WindowDelegate {
411+
@objc optional var window: Window? { get set }
412+
}
413+
414+
func test_force_unwrap_not_being_too_eager() {
415+
struct WindowContainer {
416+
unowned(unsafe) var delegate: WindowDelegate? = nil
417+
}
418+
419+
let obj: WindowContainer = WindowContainer()
420+
if let _ = obj.delegate?.window { // Ok
421+
}
422+
}

0 commit comments

Comments
 (0)