Skip to content

Commit d4b690c

Browse files
authored
Merge pull request #61302 from jckarter/single-closure-for-all-static-partial-applications
Sema: Form all static member partial applications with one closure
2 parents eb47d40 + cef7ecc commit d4b690c

16 files changed

+129
-138
lines changed

include/swift/AST/ASTScope.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
203203

204204
#pragma mark common queries
205205
public:
206-
virtual NullablePtr<ClosureExpr> getClosureIfClosureScope() const;
206+
virtual NullablePtr<AbstractClosureExpr> getClosureIfClosureScope() const;
207207
virtual ASTContext &getASTContext() const;
208208
virtual NullablePtr<Decl> getDeclIfAny() const { return nullptr; };
209209
virtual NullablePtr<Stmt> getStmtIfAny() const { return nullptr; };
@@ -1032,17 +1032,17 @@ class CaptureListScope final : public ASTScopeImpl {
10321032
/// For a closure with named parameters, this scope does the local bindings.
10331033
class ClosureParametersScope final : public ASTScopeImpl {
10341034
public:
1035-
ClosureExpr *const closureExpr;
1035+
AbstractClosureExpr *const closureExpr;
10361036

1037-
ClosureParametersScope(ClosureExpr *closureExpr)
1037+
ClosureParametersScope(AbstractClosureExpr *closureExpr)
10381038
: closureExpr(closureExpr) {}
10391039
virtual ~ClosureParametersScope() {}
10401040

10411041
std::string getClassName() const override;
10421042
SourceRange
10431043
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
10441044

1045-
NullablePtr<ClosureExpr> getClosureIfClosureScope() const override {
1045+
NullablePtr<AbstractClosureExpr> getClosureIfClosureScope() const override {
10461046
return closureExpr;
10471047
}
10481048
NullablePtr<Expr> getExprIfAny() const override { return closureExpr; }
@@ -1541,7 +1541,7 @@ class BraceStmtScope final : public AbstractStmtScope {
15411541
SourceRange
15421542
getSourceRangeOfThisASTNode(bool omitAssertions = false) const override;
15431543

1544-
NullablePtr<ClosureExpr> parentClosureIfAny() const; // public??
1544+
NullablePtr<AbstractClosureExpr> parentClosureIfAny() const; // public??
15451545
Stmt *getStmt() const override { return stmt; }
15461546

15471547
protected:

include/swift/AST/Expr.h

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4144,10 +4144,10 @@ class CaptureListExpr final : public Expr,
41444144
private llvm::TrailingObjects<CaptureListExpr, CaptureListEntry> {
41454145
friend TrailingObjects;
41464146

4147-
ClosureExpr *closureBody;
4147+
AbstractClosureExpr *closureBody;
41484148

41494149
CaptureListExpr(ArrayRef<CaptureListEntry> captureList,
4150-
ClosureExpr *closureBody)
4150+
AbstractClosureExpr *closureBody)
41514151
: Expr(ExprKind::CaptureList, /*Implicit=*/false, Type()),
41524152
closureBody(closureBody) {
41534153
Bits.CaptureListExpr.NumCaptures = captureList.size();
@@ -4158,16 +4158,16 @@ class CaptureListExpr final : public Expr,
41584158
public:
41594159
static CaptureListExpr *create(ASTContext &ctx,
41604160
ArrayRef<CaptureListEntry> captureList,
4161-
ClosureExpr *closureBody);
4161+
AbstractClosureExpr *closureBody);
41624162

41634163
ArrayRef<CaptureListEntry> getCaptureList() {
41644164
return {getTrailingObjects<CaptureListEntry>(),
41654165
Bits.CaptureListExpr.NumCaptures};
41664166
}
4167-
ClosureExpr *getClosureBody() { return closureBody; }
4168-
const ClosureExpr *getClosureBody() const { return closureBody; }
4167+
AbstractClosureExpr *getClosureBody() { return closureBody; }
4168+
const AbstractClosureExpr *getClosureBody() const { return closureBody; }
41694169

4170-
void setClosureBody(ClosureExpr *body) { closureBody = body; }
4170+
void setClosureBody(AbstractClosureExpr *body) { closureBody = body; }
41714171

41724172
/// This is a bit weird, but the capture list is lexically contained within
41734173
/// the closure, so the ClosureExpr has the full source range.
@@ -5389,10 +5389,6 @@ class KeyPathExpr : public Expr {
53895389
/// a contextual root type.
53905390
bool HasLeadingDot = false;
53915391

5392-
/// When we parse a key path literal, we claim a closure discriminator for it, since it may be used as
5393-
/// a closure value in function type context.
5394-
unsigned ClosureDiscriminator;
5395-
53965392
public:
53975393
/// A single stored component, which will be one of:
53985394
/// - an unresolved DeclNameRef, which has to be type-checked
@@ -5724,12 +5720,11 @@ class KeyPathExpr : public Expr {
57245720

57255721
KeyPathExpr(SourceLoc startLoc, Expr *parsedRoot, Expr *parsedPath,
57265722
SourceLoc endLoc, bool hasLeadingDot, bool isObjC,
5727-
bool isImplicit, unsigned closureDiscriminator);
5723+
bool isImplicit);
57285724

57295725
/// Create a key path with unresolved root and path expressions.
57305726
KeyPathExpr(SourceLoc backslashLoc, Expr *parsedRoot, Expr *parsedPath,
5731-
bool hasLeadingDot, bool isImplicit,
5732-
unsigned closureDiscriminator);
5727+
bool hasLeadingDot, bool isImplicit);
57335728

57345729
/// Create a key path with components.
57355730
KeyPathExpr(ASTContext &ctx, SourceLoc startLoc,
@@ -5740,8 +5735,7 @@ class KeyPathExpr : public Expr {
57405735
/// Create a new parsed Swift key path expression.
57415736
static KeyPathExpr *createParsed(ASTContext &ctx, SourceLoc backslashLoc,
57425737
Expr *parsedRoot, Expr *parsedPath,
5743-
bool hasLeadingDot,
5744-
unsigned closureDiscriminator = AbstractClosureExpr::InvalidDiscriminator);
5738+
bool hasLeadingDot);
57455739

57465740
/// Create a new parsed #keyPath expression.
57475741
static KeyPathExpr *createParsedPoundKeyPath(ASTContext &ctx,
@@ -5836,9 +5830,6 @@ class KeyPathExpr : public Expr {
58365830
/// True if this key path expression has a leading dot.
58375831
bool expectsContextualRoot() const { return HasLeadingDot; }
58385832

5839-
/// Return the discriminator to use if this key path becomes a closure.
5840-
unsigned getClosureDiscriminator() const { return ClosureDiscriminator; }
5841-
58425833
static bool classof(const Expr *E) {
58435834
return E->getKind() == ExprKind::KeyPath;
58445835
}

lib/AST/ASTScope.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ Pattern *AbstractPatternEntryScope::getPattern() const {
8383
return getPatternEntry().getPattern();
8484
}
8585

86-
NullablePtr<ClosureExpr> BraceStmtScope::parentClosureIfAny() const {
86+
NullablePtr<AbstractClosureExpr> BraceStmtScope::parentClosureIfAny() const {
8787
return !getParent() ? nullptr : getParent().get()->getClosureIfClosureScope();
8888
}
8989

90-
NullablePtr<ClosureExpr> ASTScopeImpl::getClosureIfClosureScope() const {
90+
NullablePtr<AbstractClosureExpr> ASTScopeImpl::getClosureIfClosureScope() const {
9191
return nullptr;
9292
}
9393

lib/AST/ASTScopeSourceRange.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,12 @@ SourceRange
283283
BraceStmtScope::getSourceRangeOfThisASTNode(const bool omitAssertions) const {
284284
// The brace statements that represent closures start their scope at the
285285
// 'in' keyword, when present.
286-
if (auto closure = parentClosureIfAny()) {
287-
if (closure.get()->getInLoc().isValid())
288-
return SourceRange(closure.get()->getInLoc(), endLoc);
286+
if (auto anyClosure = parentClosureIfAny()) {
287+
if (auto closure = dyn_cast<ClosureExpr>(parentClosureIfAny().get())) {
288+
if (closure->getInLoc().isValid()) {
289+
return SourceRange(closure->getInLoc(), endLoc);
290+
}
291+
}
289292
}
290293
return SourceRange(stmt->getStartLoc(), endLoc);
291294
}
@@ -302,7 +305,10 @@ SourceRange ConditionalClausePatternUseScope::getSourceRangeOfThisASTNode(
302305

303306
SourceRange
304307
CaptureListScope::getSourceRangeOfThisASTNode(const bool omitAssertions) const {
305-
auto *closureExpr = expr->getClosureBody();
308+
if (auto autoClosure = dyn_cast<AutoClosureExpr>(expr->getClosureBody())) {
309+
return autoClosure->getSourceRange();
310+
}
311+
auto closureExpr = cast<ClosureExpr>(expr->getClosureBody());
306312
if (!omitAssertions)
307313
ASTScopeAssert(closureExpr->getInLoc().isValid(),
308314
"We don't create these if no in loc");
@@ -311,10 +317,16 @@ CaptureListScope::getSourceRangeOfThisASTNode(const bool omitAssertions) const {
311317

312318
SourceRange ClosureParametersScope::getSourceRangeOfThisASTNode(
313319
const bool omitAssertions) const {
314-
if (closureExpr->getInLoc().isValid())
315-
return SourceRange(closureExpr->getInLoc(), closureExpr->getEndLoc());
320+
if (auto autoClosure = dyn_cast<AutoClosureExpr>(closureExpr)) {
321+
return autoClosure->getSourceRange();
322+
}
323+
auto explicitClosureExpr = cast<ClosureExpr>(closureExpr);
324+
if (explicitClosureExpr->getInLoc().isValid()) {
325+
return SourceRange(explicitClosureExpr->getInLoc(),
326+
explicitClosureExpr->getEndLoc());
327+
}
316328

317-
return closureExpr->getSourceRange();
329+
return explicitClosureExpr->getSourceRange();
318330
}
319331

320332
SourceRange AttachedPropertyWrapperScope::getSourceRangeOfThisASTNode(

lib/AST/ASTWalker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,8 +863,8 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
863863
}
864864
}
865865

866-
ClosureExpr *body = expr->getClosureBody();
867-
if ((body = cast_or_null<ClosureExpr>(doIt(body))))
866+
AbstractClosureExpr *body = expr->getClosureBody();
867+
if ((body = cast_or_null<AbstractClosureExpr>(doIt(body))))
868868
expr->setClosureBody(body);
869869
else
870870
return nullptr;

lib/AST/Expr.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,7 @@ bool CaptureListEntry::isSimpleSelfCapture() const {
13021302

13031303
CaptureListExpr *CaptureListExpr::create(ASTContext &ctx,
13041304
ArrayRef<CaptureListEntry> captureList,
1305-
ClosureExpr *closureBody) {
1305+
AbstractClosureExpr *closureBody) {
13061306
auto size = totalSizeToAlloc<CaptureListEntry>(captureList.size());
13071307
auto mem = ctx.Allocate(size, alignof(CaptureListExpr));
13081308
auto *expr = ::new(mem) CaptureListExpr(captureList, closureBody);
@@ -2252,24 +2252,21 @@ OpenedArchetypeType *OpenExistentialExpr::getOpenedArchetype() const {
22522252

22532253
KeyPathExpr::KeyPathExpr(SourceLoc startLoc, Expr *parsedRoot,
22542254
Expr *parsedPath, SourceLoc endLoc, bool hasLeadingDot,
2255-
bool isObjC, bool isImplicit,
2256-
unsigned closureDiscriminator)
2255+
bool isObjC, bool isImplicit)
22572256
: Expr(ExprKind::KeyPath, isImplicit), StartLoc(startLoc), EndLoc(endLoc),
22582257
ParsedRoot(parsedRoot), ParsedPath(parsedPath),
2259-
HasLeadingDot(hasLeadingDot), ClosureDiscriminator(closureDiscriminator) {
2258+
HasLeadingDot(hasLeadingDot) {
22602259
assert(!(isObjC && (parsedRoot || parsedPath)) &&
22612260
"Obj-C key paths should only have components");
22622261
Bits.KeyPathExpr.IsObjC = isObjC;
22632262
}
22642263

22652264
KeyPathExpr::KeyPathExpr(SourceLoc backslashLoc, Expr *parsedRoot,
2266-
Expr *parsedPath, bool hasLeadingDot, bool isImplicit,
2267-
unsigned closureDiscriminator)
2265+
Expr *parsedPath, bool hasLeadingDot, bool isImplicit)
22682266
: KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
22692267
parsedPath ? parsedPath->getEndLoc()
22702268
: parsedRoot->getEndLoc(),
2271-
hasLeadingDot, /*isObjC*/ false, isImplicit,
2272-
closureDiscriminator) {
2269+
hasLeadingDot, /*isObjC*/ false, isImplicit) {
22732270
assert((parsedRoot || parsedPath) &&
22742271
"Key path must have either root or path");
22752272
}
@@ -2278,8 +2275,7 @@ KeyPathExpr::KeyPathExpr(ASTContext &ctx, SourceLoc startLoc,
22782275
ArrayRef<Component> components, SourceLoc endLoc,
22792276
bool isObjC, bool isImplicit)
22802277
: KeyPathExpr(startLoc, /*parsedRoot*/ nullptr, /*parsedPath*/ nullptr,
2281-
endLoc, /*hasLeadingDot*/ false, isObjC, isImplicit,
2282-
/*closure discriminator*/ AbstractClosureExpr::InvalidDiscriminator) {
2278+
endLoc, /*hasLeadingDot*/ false, isObjC, isImplicit) {
22832279
assert(!components.empty());
22842280
Components = ctx.AllocateCopy(components);
22852281
}
@@ -2293,11 +2289,9 @@ KeyPathExpr *KeyPathExpr::createParsedPoundKeyPath(
22932289

22942290
KeyPathExpr *KeyPathExpr::createParsed(ASTContext &ctx, SourceLoc backslashLoc,
22952291
Expr *parsedRoot, Expr *parsedPath,
2296-
bool hasLeadingDot,
2297-
unsigned closureDiscriminator) {
2292+
bool hasLeadingDot) {
22982293
return new (ctx) KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
2299-
hasLeadingDot, /*isImplicit*/ false,
2300-
closureDiscriminator);
2294+
hasLeadingDot, /*isImplicit*/ false);
23012295
}
23022296

23032297
KeyPathExpr *KeyPathExpr::createImplicit(ASTContext &ctx,
@@ -2313,8 +2307,7 @@ KeyPathExpr *KeyPathExpr::createImplicit(ASTContext &ctx,
23132307
Expr *parsedRoot, Expr *parsedPath,
23142308
bool hasLeadingDot) {
23152309
return new (ctx) KeyPathExpr(backslashLoc, parsedRoot, parsedPath,
2316-
hasLeadingDot, /*isImplicit*/ true,
2317-
/*closureDiscriminator*/ AbstractClosureExpr::InvalidDiscriminator);
2310+
hasLeadingDot, /*isImplicit*/ true);
23182311
}
23192312

23202313
void

lib/IDE/Formatting.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ static ClosureExpr *findTrailingClosureFromArgument(Expr *arg) {
140140
if (auto TC = dyn_cast_or_null<ClosureExpr>(arg))
141141
return TC;
142142
if (auto TCL = dyn_cast_or_null<CaptureListExpr>(arg))
143-
return TCL->getClosureBody();
143+
return dyn_cast_or_null<ClosureExpr>(TCL->getClosureBody());
144144
return nullptr;
145145
}
146146

@@ -2484,7 +2484,7 @@ class FormatWalker : public ASTWalker {
24842484
Optional<IndentContext>
24852485
getIndentContextFrom(CaptureListExpr *CL,
24862486
SourceLoc ContextLoc = SourceLoc()) {
2487-
ClosureExpr *CE = CL->getClosureBody();
2487+
AbstractClosureExpr *CE = CL->getClosureBody();
24882488
BraceStmt *BS = CE->getBody();
24892489
if (!CE || !BS)
24902490
return None;
@@ -2499,8 +2499,14 @@ class FormatWalker : public ASTWalker {
24992499
}
25002500

25012501
Optional<IndentContext>
2502-
getIndentContextFrom(ClosureExpr *CE, SourceLoc ContextLoc = SourceLoc(),
2502+
getIndentContextFrom(AbstractClosureExpr *ACE, SourceLoc ContextLoc = SourceLoc(),
25032503
CaptureListExpr *ParentCapture = nullptr) {
2504+
// Explicit capture lists should always have an explicit ClosureExpr as
2505+
// their subexpression.
2506+
auto CE = dyn_cast<ClosureExpr>(ACE);
2507+
if (!CE) {
2508+
return None;
2509+
}
25042510
BraceStmt *BS = CE->getBody();
25052511
if (!BS)
25062512
return None;

lib/IDE/Refactoring.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7315,7 +7315,7 @@ class AsyncConverter : private SourceEntityWalker {
73157315
if (auto Closure = dyn_cast<ClosureExpr>(E)) {
73167316
return Closure;
73177317
} else if (auto CaptureList = dyn_cast<CaptureListExpr>(E)) {
7318-
return CaptureList->getClosureBody();
7318+
return dyn_cast<ClosureExpr>(CaptureList->getClosureBody());
73197319
} else {
73207320
return nullptr;
73217321
}

lib/Parse/ParseExpr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,8 +690,7 @@ ParserResult<Expr> Parser::parseExprKeyPath() {
690690

691691
auto *keypath = KeyPathExpr::createParsed(
692692
Context, backslashLoc, rootResult.getPtrOrNull(),
693-
pathResult.getPtrOrNull(), hasLeadingDot,
694-
CurLocalContext->claimNextClosureDiscriminator());
693+
pathResult.getPtrOrNull(), hasLeadingDot);
695694
return makeParserResult(parseStatus, keypath);
696695
}
697696

lib/SILGen/SILGenExpr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,19 @@ RValue RValueEmitter::visitFunctionConversionExpr(FunctionConversionExpr *e,
18191819
// TODO: Move this up when we can emit closures directly with C calling
18201820
// convention.
18211821
auto subExpr = e->getSubExpr()->getSemanticsProvidingExpr();
1822+
// Look through `as` type ascriptions that don't induce bridging too.
1823+
while (auto subCoerce = dyn_cast<CoerceExpr>(subExpr)) {
1824+
// Coercions that introduce bridging aren't simple type ascriptions.
1825+
// (Maybe we could still peephole through them eventually, though, by
1826+
// performing the bridging in the closure prolog/epilog and/or emitting
1827+
// the closure with the correct contextual block/closure/C function pointer
1828+
// representation.)
1829+
if (!subCoerce->getSubExpr()->getType()->isEqual(subCoerce->getType())) {
1830+
break;
1831+
}
1832+
subExpr = subCoerce->getSubExpr()->getSemanticsProvidingExpr();
1833+
}
1834+
18221835
if ((isa<AbstractClosureExpr>(subExpr) || isa<CaptureListExpr>(subExpr))
18231836
&& canPeepholeLiteralClosureConversion(subExpr->getType(),
18241837
e->getType())) {

0 commit comments

Comments
 (0)