Skip to content

Commit ca6cf0c

Browse files
xedinnate-chandler
authored andcommitted
[ConstraintSystem] Use special locator for expr representing return of single expr function
1 parent 448e04e commit ca6cf0c

File tree

4 files changed

+36
-10
lines changed

4 files changed

+36
-10
lines changed

Diff for: lib/Sema/CSApply.cpp

+10-2
Original file line numberDiff line numberDiff line change
@@ -7696,10 +7696,18 @@ Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,
76967696
if (hadError)
76977697
return nullptr;
76987698
}
7699-
7699+
7700+
// We are supposed to use contextual type only if it is present and
7701+
// this expression doesn't represent the implicit return of the single
7702+
// expression function which got deduced to be `Never`.
7703+
auto shouldCoerceToContextualType = [&]() {
7704+
return convertType && !(getType(result)->isUninhabited() &&
7705+
getContextualTypePurpose() == CTP_ReturnSingleExpr);
7706+
};
7707+
77007708
// If we're supposed to convert the expression to some particular type,
77017709
// do so now.
7702-
if (convertType) {
7710+
if (shouldCoerceToContextualType()) {
77037711
result = rewriter.coerceToType(result, convertType,
77047712
getConstraintLocator(expr));
77057713
if (!result)

Diff for: lib/Sema/CSSimplify.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -2793,9 +2793,11 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
27932793
}
27942794

27952795
// Allow '() -> T' to '() -> ()' and '() -> Never' to '() -> T' for closure
2796-
// literals.
2796+
// literals and expressions representing an implicit return type of the single
2797+
// expression functions.
27972798
if (auto elt = locator.last()) {
2798-
if (elt->getKind() == ConstraintLocator::ClosureResult) {
2799+
if (elt->getKind() == ConstraintLocator::ClosureResult ||
2800+
elt->getKind() == ConstraintLocator::SingleExprFuncResultType) {
27992801
if (kind >= ConstraintKind::Subtype &&
28002802
(type1->isUninhabited() || type2->isVoid())) {
28012803
increaseScore(SK_FunctionConversion);

Diff for: lib/Sema/CSSolver.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -1162,16 +1162,16 @@ ConstraintSystem::solveImpl(Expr *&expr,
11621162

11631163
if (getContextualTypePurpose() == CTP_CallArgument)
11641164
constraintKind = ConstraintKind::ArgumentConversion;
1165-
else if (getContextualTypePurpose() == CTP_ReturnSingleExpr)
1166-
constraintKind = ConstraintKind::SingleExpressionFunctionReturnConversion;
11671165

11681166
// In a by-reference yield, we expect the contextual type to be an
11691167
// l-value type, so the result must be bound to that.
11701168
if (getContextualTypePurpose() == CTP_YieldByReference)
11711169
constraintKind = ConstraintKind::Bind;
11721170

11731171
auto *convertTypeLocator = getConstraintLocator(
1174-
getConstraintLocator(expr), ConstraintLocator::ContextualType);
1172+
expr, getContextualTypePurpose() == CTP_ReturnSingleExpr
1173+
? ConstraintLocator::SingleExprFuncResultType
1174+
: ConstraintLocator::ContextualType);
11751175

11761176
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
11771177
convertType = convertType.transform([&](Type type) -> Type {

Diff for: lib/Sema/TypeCheckStmt.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
493493
}
494494

495495
ContextualTypePurpose ctp = CTP_ReturnStmt;
496-
if (auto func = dyn_cast_or_null<FuncDecl>(TheFunc->getAbstractFunctionDecl())) {
496+
if (auto func =
497+
dyn_cast_or_null<FuncDecl>(TheFunc->getAbstractFunctionDecl())) {
497498
if (func->hasSingleExpressionBody()) {
498499
ctp = CTP_ReturnSingleExpr;
499500
}
@@ -502,7 +503,6 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
502503
auto exprTy = TC.typeCheckExpression(E, DC, TypeLoc::withoutLoc(ResultTy),
503504
ctp,
504505
options);
505-
506506
RS->setResult(E);
507507

508508
if (!exprTy) {
@@ -1921,7 +1921,7 @@ bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
19211921
// The function returns void. We don't need an explicit return, no matter
19221922
// what the type of the expression is. Take the inserted return back out.
19231923
BS->setElement(0, E);
1924-
// Fall through to type-checking the body as if we were not a single
1924+
// Fall through to type-checking the body as if we were not a single
19251925
// expression function.
19261926
}
19271927
}
@@ -1930,6 +1930,22 @@ bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
19301930
SC.EndTypeCheckLoc = EndTypeCheckLoc;
19311931
bool HadError = SC.typeCheckBody(BS);
19321932

1933+
// If this was a function with a single expression body, let's see
1934+
// if implicit return statement came out to be `Never` which means
1935+
// that we have eagerly converted something like `{ fatalError() }`
1936+
// into `{ return fatalError() }` that has to be corrected here.
1937+
if (FD->hasSingleExpressionBody()) {
1938+
if (auto *stmt = BS->getElement(0).dyn_cast<Stmt *>()) {
1939+
if (auto *RS = dyn_cast<ReturnStmt>(stmt)) {
1940+
if (RS->isImplicit() && RS->hasResult()) {
1941+
auto returnType = RS->getResult()->getType();
1942+
if (returnType && returnType->isUninhabited())
1943+
BS->setElement(0, RS->getResult());
1944+
}
1945+
}
1946+
}
1947+
}
1948+
19331949
FD->setBody(BS);
19341950
return HadError;
19351951
}

0 commit comments

Comments
 (0)