Skip to content

Commit df755d4

Browse files
authored
Merge pull request #64192 from xedin/rdar-106364495
[CSSimplify] Propagate contextual result type into result builder tra…
2 parents 56f8e54 + 3ff0346 commit df755d4

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)