From f60d17bf3d18c28ac28c8a4804f500c28259f16e Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Wed, 10 Jun 2020 16:58:03 -0700 Subject: [PATCH] [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. --- lib/Sema/CSSimplify.cpp | 38 ++++++++++++------- test/Constraints/function_builder_diags.swift | 11 ++++++ .../function_builder_one_way.swift | 21 +++++----- 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 37e2639ccf9a3..cadfea40c9518 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7222,6 +7222,24 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, auto *closure = castToExpr(closureLocator->getAnchor()); auto *inferredClosureType = getClosureType(closure); + // Determine whether a function builder will be applied. + Type functionBuilderType; + ConstraintLocator *calleeLocator = nullptr; + if (auto last = locator.last()) { + if (auto argToParam = last->getAs()) { + calleeLocator = getCalleeLocator(getConstraintLocator(locator)); + functionBuilderType = getFunctionBuilderTypeFor( + *this, argToParam->getParamIdx(), calleeLocator); + } + } + + // Determine whether to introduce one-way constraints between the parameter's + // type as seen in the body of the closure and the external parameter + // type. + bool oneWayConstraints = + getASTContext().TypeCheckerOpts.EnableOneWayClosureParameters || + functionBuilderType; + auto *paramList = closure->getParameters(); SmallVector parameters; for (unsigned i = 0, n = paramList->size(); i != n; ++i) { @@ -7235,9 +7253,6 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, } Type internalType; - - bool oneWayConstraints = - getASTContext().TypeCheckerOpts.EnableOneWayClosureParameters; if (paramList->get(i)->getTypeRepr()) { // Internal type is the type used in the body of the closure, // so "external" type translates to it as follows: @@ -7288,17 +7303,12 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, inferredClosureType->getExtInfo()); assignFixedType(typeVar, closureType, closureLocator); - if (auto last = locator.last()) { - if (auto argToParam = last->getAs()) { - auto *calleeLocator = getCalleeLocator(getConstraintLocator(locator)); - if (auto functionBuilderType = getFunctionBuilderTypeFor( - *this, argToParam->getParamIdx(), calleeLocator)) { - if (auto result = matchFunctionBuilder( - closure, functionBuilderType, closureType->getResult(), - ConstraintKind::Conversion, calleeLocator, locator)) { - return result->isSuccess(); - } - } + // If there is a function builder to apply, do so now. + if (functionBuilderType) { + if (auto result = matchFunctionBuilder( + closure, functionBuilderType, closureType->getResult(), + ConstraintKind::Conversion, calleeLocator, locator)) { + return result->isSuccess(); } } diff --git a/test/Constraints/function_builder_diags.swift b/test/Constraints/function_builder_diags.swift index 389ddc5ba6bc1..1a04e05892926 100644 --- a/test/Constraints/function_builder_diags.swift +++ b/test/Constraints/function_builder_diags.swift @@ -558,3 +558,14 @@ func rdar61347993() { func test_closure(_: () -> Result) {} test_closure {} // expected-error {{cannot convert value of type '()' to closure result type 'Result'}} } + +// One-way constraints through parameters. +func wrapperifyInfer(_ cond: Bool, @WrapperBuilder body: (U) -> T) -> T { + fatalError("boom") +} + +let intValue = 17 +wrapperifyInfer(true) { x in // expected-error{{unable to infer type of a closure parameter 'x' in the current context}} + intValue + x +} + diff --git a/test/Constraints/function_builder_one_way.swift b/test/Constraints/function_builder_one_way.swift index d393025c4b01c..e3519800497f1 100644 --- a/test/Constraints/function_builder_one_way.swift +++ b/test/Constraints/function_builder_one_way.swift @@ -49,16 +49,17 @@ func tuplify(_ collection: C, @TupleBuilder body: (C.Element) } // CHECK: ---Connected components--- -// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T10 $T77 $T78 depends on 2 -// 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 -// CHECK-NEXT: 9: $T48 $T49 $T50 $T51 $T52 depends on 8 -// CHECK-NEXT: 8: $T43 $T44 $T45 $T46 $T47 -// CHECK-NEXT: 6: $T31 $T35 $T36 $T37 $T38 $T39 $T40 $T41 depends on 5, 7 -// CHECK-NEXT: 7: $T32 $T33 $T34 -// CHECK-NEXT: 5: $T30 -// CHECK-NEXT: 4: $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27 -// CHECK-NEXT: 3: $T15 $T16 -// CHECK-NEXT: 1: $T11 +// CHECK-NEXT: 1: $T10 depends on 0 +// CHECK-NEXT: 0: $T1 $T2 $T3 $T5 $T6 $T7 $T8 $T77 $T78 depends on 3 +// 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 +// CHECK-NEXT: 10: $T48 $T49 $T50 $T51 $T52 depends on 9 +// CHECK-NEXT: 9: $T43 $T44 $T45 $T46 $T47 +// CHECK-NEXT: 7: $T31 $T35 $T36 $T37 $T38 $T39 $T40 $T41 depends on 6, 8 +// CHECK-NEXT: 8: $T32 $T33 $T34 +// CHECK-NEXT: 6: $T30 +// CHECK-NEXT: 5: $T18 $T19 $T20 $T21 $T22 $T23 $T24 $T25 $T26 $T27 +// CHECK-NEXT: 4: $T15 $T16 +// CHECK-NEXT: 2: $T11 let names = ["Alice", "Bob", "Charlie"] let b = true var number = 17