Skip to content

Commit b14c5bb

Browse files
Merge pull request #59982 from LucianoPAlmeida/sema-closure-return-context
[Sema] Track implicit tuple expr use for closure empty return to improve diagnostic location
2 parents 511bd67 + 44f4eba commit b14c5bb

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ using namespace swift::constraints;
2626
namespace {
2727

2828
// Produce an implicit empty tuple expression.
29-
Expr *getVoidExpr(ASTContext &ctx) {
29+
Expr *getVoidExpr(ASTContext &ctx, SourceLoc contextLoc = SourceLoc()) {
3030
auto *voidExpr = TupleExpr::createEmpty(ctx,
31-
/*LParenLoc=*/SourceLoc(),
32-
/*RParenLoc=*/SourceLoc(),
31+
/*LParenLoc=*/contextLoc,
32+
/*RParenLoc=*/contextLoc,
3333
/*Implicit=*/true);
3434
voidExpr->setType(ctx.TheEmptyTupleType);
3535
return voidExpr;
@@ -885,11 +885,13 @@ class SyntacticElementConstraintGenerator
885885
} else {
886886
// If this is simplify `return`, let's create an empty tuple
887887
// which is also useful if contextual turns out to be e.g. `Void?`.
888-
resultExpr = getVoidExpr(cs.getASTContext());
888+
// Also, attach return stmt source location so if there is a contextual
889+
// mismatch we can produce a diagnostic in a valid source location.
890+
resultExpr = getVoidExpr(cs.getASTContext(), returnStmt->getEndLoc());
889891
}
890892

891893
SolutionApplicationTarget target(resultExpr, context.getAsDeclContext(),
892-
CTP_ReturnStmt, resultType,
894+
CTP_ClosureResult, resultType,
893895
/*isDiscarded=*/false);
894896

895897
if (cs.generateConstraints(target, FreeTypeVariableBinding::Disallow)) {
@@ -898,7 +900,7 @@ class SyntacticElementConstraintGenerator
898900
}
899901

900902
cs.setContextualType(target.getAsExpr(), TypeLoc::withoutLoc(resultType),
901-
CTP_ReturnStmt);
903+
CTP_ClosureResult);
902904
cs.setSolutionApplicationTarget(returnStmt, target);
903905
}
904906

@@ -1508,7 +1510,7 @@ class SyntacticElementSolutionApplication
15081510
// number of times.
15091511
{
15101512
SolutionApplicationTarget target(resultExpr, context.getAsDeclContext(),
1511-
CTP_ReturnStmt, resultType,
1513+
CTP_ClosureResult, resultType,
15121514
/*isDiscarded=*/false);
15131515
cs.setSolutionApplicationTarget(returnStmt, target);
15141516

@@ -1574,7 +1576,7 @@ class SyntacticElementSolutionApplication
15741576

15751577
SolutionApplicationTarget resultTarget(
15761578
resultExpr, context.getAsDeclContext(),
1577-
mode == convertToResult ? CTP_ReturnStmt : CTP_Unused,
1579+
mode == convertToResult ? CTP_ClosureResult : CTP_Unused,
15781580
mode == convertToResult ? resultType : Type(),
15791581
/*isDiscarded=*/false);
15801582
if (auto newResultTarget = rewriteTarget(resultTarget))

test/Constraints/callAsFunction.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ struct Test {
8383
var body8: MyLayout {
8484
MyLayout {
8585
let x = ""
86-
return x // expected-error {{cannot convert return expression of type 'String' to return type 'Int'}}
86+
return x // expected-error {{cannot convert value of type 'String' to closure result type 'Int'}}
8787
} content: {
8888
EmptyView()
8989
}

test/decl/circularity.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Sub: Base {
4141
var foo = { () -> Int in
4242
let x = 42
4343
// FIXME: Bogus diagnostic
44-
return foo(1) // expected-error {{cannot convert return expression of type '()' to return type 'Int'}}
44+
return foo(1) // expected-error {{cannot convert value of type '()' to closure result type 'Int'}}
4545
}()
4646
}
4747

test/expr/closure/closures.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ func testSR13239_ArgsFn() -> Int {
690690
func testSR13239MultiExpr() -> Int {
691691
callit {
692692
print("hello")
693-
return print("hello") // expected-error {{cannot convert return expression of type '()' to return type 'Int'}}
693+
return print("hello") // expected-error {{cannot convert value of type '()' to closure result type 'Int'}}
694694
}
695695
}
696696

@@ -732,3 +732,21 @@ public class TestImplicitCaptureOfExplicitCaptureOfSelfInEscapingClosure {
732732
}
733733
}
734734
}
735+
736+
// https://github.com/apple/swift/issues/59716
737+
["foo"].map { s in
738+
if s == "1" { return } // expected-error{{cannot convert value of type '()' to closure result type 'Bool'}}
739+
return s.isEmpty
740+
}.filter { $0 }
741+
742+
["foo"].map { s in
743+
if s == "1" { return } // expected-error{{cannot convert value of type '()' to closure result type 'Bool'}}
744+
if s == "2" { return }
745+
if s == "3" { return }
746+
return s.isEmpty
747+
}.filter { $0 }
748+
749+
["foo"].map { s in
750+
if s == "1" { return () } // expected-error{{cannot convert value of type '()' to closure result type 'Bool'}}
751+
return s.isEmpty
752+
}.filter { $0 }

0 commit comments

Comments
 (0)