Skip to content

Commit 9e42002

Browse files
Merge pull request #60952 from LucianoPAlmeida/diag-closure
2 parents 65ef6ea + 7b82be5 commit 9e42002

File tree

6 files changed

+68
-18
lines changed

6 files changed

+68
-18
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: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
22

33
var func6 : (_ fn : (Int,Int) -> Int) -> ()
44
var func6a : ((Int, Int) -> Int) -> ()
@@ -690,7 +690,7 @@ func test_55680_ArgsFn() -> Int {
690690
func test_55680_MultiExpr() -> 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,24 +734,39 @@ 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

754+
func producer<T>(_ f: (String) -> T) -> T {}
755+
func f59716() -> some BinaryInteger { // expected-note{{required by opaque return type of global function 'f59716()'}}
756+
// expected-note@+1{{only concrete types such as structs, enums and classes can conform to protocols}}
757+
return producer { s in // expected-error{{type '()' cannot conform to 'BinaryInteger'}}
758+
if s == "1" { return }
759+
return s.count // expected-error{{cannot convert value of type 'Int' to closure result type '()'}}
760+
}
761+
}
762+
763+
func f59716_1() -> some BinaryInteger {
764+
return producer { s in
765+
if s == "1" { return 1 }
766+
return s.count
767+
}
768+
}
769+
755770
// https://github.com/apple/swift/issues/60781
756771
func f60781<T>(_ x: T) -> T { x }
757772
func f60781<T>(_ x: T, _ y: T) -> T { x }
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 -swift-version 5 -enable-experimental-feature ResultBuilderASTTransform
2+
// REQUIRES: OS=macosx
3+
4+
import SwiftUI
5+
6+
protocol TestLayout {}
7+
extension TestLayout {
8+
func callAsFunction<V: View>(_ f: () -> V) -> some View {
9+
return f()
10+
}
11+
}
12+
struct EqualWitdthHStack : TestLayout {}
13+
extension EqualWitdthHStack: View {
14+
var body : some View {
15+
Spacer()
16+
}
17+
}
18+
19+
struct EmptyView: View {
20+
var body : some View {
21+
Spacer()
22+
}
23+
}
24+
25+
struct MyView: View {
26+
var body : some View {
27+
EqualWitdthHStack {
28+
EmptyView()
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)