Skip to content

Commit 7300fb5

Browse files
[Sema] Improve diagnostic for closure return contextual mismatch
1 parent 76e7cb1 commit 7300fb5

File tree

5 files changed

+20
-17
lines changed

5 files changed

+20
-17
lines changed

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9124,8 +9124,9 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
91249124
// Bodies of single-expression closures use a special locator
91259125
// for contextual type conversion to make sure that result is
91269126
// convertible to `Void` when `return` is not used explicitly.
9127-
if (contextualTypePurpose == CTP_ClosureResult) {
9128-
auto *closure = cast<ClosureExpr>(target.getDeclContext());
9127+
auto *closure = dyn_cast<ClosureExpr>(target.getDeclContext());
9128+
if (closure && closure->hasSingleExpressionBody() &&
9129+
contextualTypePurpose == CTP_ClosureResult) {
91299130
auto *returnStmt =
91309131
castToStmt<ReturnStmt>(closure->getBody()->getLastElement());
91319132

lib/Sema/CSClosure.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -891,8 +891,9 @@ class SyntacticElementConstraintGenerator
891891
return;
892892
}
893893

894+
auto contextualResultInfo = getContextualResultInfo();
894895
cs.addConstraint(ConstraintKind::Conversion, cs.getType(expr),
895-
getContextualResultType(),
896+
contextualResultInfo.getType(),
896897
cs.getConstraintLocator(
897898
context.getAbstractClosureExpr(),
898899
LocatorPathElt::ClosureBody(
@@ -913,8 +914,10 @@ class SyntacticElementConstraintGenerator
913914
resultExpr = getVoidExpr(cs.getASTContext(), returnStmt->getEndLoc());
914915
}
915916

917+
auto contextualResultInfo = getContextualResultInfo();
916918
SolutionApplicationTarget target(resultExpr, context.getAsDeclContext(),
917-
CTP_ReturnStmt, getContextualResultType(),
919+
contextualResultInfo.purpose,
920+
contextualResultInfo.getType(),
918921
/*isDiscarded=*/false);
919922

920923
if (cs.generateConstraints(target, FreeTypeVariableBinding::Disallow)) {
@@ -923,8 +926,8 @@ class SyntacticElementConstraintGenerator
923926
}
924927

925928
cs.setContextualType(target.getAsExpr(),
926-
TypeLoc::withoutLoc(getContextualResultType()),
927-
CTP_ReturnStmt);
929+
TypeLoc::withoutLoc(contextualResultInfo.getType()),
930+
contextualResultInfo.purpose);
928931
cs.setSolutionApplicationTarget(returnStmt, target);
929932
}
930933

@@ -939,15 +942,15 @@ class SyntacticElementConstraintGenerator
939942
return context.hasSingleExpressionBody();
940943
}
941944

942-
Type getContextualResultType() const {
945+
ContextualTypeInfo getContextualResultInfo() const {
943946
if (auto transform = cs.getAppliedResultBuilderTransform(context))
944-
return transform->bodyResultType;
947+
return {transform->bodyResultType, CTP_ReturnStmt};
945948

946949
if (auto *closure =
947950
getAsExpr<ClosureExpr>(context.getAbstractClosureExpr()))
948-
return cs.getClosureType(closure)->getResult();
951+
return {cs.getClosureType(closure)->getResult(), CTP_ClosureResult};
949952

950-
return context.getBodyResultType();
953+
return {context.getBodyResultType(), CTP_ReturnStmt};
951954
}
952955

953956
#define UNSUPPORTED_STMT(STMT) void visit##STMT##Stmt(STMT##Stmt *) { \

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: 4 additions & 5 deletions
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

@@ -734,21 +734,20 @@ public class TestImplicitCaptureOfExplicitCaptureOfSelfInEscapingClosure {
734734
}
735735

736736
// https://github.com/apple/swift/issues/59716
737-
// FIXME: Diagnostic should be tailored for closure result
738737
["foo"].map { s in
739-
if s == "1" { return } // expected-error{{cannot convert return expression of type '()' to return type 'Bool'}}
738+
if s == "1" { return } // expected-error{{cannot convert value of type '()' to closure result type 'Bool'}}
740739
return s.isEmpty
741740
}.filter { $0 }
742741

743742
["foo"].map { s in
744-
if s == "1" { return } // expected-error{{cannot convert return expression of type '()' to return type 'Bool'}}
743+
if s == "1" { return } // expected-error{{cannot convert value of type '()' to closure result type 'Bool'}}
745744
if s == "2" { return }
746745
if s == "3" { return }
747746
return s.isEmpty
748747
}.filter { $0 }
749748

750749
["foo"].map { s in
751-
if s == "1" { return () } // expected-error{{cannot convert return expression of type '()' to return type 'Bool'}}
750+
if s == "1" { return () } // expected-error{{cannot convert value of type '()' to closure result type 'Bool'}}
752751
return s.isEmpty
753752
}.filter { $0 }
754753

0 commit comments

Comments
 (0)