Skip to content

Commit 2c77947

Browse files
authored
Merge pull request #71006 from hamishknight/implicit-last-expression
Introduce implicit last expression results
2 parents 40ff560 + 7b4c9fe commit 2c77947

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1567
-329
lines changed

include/swift/AST/Expr.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6204,12 +6204,19 @@ class SingleValueStmtExpr : public Expr {
62046204
/// SingleValueStmtExpr.
62056205
static SingleValueStmtExpr *tryDigOutSingleValueStmtExpr(Expr *E);
62066206

6207+
/// Whether the last ASTNode in the given BraceStmt can potentially be used as
6208+
/// the implicit result for a SingleValueStmtExpr. If \p mustBeSingleValueStmt
6209+
/// is \c true, a result will be considered even if it may not be valid.
6210+
static bool isLastElementImplicitResult(BraceStmt *BS, ASTContext &ctx,
6211+
bool mustBeSingleValueStmt);
6212+
62076213
/// Retrieves a resulting ThenStmt from the given BraceStmt, or \c nullptr if
62086214
/// the brace does not have a resulting ThenStmt.
62096215
static ThenStmt *getThenStmtFrom(BraceStmt *BS);
62106216

62116217
/// Whether the given BraceStmt has a result to be produced from a parent
6212-
/// SingleValueStmtExpr.
6218+
/// SingleValueStmtExpr. Note this does not consider elements that may
6219+
/// implicitly become results, check \c isLastElementImplicitResult for that.
62136220
static bool hasResult(BraceStmt *BS) {
62146221
return getThenStmtFrom(BS);
62156222
}

include/swift/AST/Stmt.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,8 @@ class ReturnStmt : public Stmt {
269269
return createImplicit(ctx, SourceLoc(), result);
270270
}
271271

272-
/// Create an implicit implied ReturnStmt for a single expression body.
273-
static ReturnStmt *forSingleExprBody(ASTContext &ctx, Expr *result) {
272+
/// Create an implicit implied ReturnStmt for e.g a single expression body.
273+
static ReturnStmt *createImplied(ASTContext &ctx, Expr *result) {
274274
assert(result && "Result must be present to be implied");
275275
auto *RS = createImplicit(ctx, result);
276276
RS->Bits.ReturnStmt.IsImplied = true;

include/swift/AST/TypeCheckRequests.h

Lines changed: 8 additions & 4 deletions
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;
@@ -4258,9 +4258,13 @@ class IsSingleValueStmtResult {
42584258
return InvalidJumps;
42594259
}
42604260

4261-
explicit operator bool() const {
4261+
bool isValid() const {
42624262
return TheKind == Kind::Valid;
42634263
}
4264+
4265+
explicit operator bool() const {
4266+
return isValid();
4267+
}
42644268
};
42654269

42664270
/// Computes whether a given statement can be treated as a SingleValueStmtExpr.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
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/Basic/Features.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,10 @@ EXPERIMENTAL_FEATURE(ThenStatements, false)
231231
/// Enable 'do' expressions.
232232
EXPERIMENTAL_FEATURE(DoExpressions, false)
233233

234+
/// Enable implicitly treating the last expression in a function, closure,
235+
/// and 'if'/'switch' expression as the result.
236+
EXPERIMENTAL_FEATURE(ImplicitLastExprResults, false)
237+
234238
/// Enable the `@_rawLayout` attribute.
235239
EXPERIMENTAL_FEATURE(RawLayout, true)
236240

include/swift/IDE/AfterPoundExprCompletion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace ide {
2626
class AfterPoundExprCompletion : public TypeCheckCompletionCallback {
2727
struct Result {
2828
Type ExpectedTy;
29-
bool IsImplicitSingleExpressionReturn;
29+
bool IsImpliedResult;
3030

3131
/// Whether the surrounding context is async and thus calling async
3232
/// functions is supported.

include/swift/IDE/CodeCompletionContext.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ class CodeCompletionContext {
3939
/// There is no known contextual type. All types are equally good.
4040
None,
4141

42-
/// There is a contextual type from a single-expression closure/function
43-
/// body. The context is a hint, and enables unresolved member completion,
44-
/// but should not hide any results.
45-
SingleExpressionBody,
42+
/// There is a contextual type from e.g a single-expression closure/function
43+
/// body, where the return is implied. The context is a hint, and enables
44+
/// unresolved member completion, but should not hide any results.
45+
Implied,
4646

4747
/// There are known contextual types, or there aren't but a nonvoid type is
4848
/// expected.

include/swift/IDE/CodeCompletionResultType.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ class ExpectedTypeContext {
4444
/// Pre typechecked type of the expression at the completion position.
4545
Type IdealType;
4646

47-
/// Whether the `ExpectedTypes` comes from a single-expression body, e.g.
47+
/// Whether the `ExpectedTypes` comes from an implied result, e.g.
4848
/// `foo({ here })`.
4949
///
5050
/// Since the input may be incomplete, we take into account that the types are
5151
/// only a hint.
52-
bool IsImplicitSingleExpressionReturn = false;
52+
bool IsImpliedResult = false;
5353
bool PreferNonVoid = false;
5454

5555
/// If not empty, \c PossibleTypes are ignored and types that have an
@@ -86,7 +86,7 @@ class ExpectedTypeContext {
8686
if (!IdealType || !Other.IdealType || !IdealType->isEqual(Other.IdealType)) {
8787
IdealType = Type();
8888
}
89-
IsImplicitSingleExpressionReturn |= Other.IsImplicitSingleExpressionReturn;
89+
IsImpliedResult |= Other.IsImpliedResult;
9090
PreferNonVoid &= Other.PreferNonVoid;
9191
ExpectedCustomAttributeKinds |= Other.ExpectedCustomAttributeKinds;
9292
}
@@ -96,7 +96,7 @@ class ExpectedTypeContext {
9696
void setIdealType(Type IdealType) { this->IdealType = IdealType; }
9797

9898
bool requiresNonVoid() const {
99-
if (IsImplicitSingleExpressionReturn)
99+
if (IsImpliedResult)
100100
return false;
101101
if (PreferNonVoid)
102102
return true;
@@ -105,13 +105,12 @@ class ExpectedTypeContext {
105105
return llvm::all_of(PossibleTypes, [](Type Ty) { return !Ty->isVoid(); });
106106
}
107107

108-
bool isImplicitSingleExpressionReturn() const {
109-
return IsImplicitSingleExpressionReturn;
108+
bool isImpliedResult() const {
109+
return IsImpliedResult;
110110
}
111111

112-
void
113-
setIsImplicitSingleExpressionReturn(bool IsImplicitSingleExpressionReturn) {
114-
this->IsImplicitSingleExpressionReturn = IsImplicitSingleExpressionReturn;
112+
void setIsImpliedResult(bool IsImpliedResult) {
113+
this->IsImpliedResult = IsImpliedResult;
115114
}
116115

117116
bool getPreferNonVoid() const { return PreferNonVoid; }

include/swift/IDE/CompletionLookup.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
234234
void setIsStaticMetatype(bool value) { IsStaticMetatype = value; }
235235

236236
void setExpectedTypes(
237-
ArrayRef<Type> Types, bool isImplicitSingleExpressionReturn,
238-
bool preferNonVoid = false,
237+
ArrayRef<Type> Types, bool isImpliedResult, bool preferNonVoid = false,
239238
OptionSet<CustomAttributeKind> expectedCustomAttributeKinds = {}) {
240-
expectedTypeContext.setIsImplicitSingleExpressionReturn(
241-
isImplicitSingleExpressionReturn);
239+
expectedTypeContext.setIsImpliedResult(isImpliedResult);
242240
expectedTypeContext.setPreferNonVoid(preferNonVoid);
243241
expectedTypeContext.setPossibleTypes(Types);
244242
expectedTypeContext.setExpectedCustomAttributeKinds(
@@ -269,8 +267,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
269267
if (expectedTypeContext.empty() &&
270268
!expectedTypeContext.getPreferNonVoid()) {
271269
return CodeCompletionContext::TypeContextKind::None;
272-
} else if (expectedTypeContext.isImplicitSingleExpressionReturn()) {
273-
return CodeCompletionContext::TypeContextKind::SingleExpressionBody;
270+
} else if (expectedTypeContext.isImpliedResult()) {
271+
return CodeCompletionContext::TypeContextKind::Implied;
274272
} else {
275273
return CodeCompletionContext::TypeContextKind::Required;
276274
}

include/swift/IDE/ExprCompletion.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ namespace ide {
2323
class ExprTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
2424
public:
2525
struct Result {
26-
/// If the code completion expression is an implicit return in a
26+
/// If the code completion expression is an implied result, e.g in a
2727
/// single-expression closure.
28-
bool IsImplicitSingleExpressionReturn;
28+
bool IsImpliedResult;
2929

3030
/// Whether the surrounding context is async and thus calling async
3131
/// functions is supported.
@@ -75,7 +75,7 @@ class ExprTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
7575
/// If \c AddUnresolvedMemberCompletions is false, the
7676
/// \p UnresolvedMemberBaseType is ignored.
7777
void addResult(
78-
bool IsImplicitSingleExpressionReturn, bool IsInAsyncContext,
78+
bool IsImpliedResult, bool IsInAsyncContext,
7979
Type UnresolvedMemberBaseType,
8080
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes);
8181

0 commit comments

Comments
 (0)