Skip to content

Commit 0e88bd6

Browse files
committed
[ConstraintSystem] Don't attempt bindings for closure parameters/result until body is opened
Let's delay attempting any bindings for type variables representing parameters or result type of the closure until the body is "opened" because it's impossible to infer a full set of bindings until all constraints related to a closure have been generated. Resolves: rdar://problem/59741308
1 parent 9ae6813 commit 0e88bd6

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,20 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
314314
type = first;
315315
kind = AllowedBindingKind::Supertypes;
316316
} else {
317+
// If the left-hand side of a relational constraint is a
318+
// type variable representing a closure type, let's delay
319+
// attempting any bindings related to any type variables
320+
// on the other side since it could only be either a closure
321+
// parameter or a result type, and we can't get a full set
322+
// of bindings for them until closure's body is opened.
323+
if (auto *typeVar = first->getAs<TypeVariableType>()) {
324+
if (typeVar->getImpl().isClosureType()) {
325+
result.InvolvesTypeVariables = true;
326+
result.FullyBound = true;
327+
return None;
328+
}
329+
}
330+
317331
// Can't infer anything.
318332
if (result.InvolvesTypeVariables)
319333
return None;

test/Constraints/closures.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,3 +973,22 @@ func test_correct_inference_of_closure_result_in_presence_of_optionals() {
973973
return;
974974
}
975975
}
976+
977+
// rdar://problem/59741308 - inference fails with tuple element has to joined to supertype
978+
func rdar_59741308() {
979+
class Base {
980+
func foo(_: Int) {}
981+
}
982+
983+
class A : Base {}
984+
class B : Base {}
985+
986+
func test() {
987+
// Note that `0`, and `1` here are going to be type variables
988+
// which makes join impossible until it's already to late for
989+
// it to be useful.
990+
[(A(), 0), (B(), 1)].forEach { base, value in
991+
base.foo(value) // Ok
992+
}
993+
}
994+
}

test/Constraints/function_builder_one_way.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@ func tuplify<C: Collection, T>(_ collection: C, @TupleBuilder body: (C.Element)
4949
}
5050

5151
// CHECK: ---Connected components---
52-
// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T10 $T11 $T78 $T79 depends on 2
53-
// CHECK-NEXT: 2: $T13 $T18 $T29 $T43 $T54 $T55 $T56 $T57 $T58 $T59 $T60 $T61 $T62 $T63 $T64 $T65 $T66 $T67 $T69 $T70 $T71 $T72 $T73 $T74 $T75 $T76 $T77 depends on 1, 3, 4, 6, 9
54-
// CHECK-NEXT: 9: $T49 $T50 $T51 $T52 $T53 depends on 8
55-
// CHECK-NEXT: 8: $T44 $T45 $T46 $T47 $T48
56-
// CHECK-NEXT: 6: $T32 $T36 $T37 $T38 $T39 $T40 $T41 $T42 depends on 5, 7
57-
// CHECK-NEXT: 7: $T33 $T34 $T35
58-
// CHECK-NEXT: 5: $T31
59-
// CHECK-NEXT: 4: $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27 $T28
60-
// CHECK-NEXT: 3: $T16 $T17
61-
// CHECK-NEXT: 1: $T12
52+
// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T10 $T77 $T78 depends on 2
53+
// CHECK-NEXT: 2: $T12 $T17 $T28 $T42 $T53 $T54 $T55 $T56 $T57 $T58 $T59 $T60 $T61 $T62 $T63 $T64 $T65 $T66 $T68 $T69 $T70 $T71 $T72 $T73 $T74 $T75 $T76 depends on 1, 3, 4, 6, 9
54+
// CHECK-NEXT: 9: $T48 $T49 $T50 $T51 $T52 depends on 8
55+
// CHECK-NEXT: 8: $T43 $T44 $T45 $T46 $T47
56+
// CHECK-NEXT: 6: $T31 $T35 $T36 $T37 $T38 $T39 $T40 $T41 depends on 5, 7
57+
// CHECK-NEXT: 7: $T32 $T33 $T34
58+
// CHECK-NEXT: 5: $T30
59+
// CHECK-NEXT: 4: $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27
60+
// CHECK-NEXT: 3: $T15 $T16
61+
// CHECK-NEXT: 1: $T11
6262
let names = ["Alice", "Bob", "Charlie"]
6363
let b = true
6464
var number = 17

0 commit comments

Comments
 (0)