Skip to content

Commit 64d4e30

Browse files
committed
Used a constraint system, not typeCheckExpression.
1 parent 74b462b commit 64d4e30

File tree

2 files changed

+134
-11
lines changed

2 files changed

+134
-11
lines changed

Diff for: lib/Sema/TypeCheckStmt.cpp

+21-11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "TypeChecker.h"
1818
#include "TypeCheckType.h"
1919
#include "MiscDiagnostics.h"
20+
#include "ConstraintSystem.h"
2021
#include "swift/Subsystems.h"
2122
#include "swift/AST/ASTPrinter.h"
2223
#include "swift/AST/ASTWalker.h"
@@ -1908,7 +1909,8 @@ bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
19081909
// FIXME: FIXME_NOW: DETERMINE: What is the appropriate place for this code to
19091910
// live?
19101911
if (FD->hasSingleExpressionBody()) {
1911-
auto fnType = FD->getBodyResultTypeLoc().getType();
1912+
auto fnTypeLoc = FD->getBodyResultTypeLoc();
1913+
auto fnType = fnTypeLoc.getType();
19121914
auto returnStmt = cast<ReturnStmt>(BS->getElement(0).get<Stmt *>());
19131915
auto E = returnStmt->getResult();
19141916

@@ -1920,7 +1922,7 @@ bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
19201922
// FD->setSingleExpressionBody(E);
19211923
// }
19221924

1923-
if (FD->getBodyResultTypeLoc().isNull() || fnType->isVoid()) {
1925+
if (fnTypeLoc.isNull() || fnType->isVoid()) {
19241926
auto voidExpr = TupleExpr::createEmpty(Context,
19251927
E->getStartLoc(),
19261928
E->getEndLoc(),
@@ -1934,15 +1936,23 @@ bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
19341936
} else {
19351937
// FIXME: FIXME_NOW: DETERMINE: Is this the appropriate mechanism to use
19361938
// to divine the type of E?
1937-
auto exprTy = typeCheckExpression(E, FD, TypeLoc(),
1938-
CTP_ReturnStmt);
1939-
if (!exprTy.isNull() && exprTy->isUninhabited() &&
1940-
exprTy->getCanonicalType() != fnType->getCanonicalType()) {
1941-
BS = BraceStmt::create(Context,
1942-
BS->getStartLoc(),
1943-
{ E },
1944-
BS->getEndLoc(),
1945-
/*implicit=*/true);
1939+
preCheckExpression(E, FD);
1940+
constraints::ConstraintSystem cs(*this, FD,
1941+
constraints::ConstraintSystemFlags::SuppressDiagnostics);
1942+
SmallVector<constraints::Solution, 4> viable;
1943+
if(!cs.solve(E, /*convertType*/Type(), nullptr, viable,
1944+
FreeTypeVariableBinding::Disallow)) {
1945+
auto &solution = viable[0];
1946+
auto &solutionCS = solution.getConstraintSystem();
1947+
Type exprType = solution.simplifyType(solutionCS.getType(E));
1948+
if (!exprType.isNull() && exprType->isUninhabited() &&
1949+
exprType->getCanonicalType() != fnType->getCanonicalType()) {
1950+
BS = BraceStmt::create(Context,
1951+
BS->getStartLoc(),
1952+
{ E },
1953+
BS->getEndLoc(),
1954+
/*implicit=*/true);
1955+
}
19461956
}
19471957
}
19481958
}

Diff for: test/Parse/omit_return.swift

+113
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@ func myOwnFatalError() -> MyOwnNever { fatalError() }
3434

3535
func identity<T>(_ t: T) -> T { t }
3636

37+
internal func _fatalErrorFlags() -> UInt32 {
38+
return 0
39+
}
40+
internal func _assertionFailure(
41+
_ prefix: StaticString, _ message: String,
42+
flags: UInt32
43+
) -> Never {
44+
fatalError()
45+
}
46+
internal func _diagnoseUnexpectedEnumCaseValue<SwitchedValue, RawValue>(
47+
type: SwitchedValue.Type,
48+
rawValue: RawValue
49+
) -> Never {
50+
_assertionFailure("Fatal error",
51+
"unexpected enum case '\(type)(rawValue: \(rawValue))'",
52+
flags: _fatalErrorFlags())
53+
}
3754

3855

3956
// MARK: - Free Functions
@@ -62,6 +79,22 @@ func ff_implicitClosure() -> () -> Void {
6279
{ print("howdy") }
6380
}
6481

82+
func ff_explicitMultilineClosure() -> () -> String {
83+
return {
84+
let one = "big a"
85+
let two = "little a"
86+
return "\(one) + \(two)"
87+
}
88+
}
89+
90+
func ff_implicitMultilineClosure() -> () -> String {
91+
{
92+
let one = "big a"
93+
let two = "little a"
94+
return "\(one) + \(two)"
95+
}
96+
}
97+
6598
func ff_implicitWrong() -> String {
6699
17 // expected-error {{cannot convert return expression of type 'Int' to return type 'String'}}
67100
}
@@ -242,6 +275,22 @@ var fv_implicitClosure: () -> Void {
242275
{ print("howdy") }
243276
}
244277

278+
var fv_explicitMultilineClosure: () -> String {
279+
return {
280+
let one = "big a"
281+
let two = "little a"
282+
return "\(one) + \(two)"
283+
}
284+
}
285+
286+
var fv_implicitMultilineClosure: () -> String {
287+
{
288+
let one = "big a"
289+
let two = "little a"
290+
return "\(one) + \(two)"
291+
}
292+
}
293+
245294
var fv_implicitWrong: String {
246295
17 // expected-error {{cannot convert return expression of type 'Int' to return type 'String'}}
247296
}
@@ -400,6 +449,26 @@ var fvg_implicitClosure: () -> Void {
400449
}
401450
}
402451

452+
var fvg_explicitMultilineClosure: () -> String {
453+
get {
454+
return {
455+
let one = "big a"
456+
let two = "little a"
457+
return "\(one) + \(two)"
458+
}
459+
}
460+
}
461+
462+
var fvg_implicitMultilineClosure: () -> String {
463+
get {
464+
{
465+
let one = "big a"
466+
let two = "little a"
467+
return "\(one) + \(two)"
468+
}
469+
}
470+
}
471+
403472
var fvg_implicitWrong: String {
404473
get {
405474
17 // expected-error {{cannot convert return expression of type 'Int' to return type 'String'}}
@@ -726,6 +795,26 @@ enum S_implicitClosure {
726795
}
727796
}
728797

798+
enum S_explicitMultilineClosure {
799+
subscript() -> () -> String {
800+
return {
801+
let one = "big a"
802+
let two = "little a"
803+
return "\(one) + \(two)"
804+
}
805+
}
806+
}
807+
808+
enum S_implicitMultilineClosure {
809+
subscript() -> () -> String {
810+
{
811+
let one = "big a"
812+
let two = "little a"
813+
return "\(one) + \(two)"
814+
}
815+
}
816+
}
817+
729818
enum S_implicitWrong {
730819
subscript() -> String {
731820
17 // expected-error {{cannot convert return expression of type 'Int' to return type 'String'}}
@@ -932,6 +1021,30 @@ enum SRO_implicitClosure {
9321021
}
9331022
}
9341023

1024+
enum SRO_explicitMultilineClosure {
1025+
subscript() -> () -> String {
1026+
get {
1027+
return {
1028+
let one = "big a"
1029+
let two = "little a"
1030+
return "\(one) + \(two)"
1031+
}
1032+
}
1033+
}
1034+
}
1035+
1036+
enum SRO_implicitMultilineClosure {
1037+
subscript() -> () -> String {
1038+
get {
1039+
{
1040+
let one = "big a"
1041+
let two = "little a"
1042+
return "\(one) + \(two)"
1043+
}
1044+
}
1045+
}
1046+
}
1047+
9351048
enum SRO_implicitWrong {
9361049
subscript() -> String {
9371050
get {

0 commit comments

Comments
 (0)