Skip to content

Commit c02c69a

Browse files
committed
[AST] Introduce CaseStmt::createImplicit
This allows us to re-use the same logic to create the case body variables.
1 parent 245e287 commit c02c69a

9 files changed

+55
-131
lines changed

include/swift/AST/Stmt.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,13 +1243,17 @@ class CaseStmt final
12431243
ArrayRef<CaseLabelItem> CaseLabelItems,
12441244
BraceStmt *Body);
12451245

1246+
static CaseStmt *
1247+
createImplicit(ASTContext &ctx, CaseParentKind parentKind,
1248+
ArrayRef<CaseLabelItem> caseLabelItems, BraceStmt *body,
1249+
NullablePtr<FallthroughStmt> fallthroughStmt = nullptr);
1250+
12461251
static CaseStmt *
12471252
create(ASTContext &C, CaseParentKind ParentKind, SourceLoc ItemIntroducerLoc,
12481253
ArrayRef<CaseLabelItem> CaseLabelItems, SourceLoc UnknownAttrLoc,
12491254
SourceLoc ItemTerminatorLoc, BraceStmt *Body,
1250-
ArrayRef<VarDecl *> CaseBodyVariables,
1251-
std::optional<bool> Implicit = std::nullopt,
1252-
NullablePtr<FallthroughStmt> fallthroughStmt = nullptr);
1255+
ArrayRef<VarDecl *> CaseBodyVariables, std::optional<bool> Implicit,
1256+
NullablePtr<FallthroughStmt> fallthroughStmt);
12531257

12541258
CaseParentKind getParentKind() const { return ParentKind; }
12551259

lib/AST/Stmt.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -897,11 +897,23 @@ CaseStmt *CaseStmt::createParsedDoCatch(ASTContext &ctx, SourceLoc catchLoc,
897897
}
898898

899899
CaseStmt *
900-
CaseStmt::create(ASTContext &ctx, CaseParentKind ParentKind, SourceLoc caseLoc,
901-
ArrayRef<CaseLabelItem> caseLabelItems,
902-
SourceLoc unknownAttrLoc, SourceLoc colonLoc, BraceStmt *body,
903-
ArrayRef<VarDecl *> caseVarDecls, std::optional<bool> implicit,
904-
NullablePtr<FallthroughStmt> fallthroughStmt) {
900+
CaseStmt::createImplicit(ASTContext &ctx, CaseParentKind parentKind,
901+
ArrayRef<CaseLabelItem> caseLabelItems,
902+
BraceStmt *body,
903+
NullablePtr<FallthroughStmt> fallthroughStmt) {
904+
auto caseVarDecls = getCaseVarDecls(ctx, caseLabelItems);
905+
return create(ctx, parentKind, /*catchLoc*/ SourceLoc(), caseLabelItems,
906+
/*unknownAttrLoc*/ SourceLoc(), /*colonLoc*/ SourceLoc(), body,
907+
caseVarDecls, /*implicit*/ true, fallthroughStmt);
908+
}
909+
910+
CaseStmt *CaseStmt::create(ASTContext &ctx, CaseParentKind ParentKind,
911+
SourceLoc caseLoc,
912+
ArrayRef<CaseLabelItem> caseLabelItems,
913+
SourceLoc unknownAttrLoc, SourceLoc colonLoc,
914+
BraceStmt *body, ArrayRef<VarDecl *> caseVarDecls,
915+
std::optional<bool> implicit,
916+
NullablePtr<FallthroughStmt> fallthroughStmt) {
905917
void *mem =
906918
ctx.Allocate(totalSizeToAlloc<FallthroughStmt *, CaseLabelItem>(
907919
fallthroughStmt.isNonNull(), caseLabelItems.size()),

lib/Sema/DerivedConformance/DerivedConformance.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -805,9 +805,8 @@ DeclRefExpr *DerivedConformance::convertEnumToIndex(SmallVectorImpl<ASTNode> &st
805805
assignExpr->setType(TupleType::getEmpty(C));
806806
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(assignExpr),
807807
SourceLoc());
808-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
809-
labelItem, SourceLoc(), SourceLoc(), body,
810-
/*case body vardecls*/ std::nullopt));
808+
cases.push_back(
809+
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
811810
}
812811

813812
// generate: switch enumVar { }
@@ -967,9 +966,7 @@ CaseStmt *DerivedConformance::unavailableEnumElementCaseStmt(
967966
auto *callExpr =
968967
DerivedConformance::createDiagnoseUnavailableCodeReachedCallExpr(C);
969968
auto body = BraceStmt::create(C, SourceLoc(), {callExpr}, SourceLoc());
970-
return CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(), labelItem,
971-
SourceLoc(), SourceLoc(), body, {},
972-
/*implicit*/ true);
969+
return CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body);
973970
}
974971

975972
/// Creates a named variable based on a prefix character and a numeric index.

lib/Sema/DerivedConformance/DerivedConformanceCodable.cpp

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -946,27 +946,10 @@ createEnumSwitch(ASTContext &C, DeclContext *DC, Expr *expr, EnumDecl *enumDecl,
946946
// .<elt>(let a0, let a1, ...)
947947
SmallVector<VarDecl *, 3> payloadVars;
948948
Pattern *subpattern = nullptr;
949-
ArrayRef<VarDecl *> caseBodyVarDecls;
950949

951950
if (createSubpattern) {
952951
subpattern = DerivedConformance::enumElementPayloadSubpattern(
953952
elt, 'a', DC, payloadVars, /* useLabels */ true);
954-
955-
auto hasBoundDecls = !payloadVars.empty();
956-
if (hasBoundDecls) {
957-
// We allocated a direct copy of our var decls for the case
958-
// body.
959-
auto copy = C.Allocate<VarDecl *>(payloadVars.size());
960-
for (unsigned i : indices(payloadVars)) {
961-
auto *vOld = payloadVars[i];
962-
auto *vNew = new (C) VarDecl(
963-
/*IsStatic*/ false, vOld->getIntroducer(), vOld->getNameLoc(),
964-
vOld->getName(), vOld->getDeclContext());
965-
vNew->setImplicit();
966-
copy[i] = vNew;
967-
}
968-
caseBodyVarDecls = copy;
969-
}
970953
}
971954

972955
// CodingKeys.x
@@ -985,10 +968,8 @@ createEnumSwitch(ASTContext &C, DeclContext *DC, Expr *expr, EnumDecl *enumDecl,
985968
subpattern, DC);
986969

987970
auto labelItem = CaseLabelItem(pat);
988-
auto stmt =
989-
CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(), labelItem,
990-
SourceLoc(), SourceLoc(), caseBody,
991-
caseBodyVarDecls);
971+
auto stmt = CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem,
972+
caseBody);
992973
cases.push_back(stmt);
993974
}
994975
}

lib/Sema/DerivedConformance/DerivedConformanceCodingKey.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,8 @@ deriveBodyCodingKey_enum_stringValue(AbstractFunctionDecl *strValDecl, void *) {
222222
auto *returnStmt = ReturnStmt::createImplicit(C, caseValue);
223223
auto *caseBody = BraceStmt::create(C, SourceLoc(), ASTNode(returnStmt),
224224
SourceLoc());
225-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
226-
labelItem, SourceLoc(), SourceLoc(),
227-
caseBody,
228-
/*case body var decls*/ std::nullopt));
225+
cases.push_back(CaseStmt::createImplicit(C, CaseParentKind::Switch,
226+
labelItem, caseBody));
229227
}
230228

231229
auto *selfRef = DerivedConformance::createSelfDeclRef(strValDecl);
@@ -292,9 +290,8 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) {
292290

293291
auto *body = BraceStmt::create(C, SourceLoc(), ASTNode(assignment),
294292
SourceLoc());
295-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
296-
labelItem, SourceLoc(), SourceLoc(), body,
297-
/*case body var decls*/ std::nullopt));
293+
cases.push_back(
294+
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
298295
}
299296

300297
auto *anyPat = AnyPattern::createImplicit(C);
@@ -303,10 +300,8 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) {
303300
auto *dfltReturnStmt = new (C) FailStmt(SourceLoc(), SourceLoc());
304301
auto *dfltBody = BraceStmt::create(C, SourceLoc(), ASTNode(dfltReturnStmt),
305302
SourceLoc());
306-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
307-
dfltLabelItem, SourceLoc(), SourceLoc(),
308-
dfltBody,
309-
/*case body var decls*/ std::nullopt));
303+
cases.push_back(CaseStmt::createImplicit(C, CaseParentKind::Switch,
304+
dfltLabelItem, dfltBody));
310305

311306
auto *stringValueDecl = initDecl->getParameters()->get(0);
312307
auto *stringValueRef = new (C) DeclRefExpr(stringValueDecl, DeclNameLoc(),

lib/Sema/DerivedConformance/DerivedConformanceComparable.cpp

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -127,23 +127,6 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v
127127
auto *rhsElemPat = EnumElementPattern::createImplicit(
128128
enumType, elt, rhsSubpattern, /*DC*/ ltDecl);
129129

130-
auto hasBoundDecls = !lhsPayloadVars.empty();
131-
ArrayRef<VarDecl *> caseBodyVarDecls;
132-
if (hasBoundDecls) {
133-
// We allocated a direct copy of our lhs var decls for the case
134-
// body.
135-
auto copy = C.Allocate<VarDecl *>(lhsPayloadVars.size());
136-
for (unsigned i : indices(lhsPayloadVars)) {
137-
auto *vOld = lhsPayloadVars[i];
138-
auto *vNew = new (C) VarDecl(
139-
/*IsStatic*/ false, vOld->getIntroducer(),
140-
vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
141-
vNew->setImplicit();
142-
copy[i] = vNew;
143-
}
144-
caseBodyVarDecls = copy;
145-
}
146-
147130
// case (.<elt>(let l0, let l1, ...), .<elt>(let r0, let r1, ...))
148131
auto caseTuplePattern = TuplePattern::createImplicit(C, {
149132
TuplePatternElt(lhsElemPat), TuplePatternElt(rhsElemPat) });
@@ -177,9 +160,8 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v
177160

178161
auto body = BraceStmt::create(C, SourceLoc(), statementsInCase,
179162
SourceLoc());
180-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
181-
labelItem, SourceLoc(), SourceLoc(), body,
182-
caseBodyVarDecls));
163+
cases.push_back(
164+
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
183165
}
184166

185167
// default: result = <enum index>(lhs) < <enum index>(rhs)
@@ -190,10 +172,8 @@ deriveBodyComparable_enum_hasAssociatedValues_lt(AbstractFunctionDecl *ltDecl, v
190172
auto defaultPattern = AnyPattern::createImplicit(C);
191173
auto defaultItem = CaseLabelItem::getDefault(defaultPattern);
192174
auto body = deriveBodyComparable_enum_noAssociatedValues_lt(ltDecl, nullptr).first;
193-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
194-
defaultItem, SourceLoc(), SourceLoc(),
195-
body,
196-
/*case body var decls*/ std::nullopt));
175+
cases.push_back(
176+
CaseStmt::createImplicit(C, CaseParentKind::Switch, defaultItem, body));
197177
}
198178

199179
// switch (a, b) { <case statements> }

lib/Sema/DerivedConformance/DerivedConformanceEquatableHashable.cpp

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -193,23 +193,6 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
193193
auto *rhsElemPat = EnumElementPattern::createImplicit(
194194
enumType, elt, rhsSubpattern, /*DC*/ eqDecl);
195195

196-
auto hasBoundDecls = !lhsPayloadVars.empty();
197-
ArrayRef<VarDecl *> caseBodyVarDecls;
198-
if (hasBoundDecls) {
199-
// We allocated a direct copy of our lhs var decls for the case
200-
// body.
201-
auto copy = C.Allocate<VarDecl *>(lhsPayloadVars.size());
202-
for (unsigned i : indices(lhsPayloadVars)) {
203-
auto *vOld = lhsPayloadVars[i];
204-
auto *vNew = new (C) VarDecl(
205-
/*IsStatic*/ false, vOld->getIntroducer(),
206-
vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
207-
vNew->setImplicit();
208-
copy[i] = vNew;
209-
}
210-
caseBodyVarDecls = copy;
211-
}
212-
213196
// case (.<elt>(let l0, let l1, ...), .<elt>(let r0, let r1, ...))
214197
auto caseTuplePattern = TuplePattern::createImplicit(C, {
215198
TuplePatternElt(lhsElemPat), TuplePatternElt(rhsElemPat) });
@@ -244,9 +227,8 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
244227

245228
auto body = BraceStmt::create(C, SourceLoc(), statementsInCase,
246229
SourceLoc());
247-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
248-
labelItem, SourceLoc(), SourceLoc(), body,
249-
caseBodyVarDecls));
230+
cases.push_back(
231+
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
250232
}
251233

252234
// default: result = false
@@ -261,10 +243,8 @@ deriveBodyEquatable_enum_hasAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
261243
auto *returnStmt = ReturnStmt::createImplicit(C, falseExpr);
262244
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(returnStmt),
263245
SourceLoc());
264-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
265-
defaultItem, SourceLoc(), SourceLoc(),
266-
body,
267-
/*case body var decls*/ std::nullopt));
246+
cases.push_back(
247+
CaseStmt::createImplicit(C, CaseParentKind::Switch, defaultItem, body));
268248
}
269249

270250
// switch (a, b) { <case statements> }
@@ -735,26 +715,9 @@ deriveBodyHashable_enum_hasAssociatedValues_hashInto(
735715
statements.emplace_back(ASTNode(combineExpr));
736716
}
737717

738-
auto hasBoundDecls = !payloadVars.empty();
739-
ArrayRef<VarDecl *> caseBodyVarDecls;
740-
if (hasBoundDecls) {
741-
auto copy = C.Allocate<VarDecl *>(payloadVars.size());
742-
for (unsigned i : indices(payloadVars)) {
743-
auto *vOld = payloadVars[i];
744-
auto *vNew = new (C) VarDecl(
745-
/*IsStatic*/ false, vOld->getIntroducer(),
746-
vOld->getNameLoc(), vOld->getName(), vOld->getDeclContext());
747-
vNew->setImplicit();
748-
copy[i] = vNew;
749-
}
750-
caseBodyVarDecls = copy;
751-
}
752-
753718
auto body = BraceStmt::create(C, SourceLoc(), statements, SourceLoc());
754-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
755-
labelItem, SourceLoc(), SourceLoc(), body,
756-
caseBodyVarDecls,
757-
/*implicit*/ true));
719+
cases.push_back(
720+
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
758721
}
759722

760723
// generate: switch enumVar { }

lib/Sema/DerivedConformance/DerivedConformanceRawRepresentable.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,8 @@ deriveBodyRawRepresentable_raw(AbstractFunctionDecl *toRawDecl, void *) {
129129
auto body = BraceStmt::create(C, SourceLoc(),
130130
ASTNode(returnStmt), SourceLoc());
131131

132-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
133-
labelItem, SourceLoc(), SourceLoc(), body,
134-
/*case body var decls*/ std::nullopt));
132+
cases.push_back(
133+
CaseStmt::createImplicit(C, CaseParentKind::Switch, labelItem, body));
135134
}
136135

137136
auto selfRef = DerivedConformance::createSelfDeclRef(toRawDecl);
@@ -363,10 +362,8 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl, void *) {
363362
stmts, SourceLoc());
364363

365364
// cases.append("case \(litPat): \(body)")
366-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
367-
CaseLabelItem(litPat), SourceLoc(),
368-
SourceLoc(), body,
369-
/*case body var decls*/ std::nullopt));
365+
cases.push_back(CaseStmt::createImplicit(C, CaseParentKind::Switch,
366+
CaseLabelItem(litPat), body));
370367
++Idx;
371368
}
372369

@@ -376,10 +373,8 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl, void *) {
376373
auto dfltReturnStmt = new (C) FailStmt(SourceLoc(), SourceLoc());
377374
auto dfltBody = BraceStmt::create(C, SourceLoc(),
378375
ASTNode(dfltReturnStmt), SourceLoc());
379-
cases.push_back(CaseStmt::create(C, CaseParentKind::Switch, SourceLoc(),
380-
dfltLabelItem, SourceLoc(), SourceLoc(),
381-
dfltBody,
382-
/*case body var decls*/ std::nullopt));
376+
cases.push_back(CaseStmt::createImplicit(C, CaseParentKind::Switch,
377+
dfltLabelItem, dfltBody));
383378

384379
auto rawDecl = initDecl->getParameters()->get(0);
385380
auto rawRef = new (C) DeclRefExpr(rawDecl, DeclNameLoc(), /*implicit*/true);

unittests/Sema/ConstraintGenerationTests.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,8 @@ TEST_F(SemaTest, TestSwitchExprLocator) {
286286
{IntegerLiteralExpr::createFromUnsigned(Context, 1, SourceLoc())});
287287
auto *truePattern = ExprPattern::createImplicit(
288288
Context, new (Context) BooleanLiteralExpr(true, SourceLoc()), DC);
289-
auto *trueCase =
290-
CaseStmt::create(Context, CaseParentKind::Switch, SourceLoc(),
291-
{CaseLabelItem(truePattern)}, SourceLoc(), SourceLoc(),
292-
trueBrace, /*caseBodyVars*/ std::nullopt);
289+
auto *trueCase = CaseStmt::createImplicit(
290+
Context, CaseParentKind::Switch, {CaseLabelItem(truePattern)}, trueBrace);
293291

294292
// case false: 2
295293
auto *falseBrace = BraceStmt::createImplicit(
@@ -298,9 +296,8 @@ TEST_F(SemaTest, TestSwitchExprLocator) {
298296
auto *falsePattern = ExprPattern::createImplicit(
299297
Context, new (Context) BooleanLiteralExpr(false, SourceLoc()), DC);
300298
auto *falseCase =
301-
CaseStmt::create(Context, CaseParentKind::Switch, SourceLoc(),
302-
{CaseLabelItem(falsePattern)}, SourceLoc(), SourceLoc(),
303-
falseBrace, /*caseBodyVars*/ std::nullopt);
299+
CaseStmt::createImplicit(Context, CaseParentKind::Switch,
300+
{CaseLabelItem(falsePattern)}, falseBrace);
304301

305302
auto *subject = new (Context) BooleanLiteralExpr(true, SourceLoc());
306303

0 commit comments

Comments
 (0)