@@ -92,10 +92,6 @@ static bool canDeriveConformance(TypeChecker &tc, DeclContext *DC,
9292 ProtocolDecl *protocol) {
9393 // The type must be an enum or a struct.
9494 if (auto enumDecl = dyn_cast<EnumDecl>(target)) {
95- // The enum must have cases.
96- if (!enumDecl->hasCases ())
97- return false ;
98-
9995 // The cases must not have associated values, or all associated values must
10096 // conform to the protocol.
10197 return allAssociatedValuesConformToProtocol (tc, DC, enumDecl, protocol);
@@ -304,6 +300,34 @@ static GuardStmt *returnIfNotEqualGuard(ASTContext &C,
304300 return new (C) GuardStmt (SourceLoc (), C.AllocateCopy (conditions), body);
305301}
306302
303+ static void
304+ deriveBodyEquatable_enum_uninhabited_eq (AbstractFunctionDecl *eqDecl) {
305+ auto parentDC = eqDecl->getDeclContext ();
306+ ASTContext &C = parentDC->getASTContext ();
307+
308+ auto args = eqDecl->getParameterLists ().back ();
309+ auto aParam = args->get (0 );
310+ auto bParam = args->get (1 );
311+
312+ assert (!cast<EnumDecl>(aParam->getType ()->getAnyNominal ())->hasCases ());
313+
314+ SmallVector<ASTNode, 1 > statements;
315+ SmallVector<ASTNode, 0 > cases;
316+
317+ // switch (a, b) { }
318+ auto aRef = new (C) DeclRefExpr (aParam, DeclNameLoc (), /* implicit*/ true );
319+ auto bRef = new (C) DeclRefExpr (bParam, DeclNameLoc (), /* implicit*/ true );
320+ auto abExpr = TupleExpr::create (C, SourceLoc (), {aRef, bRef}, {}, {},
321+ SourceLoc (), /* HasTrailingClosure*/ false ,
322+ /* implicit*/ true );
323+ auto switchStmt = SwitchStmt::create (LabeledStmtInfo (), SourceLoc (), abExpr,
324+ SourceLoc (), cases, SourceLoc (), C);
325+ statements.push_back (switchStmt);
326+
327+ auto body = BraceStmt::create (C, SourceLoc (), statements, SourceLoc ());
328+ eqDecl->setBody (body);
329+ }
330+
307331// / Derive the body for an '==' operator for an enum that has no associated
308332// / values. This generates code that converts each value to its integer ordinal
309333// / and compares them, which produces an optimal single icmp instruction.
@@ -673,11 +697,13 @@ ValueDecl *DerivedConformance::deriveEquatable(ValueDecl *requirement) {
673697
674698 // Build the necessary decl.
675699 if (requirement->getBaseName () == " ==" ) {
676- if (auto ED = dyn_cast<EnumDecl>(Nominal)) {
700+ if (auto ed = dyn_cast<EnumDecl>(Nominal)) {
677701 auto bodySynthesizer =
678- ED->hasOnlyCasesWithoutAssociatedValues ()
679- ? &deriveBodyEquatable_enum_noAssociatedValues_eq
680- : &deriveBodyEquatable_enum_hasAssociatedValues_eq;
702+ !ed->hasCases ()
703+ ? &deriveBodyEquatable_enum_uninhabited_eq
704+ : ed->hasOnlyCasesWithoutAssociatedValues ()
705+ ? &deriveBodyEquatable_enum_noAssociatedValues_eq
706+ : &deriveBodyEquatable_enum_hasAssociatedValues_eq;
681707 return deriveEquatable_eq (*this , TC.Context .Id_derived_enum_equals ,
682708 bodySynthesizer);
683709 } else if (isa<StructDecl>(Nominal))
0 commit comments