@@ -1552,13 +1552,14 @@ deriveBodyDecodable_enum_init(AbstractFunctionDecl *initDecl, void *) {
1552
1552
//
1553
1553
// @derived init(from decoder: Decoder) throws {
1554
1554
// let container = try decoder.container(keyedBy: CodingKeys.self)
1555
- // if container.allKeys.count != 1 {
1555
+ // var allKeys = ArraySlice(container.allKeys)
1556
+ // guard let onlyKey = allKeys.popFirst(), allKeys.isEmpty else {
1556
1557
// let context = DecodingError.Context(
1557
1558
// codingPath: container.codingPath,
1558
1559
// debugDescription: "Invalid number of keys found, expected one.")
1559
1560
// throw DecodingError.typeMismatch(Foo.self, context)
1560
1561
// }
1561
- // switch container.allKeys.first {
1562
+ // switch onlyKey {
1562
1563
// case .bar:
1563
1564
// let nestedContainer = try container.nestedContainer(
1564
1565
// keyedBy: BarCodingKeys.self, forKey: .bar)
@@ -1597,15 +1598,67 @@ deriveBodyDecodable_enum_init(AbstractFunctionDecl *initDecl, void *) {
1597
1598
initDecl->getParameters ()->get (0 ), codingKeysEnum, statements,
1598
1599
/* throws*/ true );
1599
1600
1601
+ // generate: var allKeys = ArraySlice(container.allKeys);
1602
+ auto *allKeysDecl =
1603
+ new (C) VarDecl (/* IsStatic=*/ false , VarDecl::Introducer::Var,
1604
+ SourceLoc (), C.Id_allKeys , funcDC);
1605
+ allKeysDecl->setImplicit ();
1606
+ allKeysDecl->setSynthesized ();
1607
+ {
1608
+ auto *arraySliceRef =
1609
+ new (C) DeclRefExpr (ConcreteDeclRef (C.getArraySliceDecl ()),
1610
+ DeclNameLoc (), /* Implicit=*/ true );
1611
+ auto *containerAllKeys =
1612
+ UnresolvedDotExpr::createImplicit (C, containerExpr, C.Id_allKeys );
1613
+ auto *argList = ArgumentList::createImplicit (
1614
+ C, {Argument::unlabeled (containerAllKeys)});
1615
+ auto *init = CallExpr::createImplicit (C, arraySliceRef, argList);
1616
+
1617
+ auto *allKeysPattern = NamedPattern::createImplicit (C, allKeysDecl);
1618
+ auto *allKeysBindingDecl = PatternBindingDecl::createImplicit (
1619
+ C, StaticSpellingKind::None, allKeysPattern, init, funcDC);
1620
+
1621
+ statements.push_back (allKeysBindingDecl);
1622
+ statements.push_back (allKeysDecl);
1623
+ }
1624
+
1600
1625
// generate:
1601
- //
1602
- // if container.allKeys.count != 1 {
1626
+ // guard let onlyKey = allKeys.popFirst(), allKeys.isEmpty else {
1603
1627
// let context = DecodingError.Context(
1604
1628
// codingPath: container.codingPath,
1605
1629
// debugDescription: "Invalid number of keys found, expected
1606
1630
// one.")
1607
1631
// throw DecodingError.typeMismatch(Foo.self, context)
1608
1632
// }
1633
+ auto *theKeyDecl =
1634
+ new (C) VarDecl (/* IsStatic=*/ false , VarDecl::Introducer::Let,
1635
+ SourceLoc (), C.getIdentifier (" onlyKey" ), funcDC);
1636
+ theKeyDecl->setImplicit ();
1637
+ theKeyDecl->setSynthesized ();
1638
+
1639
+ SmallVector<StmtConditionElement, 2 > guardElements;
1640
+ {
1641
+ auto *allKeysExpr =
1642
+ new (C) DeclRefExpr (ConcreteDeclRef (allKeysDecl), DeclNameLoc (),
1643
+ /* Implicit=*/ true );
1644
+
1645
+ // generate: let onlyKey = allKeys.popFirst;
1646
+ auto *allKeysPopFisrtCallExpr = CallExpr::createImplicitEmpty (
1647
+ C, UnresolvedDotExpr::createImplicit (C, allKeysExpr, C.Id_popFirst ));
1648
+
1649
+ auto *theKeyPattern = BindingPattern::createImplicit (
1650
+ C, /* isLet=*/ true , NamedPattern::createImplicit (C, theKeyDecl));
1651
+
1652
+ guardElements.emplace_back (SourceLoc (), theKeyPattern,
1653
+ allKeysPopFisrtCallExpr);
1654
+
1655
+ // generate: allKeys.isEmpty;
1656
+ auto *allKeysIsEmptyExpr =
1657
+ UnresolvedDotExpr::createImplicit (C, allKeysExpr, C.Id_isEmpty );
1658
+
1659
+ guardElements.emplace_back (allKeysIsEmptyExpr);
1660
+ }
1661
+
1609
1662
auto *targetType = TypeExpr::createImplicit (
1610
1663
funcDC->mapTypeIntoContext (targetEnum->getDeclaredInterfaceType ()), C);
1611
1664
auto *targetTypeExpr =
@@ -1615,44 +1668,21 @@ deriveBodyDecodable_enum_init(AbstractFunctionDecl *initDecl, void *) {
1615
1668
C, containerExpr, C.getDecodingErrorDecl (), C.Id_typeMismatch ,
1616
1669
targetTypeExpr, " Invalid number of keys found, expected one." );
1617
1670
1618
- // container.allKeys
1619
- auto *allKeysExpr =
1620
- UnresolvedDotExpr::createImplicit (C, containerExpr, C.Id_allKeys );
1621
-
1622
- // container.allKeys.count
1623
- auto *keysCountExpr =
1624
- UnresolvedDotExpr::createImplicit (C, allKeysExpr, C.Id_count );
1625
-
1626
- // container.allKeys.count == 1
1627
- auto *cmpFunc = C.getEqualIntDecl ();
1628
- auto *fnType = cmpFunc->getInterfaceType ()->castTo <FunctionType>();
1629
- auto *cmpFuncExpr = new (C)
1630
- DeclRefExpr (cmpFunc, DeclNameLoc (),
1631
- /* implicit*/ true , AccessSemantics::Ordinary, fnType);
1632
- auto *oneExpr = IntegerLiteralExpr::createFromUnsigned (C, 1 );
1633
-
1634
- auto *cmpExpr = BinaryExpr::create (C, keysCountExpr, cmpFuncExpr, oneExpr,
1635
- /* implicit*/ true );
1636
- cmpExpr->setThrows (false );
1637
-
1638
1671
auto *guardBody = BraceStmt::create (C, SourceLoc (), {throwStmt},
1639
1672
SourceLoc (), /* Implicit */ true );
1640
1673
1641
- auto *guardStmt = new (C)
1642
- GuardStmt (SourceLoc (), cmpExpr, guardBody, /* Implicit */ true , C);
1674
+ auto *guardStmt =
1675
+ new (C) GuardStmt (SourceLoc (), C.AllocateCopy (guardElements), guardBody,
1676
+ /* Implicit */ true );
1643
1677
1644
1678
statements.push_back (guardStmt);
1645
1679
1646
- // generate: switch container.allKeys.first { }
1647
- auto *firstExpr =
1648
- UnresolvedDotExpr::createImplicit (C, allKeysExpr, C.Id_first );
1649
-
1650
- // generate: switch container.allKeys.first.unsafelyUnwrapped { }
1651
- auto *unwrapped =
1652
- UnresolvedDotExpr::createImplicit (C, firstExpr, C.Id_unsafelyUnwrapped );
1680
+ // generate: switch onlyKey { }
1681
+ auto *theKeyExpr = new (C) DeclRefExpr (ConcreteDeclRef (theKeyDecl),
1682
+ DeclNameLoc (), /* Implicit=*/ true );
1653
1683
1654
1684
auto switchStmt = createEnumSwitch (
1655
- C, funcDC, unwrapped , targetEnum, codingKeysEnum,
1685
+ C, funcDC, theKeyExpr , targetEnum, codingKeysEnum,
1656
1686
/* createSubpattern*/ false ,
1657
1687
[&](auto *elt, auto *codingKeyCase,
1658
1688
auto payloadVars) -> std::tuple<EnumElementDecl *, BraceStmt *> {
0 commit comments