Skip to content

Commit 02d6075

Browse files
committed
[Sema] Synthesize pre-type-checked AST for == on no-associated-value enums
1 parent 67e7eba commit 02d6075

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

lib/Sema/DerivedConformanceEquatableHashable.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,17 @@ enumElementPayloadSubpattern(EnumElementDecl *enumElementDecl,
257257
return pat;
258258
}
259259

260+
/// Build a type-checked integer literal.
261+
static IntegerLiteralExpr *buildIntegerLiteral(ASTContext &C, unsigned index) {
262+
Type intType = C.getIntDecl()->getDeclaredType();
263+
264+
auto literal = IntegerLiteralExpr::createFromUnsigned(C, index);
265+
literal->setType(intType);
266+
literal->setBuiltinInitializer(C.getIntBuiltinInitDecl(C.getIntDecl()));
267+
268+
return literal;
269+
}
270+
260271
/// Create AST statements which convert from an enum to an Int with a switch.
261272
/// \p stmts The generated statements are appended to this vector.
262273
/// \p parentDC Either an extension or the enum itself.
@@ -298,15 +309,20 @@ static DeclRefExpr *convertEnumToIndex(SmallVectorImpl<ASTNode> &stmts,
298309
SourceLoc(), SourceLoc(),
299310
Identifier(), elt, nullptr);
300311
pat->setImplicit();
312+
pat->setType(enumType);
301313

302314
auto labelItem = CaseLabelItem(pat);
303315

304316
// generate: indexVar = <index>
305-
auto indexExpr = IntegerLiteralExpr::createFromUnsigned(C, index++);
317+
auto indexExpr = buildIntegerLiteral(C, index++);
318+
306319
auto indexRef = new (C) DeclRefExpr(indexVar, DeclNameLoc(),
307-
/*implicit*/true);
320+
/*implicit*/true,
321+
AccessSemantics::Ordinary,
322+
LValueType::get(intType));
308323
auto assignExpr = new (C) AssignExpr(indexRef, SourceLoc(),
309324
indexExpr, /*implicit*/ true);
325+
assignExpr->setType(TupleType::getEmpty(C));
310326
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(assignExpr),
311327
SourceLoc());
312328
cases.push_back(CaseStmt::create(C, SourceLoc(), labelItem, SourceLoc(),
@@ -316,7 +332,9 @@ static DeclRefExpr *convertEnumToIndex(SmallVectorImpl<ASTNode> &stmts,
316332

317333
// generate: switch enumVar { }
318334
auto enumRef = new (C) DeclRefExpr(enumVarDecl, DeclNameLoc(),
319-
/*implicit*/true);
335+
/*implicit*/true,
336+
AccessSemantics::Ordinary,
337+
enumVarDecl->getType());
320338
auto switchStmt = SwitchStmt::create(LabeledStmtInfo(), SourceLoc(), enumRef,
321339
SourceLoc(), cases, SourceLoc(), C);
322340

@@ -445,16 +463,20 @@ deriveBodyEquatable_enum_noAssociatedValues_eq(AbstractFunctionDecl *eqDecl,
445463
fnType);
446464
}
447465

466+
TupleTypeElt abTupleElts[2] = { aIndex->getType(), bIndex->getType() };
448467
TupleExpr *abTuple = TupleExpr::create(C, SourceLoc(), { aIndex, bIndex },
449468
{ }, { }, SourceLoc(),
450469
/*HasTrailingClosure*/ false,
451-
/*Implicit*/ true);
470+
/*Implicit*/ true,
471+
TupleType::get(abTupleElts, C));
452472

453-
auto *cmpExpr = new (C) BinaryExpr(cmpFuncExpr, abTuple, /*implicit*/ true);
473+
auto *cmpExpr = new (C) BinaryExpr(
474+
cmpFuncExpr, abTuple, /*implicit*/ true,
475+
fnType->castTo<FunctionType>()->getResult());
454476
statements.push_back(new (C) ReturnStmt(SourceLoc(), cmpExpr));
455477

456478
BraceStmt *body = BraceStmt::create(C, SourceLoc(), statements, SourceLoc());
457-
return { body, /*isTypeChecked=*/false };
479+
return { body, /*isTypeChecked=*/true };
458480
}
459481

460482
/// Derive the body for an '==' operator for an enum where at least one of the

0 commit comments

Comments
 (0)