Skip to content

Commit fd29659

Browse files
committed
[Function builders] Use one-way constraints for closure parameters.
Introduce one-way constraints for the parameters of closures to which a function builder is being applied. This was an intended part of the model when one-way constraints were introduced, but somehow got missed. This should further break up large constraints systems for faster solving, and *most likely* won't break much source code in practice. Fixes rdar://problem/64231116. (cherry picked from commit f60d17b)
1 parent b556c73 commit fd29659

File tree

3 files changed

+46
-24
lines changed

3 files changed

+46
-24
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7115,6 +7115,24 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
71157115
auto *closure = cast<ClosureExpr>(closureLocator->getAnchor());
71167116
auto *inferredClosureType = getClosureType(closure);
71177117

7118+
// Determine whether a function builder will be applied.
7119+
Type functionBuilderType;
7120+
ConstraintLocator *calleeLocator = nullptr;
7121+
if (auto last = locator.last()) {
7122+
if (auto argToParam = last->getAs<LocatorPathElt::ApplyArgToParam>()) {
7123+
calleeLocator = getCalleeLocator(getConstraintLocator(locator));
7124+
functionBuilderType = getFunctionBuilderTypeFor(
7125+
*this, argToParam->getParamIdx(), calleeLocator);
7126+
}
7127+
}
7128+
7129+
// Determine whether to introduce one-way constraints between the parameter's
7130+
// type as seen in the body of the closure and the external parameter
7131+
// type.
7132+
bool oneWayConstraints =
7133+
getASTContext().TypeCheckerOpts.EnableOneWayClosureParameters ||
7134+
functionBuilderType;
7135+
71187136
auto *paramList = closure->getParameters();
71197137
SmallVector<AnyFunctionType::Param, 4> parameters;
71207138
for (unsigned i = 0, n = paramList->size(); i != n; ++i) {
@@ -7128,9 +7146,6 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
71287146
}
71297147

71307148
Type internalType;
7131-
7132-
bool oneWayConstraints =
7133-
getASTContext().TypeCheckerOpts.EnableOneWayClosureParameters;
71347149
if (paramList->get(i)->getTypeRepr()) {
71357150
// Internal type is the type used in the body of the closure,
71367151
// so "external" type translates to it as follows:
@@ -7181,17 +7196,12 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
71817196
inferredClosureType->getExtInfo());
71827197
assignFixedType(typeVar, closureType, closureLocator);
71837198

7184-
if (auto last = locator.last()) {
7185-
if (auto argToParam = last->getAs<LocatorPathElt::ApplyArgToParam>()) {
7186-
auto *calleeLocator = getCalleeLocator(getConstraintLocator(locator));
7187-
if (auto functionBuilderType = getFunctionBuilderTypeFor(
7188-
*this, argToParam->getParamIdx(), calleeLocator)) {
7189-
if (auto result = matchFunctionBuilder(
7190-
closure, functionBuilderType, closureType->getResult(),
7191-
ConstraintKind::Conversion, calleeLocator, locator)) {
7192-
return result->isSuccess();
7193-
}
7194-
}
7199+
// If there is a function builder to apply, do so now.
7200+
if (functionBuilderType) {
7201+
if (auto result = matchFunctionBuilder(
7202+
closure, functionBuilderType, closureType->getResult(),
7203+
ConstraintKind::Conversion, calleeLocator, locator)) {
7204+
return result->isSuccess();
71957205
}
71967206
}
71977207

test/Constraints/function_builder_diags.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,3 +558,14 @@ func rdar61347993() {
558558
func test_closure(_: () -> Result) {}
559559
test_closure {} // expected-error {{cannot convert value of type '()' to closure result type 'Result'}}
560560
}
561+
562+
// One-way constraints through parameters.
563+
func wrapperifyInfer<T, U>(_ cond: Bool, @WrapperBuilder body: (U) -> T) -> T {
564+
fatalError("boom")
565+
}
566+
567+
let intValue = 17
568+
wrapperifyInfer(true) { x in // expected-error{{unable to infer type of a closure parameter 'x' in the current context}}
569+
intValue + x
570+
}
571+

test/Constraints/function_builder_one_way.swift

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,17 @@ 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 $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
52+
// CHECK-NEXT: 1: $T10 depends on 0
53+
// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T77 $T78 depends on 3
54+
// CHECK-NEXT: 3: $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 2, 4, 5, 7, 10
55+
// CHECK-NEXT: 10: $T48 $T49 $T50 $T51 $T52 depends on 9
56+
// CHECK-NEXT: 9: $T43 $T44 $T45 $T46 $T47
57+
// CHECK-NEXT: 7: $T31 $T35 $T36 $T37 $T38 $T39 $T40 $T41 depends on 6, 8
58+
// CHECK-NEXT: 8: $T32 $T33 $T34
59+
// CHECK-NEXT: 6: $T30
60+
// CHECK-NEXT: 5: $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27
61+
// CHECK-NEXT: 4: $T15 $T16
62+
// CHECK-NEXT: 2: $T11
6263
let names = ["Alice", "Bob", "Charlie"]
6364
let b = true
6465
var number = 17

0 commit comments

Comments
 (0)