Skip to content

Commit 3ff0346

Browse files
committed
[CSSimplify] Propagate contextual result type into result builder transformed closure
Propagate fully or partially resolved contextual type down into the body of result builder transformed closure by eagerly binding intermediate body result type to the contextual one. This helps to determine when closure body could be solved early. Resolves: rdar://106364495
1 parent b989057 commit 3ff0346

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3532,11 +3532,29 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
35323532
}
35333533
}
35343534

3535+
auto resultMatchKind = subKind;
3536+
// Performance optimization: Propagate fully or partially resolved contextual
3537+
// type down into the body of result builder transformed closure by eagerly
3538+
// binding intermediate body result type to the contextual one. This helps to
3539+
// determine when closure body could be solved early.
3540+
//
3541+
// TODO: This could be extended to cover all multi-statement closures.
3542+
//
3543+
// See \c BindingSet::favoredOverConjunction for more details.
3544+
if (resultMatchKind >= ConstraintKind::Subtype &&
3545+
!func2->getResult()->isTypeVariableOrMember()) {
3546+
if (auto *closure = getAsExpr<ClosureExpr>(locator.trySimplifyToExpr())) {
3547+
if (!closure->hasExplicitResultType() &&
3548+
getAppliedResultBuilderTransform(closure)) {
3549+
resultMatchKind = ConstraintKind::Equal;
3550+
}
3551+
}
3552+
}
3553+
35353554
// Result type can be covariant (or equal).
3536-
return matchTypes(func1->getResult(), func2->getResult(), subKind,
3537-
subflags,
3538-
locator.withPathElement(
3539-
ConstraintLocator::FunctionResult));
3555+
return matchTypes(func1->getResult(), func2->getResult(), resultMatchKind,
3556+
subflags,
3557+
locator.withPathElement(ConstraintLocator::FunctionResult));
35403558
}
35413559

35423560
ConstraintSystem::TypeMatchResult

test/Constraints/result_builder.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,3 +1383,22 @@ testOptionalIfElseSequences()
13831383
// CHECK-NEXT: second(Optional(main.B()), nil)
13841384
// CHECK-NEXT: second(nil, Optional(main.Either<main.C, main.D>.first(main.C())))
13851385
// CHECK-NEXT: second(nil, Optional(main.Either<main.C, main.D>.second(main.D())))
1386+
1387+
// rdar://106364495 - ambiguous use of `buildFinalResult`
1388+
func testBuildFinalResultDependentOnContextualType() {
1389+
@resultBuilder
1390+
struct MyBuilder {
1391+
static func buildBlock(_ v: Int) -> Int { v }
1392+
static func buildFinalResult(_ v: Int) -> Int { v }
1393+
static func buildFinalResult(_ v: Int) -> String { "" }
1394+
}
1395+
1396+
func test(@MyBuilder _ fn: () -> Int?) { print(fn()) }
1397+
1398+
test {
1399+
42
1400+
}
1401+
}
1402+
1403+
testBuildFinalResultDependentOnContextualType()
1404+
// CHECK: Optional(42)

0 commit comments

Comments
 (0)