Skip to content

Commit a54fbab

Browse files
committed
[ConstraintSystem] Favor resolving closures over any disjunction binding type variables
Fix a case where favoring didn't account for "bound" type variable being wrapped into optional(s) (disjunctions like that are used for optional conversions). Doing so makes sure that closure result type is not bound before the body of the closure is "opened", that's important because body could provide additional context required to bind result type e.g. `{ $0 as? <Type> }`. Resolve: rdar://problem/59208419
1 parent 2b85835 commit a54fbab

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,14 @@ bool ConstraintSystem::PotentialBindings::favoredOverDisjunction(
246246
// if it's something like a collection (where it has to pick
247247
// between a conversion and bridging conversion) or concrete
248248
// type let's prefer the disjunction.
249-
return boundType->is<TypeVariableType>();
249+
//
250+
// We are looking through optionals here because it could be
251+
// a situation where disjunction is formed to match optionals
252+
// either as deep equality or optional-to-optional conversion.
253+
// Such type variables might be connected to closure as well
254+
// e.g. when result type is optional, so it makes sense to
255+
// open closure before attempting such disjunction.
256+
return boundType->lookThroughAllOptionalTypes()->is<TypeVariableType>();
250257
}
251258

252259
return !InvolvesTypeVariables;

test/Constraints/closures.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,3 +953,21 @@ class Foo<State: StateType> {
953953
func test_explicit_variadic_is_interpreted_correctly() {
954954
_ = { (T: String...) -> String in T[0] + "" } // Ok
955955
}
956+
957+
// rdar://problem/59208419 - closure result type is incorrectly inferred to be a supertype
958+
func test_correct_inference_of_closure_result_in_presence_of_optionals() {
959+
class A {}
960+
class B : A {}
961+
962+
func foo(_: B) -> Int? { return 42 }
963+
964+
func bar<T: A>(_: (A) -> T?) -> T? {
965+
return .none
966+
}
967+
968+
guard let v = bar({ $0 as? B }),
969+
let _ = foo(v) // Ok, v is inferred as `B`
970+
else {
971+
return;
972+
}
973+
}

0 commit comments

Comments
 (0)