Skip to content

Commit bd44fb3

Browse files
authored
Merge pull request #30838 from xedin/rdar-61347993
[ConstraintSystem] Don't bind result type of an empty closure too early
2 parents 64c0bb8 + 04e2795 commit bd44fb3

File tree

4 files changed

+32
-13
lines changed

4 files changed

+32
-13
lines changed

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,7 +2184,6 @@ namespace {
21842184
closure->getExplicitResultTypeLoc().getType()) {
21852185
resultTy = closure->getExplicitResultTypeLoc().getType();
21862186
} else {
2187-
auto &ctx = CS.getASTContext();
21882187
auto *resultLoc =
21892188
CS.getConstraintLocator(closure, ConstraintLocator::ClosureResult);
21902189

@@ -2196,11 +2195,7 @@ namespace {
21962195
return Type();
21972196
};
21982197

2199-
if (closure->hasEmptyBody()) {
2200-
// Closures with empty bodies should be inferred to return
2201-
// ().
2202-
resultTy = ctx.TheEmptyTupleType;
2203-
} else if (auto contextualResultTy = getContextualResultType()) {
2198+
if (auto contextualResultTy = getContextualResultType()) {
22042199
resultTy = contextualResultTy;
22052200
} else {
22062201
// If no return type was specified, create a fresh type

lib/Sema/CSSimplify.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7048,7 +7048,7 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
70487048
}
70497049

70507050
bool hasReturn = hasExplicitResult(closure);
7051-
7051+
auto &ctx = getASTContext();
70527052
// If this is a multi-statement closure its body doesn't participate
70537053
// in type-checking.
70547054
if (closure->hasSingleExpressionBody()) {
@@ -7061,12 +7061,18 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
70617061
closureType->getResult(),
70627062
getConstraintLocator(closure, LocatorPathElt::ClosureBody(hasReturn)));
70637063
} else if (!hasReturn) {
7064-
// If multi-statement closure doesn't have an explicit result
7065-
// (no `return` statements) let's default it to `Void`.
7066-
auto &ctx = getASTContext();
7064+
bool hasExplicitResult = closure->hasExplicitResultType() &&
7065+
closure->getExplicitResultTypeLoc().getType();
7066+
7067+
// If this closure has an empty body and no explicit result type
7068+
// let's bind result type to `Void` since that's the only type empty body
7069+
// can produce. Otherwise, if (multi-statement) closure doesn't have
7070+
// an explicit result (no `return` statements) let's default it to `Void`.
7071+
auto constraintKind = (closure->hasEmptyBody() && !hasExplicitResult)
7072+
? ConstraintKind::Bind
7073+
: ConstraintKind::Defaultable;
70677074
addConstraint(
7068-
ConstraintKind::Defaultable, inferredClosureType->getResult(),
7069-
ctx.TheEmptyTupleType,
7075+
constraintKind, inferredClosureType->getResult(), ctx.TheEmptyTupleType,
70707076
getConstraintLocator(closure, ConstraintLocator::ClosureResult));
70717077
}
70727078

test/Constraints/closures.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ func test() -> Int? {
793793
}
794794

795795
var fn: () -> [Int] = {}
796-
// expected-error@-1 {{cannot convert value of type '()' to closure result type '[Int]'}}
796+
// expected-error@-1 {{cannot convert value of type '[Int]' to closure result type '()'}}
797797

798798
fn = {}
799799
// expected-error@-1 {{cannot assign value of type '() -> ()' to type '() -> [Int]'}}

test/Constraints/function_builder_diags.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,3 +540,21 @@ func testWrapperBuilder() {
540540

541541
let _: Int = x // expected-error{{cannot convert value of type 'Wrapper<(Double, String)>' to specified type 'Int'}}
542542
}
543+
544+
// rdar://problem/61347993 - empty function builder doesn't compile
545+
func rdar61347993() {
546+
struct Result {}
547+
548+
@_functionBuilder
549+
struct Builder {
550+
static func buildBlock() -> Result {
551+
Result()
552+
}
553+
}
554+
555+
func test_builder<T>(@Builder _: () -> T) {}
556+
test_builder {} // Ok
557+
558+
func test_closure(_: () -> Result) {}
559+
test_closure {} // expected-error {{cannot convert value of type '()' to closure result type 'Result'}}
560+
}

0 commit comments

Comments
 (0)