Skip to content

Commit 33cdd33

Browse files
committed
[CS] Account for implicit returns in closures
Avoid defaulting to Void if we have an implicit return from which we can infer the result type.
1 parent 1003b2f commit 33cdd33

File tree

6 files changed

+15
-20
lines changed

6 files changed

+15
-20
lines changed

include/swift/AST/TypeCheckRequests.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -3397,10 +3397,10 @@ class ScopedImportLookupRequest
33973397
bool isCached() const { return true; }
33983398
};
33993399

3400-
/// Determine whether closure body has any explicit `return`
3400+
/// Determine whether closure body has any `return`
34013401
/// statements which could produce a non-void result.
3402-
class ClosureHasExplicitResultRequest
3403-
: public SimpleRequest<ClosureHasExplicitResultRequest, bool(ClosureExpr *),
3402+
class ClosureHasResultExprRequest
3403+
: public SimpleRequest<ClosureHasResultExprRequest, bool(ClosureExpr *),
34043404
RequestFlags::Cached> {
34053405
public:
34063406
using SimpleRequest::SimpleRequest;

include/swift/AST/TypeCheckerTypeIDZone.def

+1-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ SWIFT_REQUEST(TypeChecker, PatternTypeRequest,
444444
Cached, HasNearestLocation)
445445
SWIFT_REQUEST(TypeChecker, ScopedImportLookupRequest,
446446
ArrayRef<ValueDecl *>(ImportDecl *), Cached, NoLocationInfo)
447-
SWIFT_REQUEST(TypeChecker, ClosureHasExplicitResultRequest,
447+
SWIFT_REQUEST(TypeChecker, ClosureHasResultExprRequest,
448448
bool(ClosureExpr *), Cached, NoLocationInfo)
449449
SWIFT_REQUEST(TypeChecker, LookupAllConformancesInContextRequest,
450450
ProtocolConformanceLookupResult(const IterableDeclContext *),

include/swift/Sema/ConstraintSystem.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -6460,9 +6460,9 @@ bool isTypeErasedKeyPathType(Type type);
64606460
/// `{Writable, ReferenceWritable}KeyPath`.
64616461
bool isKnownKeyPathDecl(ASTContext &ctx, ValueDecl *decl);
64626462

6463-
/// Determine whether given closure has any explicit `return`
6463+
/// Determine whether given closure has any `return`
64646464
/// statements that could produce non-void result.
6465-
bool hasExplicitResult(ClosureExpr *closure);
6465+
bool hasResultExpr(ClosureExpr *closure);
64666466

64676467
/// Emit diagnostics for syntactic restrictions within a given solution
64686468
/// application target.

lib/Sema/CSSyntacticElement.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -1135,16 +1135,14 @@ class SyntacticElementConstraintGenerator
11351135
// multi-statement closure.
11361136
if (locator->directlyAt<ClosureExpr>()) {
11371137
auto *closure = context.getAsClosureExpr().get();
1138-
// If this closure has an empty body and no explicit result type
1139-
// let's bind result type to `Void` since that's the only type empty
1140-
// body can produce. Otherwise, if (multi-statement) closure doesn't
1141-
// have an explicit result (no `return` statements) let's default it to
1142-
// `Void`.
1138+
// If this closure has an empty body or no `return` statements with
1139+
// results let's bind result type to `Void` since that's the only type
1140+
// empty body can produce.
11431141
//
11441142
// Note that result builder bodies always have a `return` statement
11451143
// at the end, so they don't need to be defaulted.
11461144
if (!cs.getAppliedResultBuilderTransform({closure}) &&
1147-
!hasExplicitResult(closure)) {
1145+
!hasResultExpr(closure)) {
11481146
auto constraintKind =
11491147
(closure->hasEmptyBody() && !closure->hasExplicitResultType())
11501148
? ConstraintKind::Bind

lib/Sema/ConstraintSystem.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -6671,10 +6671,10 @@ bool constraints::isTypeErasedKeyPathType(Type type) {
66716671
return superclass ? isTypeErasedKeyPathType(superclass) : false;
66726672
}
66736673

6674-
bool constraints::hasExplicitResult(ClosureExpr *closure) {
6674+
bool constraints::hasResultExpr(ClosureExpr *closure) {
66756675
auto &ctx = closure->getASTContext();
6676-
return evaluateOrDefault(ctx.evaluator,
6677-
ClosureHasExplicitResultRequest{closure}, false);
6676+
return evaluateOrDefault(ctx.evaluator, ClosureHasResultExprRequest{closure},
6677+
false);
66786678
}
66796679

66806680
Type constraints::getConcreteReplacementForProtocolSelfType(ValueDecl *member) {

lib/Sema/TypeCheckExpr.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -773,8 +773,8 @@ Expr *CallerSideDefaultArgExprRequest::evaluate(
773773
return initExpr;
774774
}
775775

776-
bool ClosureHasExplicitResultRequest::evaluate(Evaluator &evaluator,
777-
ClosureExpr *closure) const {
776+
bool ClosureHasResultExprRequest::evaluate(Evaluator &evaluator,
777+
ClosureExpr *closure) const {
778778
// A walker that looks for 'return' statements that aren't
779779
// nested within closures or nested declarations.
780780
class FindReturns : public ASTWalker {
@@ -796,9 +796,6 @@ bool ClosureHasExplicitResultRequest::evaluate(Evaluator &evaluator,
796796
PreWalkResult<Stmt *> walkToStmtPre(Stmt *stmt) override {
797797
// Record return statements.
798798
if (auto ret = dyn_cast<ReturnStmt>(stmt)) {
799-
if (ret->isImplicit())
800-
return Action::Continue(stmt);
801-
802799
// If it has a result, remember that we saw one, but keep
803800
// traversing in case there's a no-result return somewhere.
804801
if (ret->hasResult()) {

0 commit comments

Comments
 (0)