@@ -29,38 +29,15 @@ using namespace swift;
2929
3030// / Returns whether the type represented by the given ClassDecl inherits from a
3131// / type which conforms to the given protocol.
32- // /
33- // / \param target The \c ClassDecl whose superclass to look up.
34- // /
35- // / \param proto The protocol to check conformance for.
36- static bool inheritsConformanceTo (ClassDecl *target, ProtocolDecl *proto) {
37- if (!target->hasSuperclass ())
32+ static bool superclassConformsTo (ClassDecl *target, KnownProtocolKind kpk) {
33+ if (!target || !target->getSuperclass () || target->hasCircularInheritance ()) {
3834 return false ;
39-
40- auto *superclassDecl = target->getSuperclassDecl ();
41- auto *superclassModule = superclassDecl->getModuleContext ();
42- return (bool )superclassModule->lookupConformance (target->getSuperclass (),
43- proto);
44- }
45-
46- // / Returns whether the superclass of the given class conforms to Encodable.
47- // /
48- // / \param target The \c ClassDecl whose superclass to check.
49- static bool superclassIsEncodable (ClassDecl *target) {
50- auto &C = target->getASTContext ();
51- return inheritsConformanceTo (target,
52- C.getProtocol (KnownProtocolKind::Encodable));
53- }
54-
55- // / Returns whether the superclass of the given class conforms to Decodable.
56- // /
57- // / \param target The \c ClassDecl whose superclass to check.
58- static bool superclassIsDecodable (ClassDecl *target) {
59- auto &C = target->getASTContext ();
60- return inheritsConformanceTo (target,
61- C.getProtocol (KnownProtocolKind::Decodable));
62- }
63-
35+ }
36+ return !target->getSuperclassDecl ()
37+ ->getModuleContext ()
38+ ->lookupConformance (target->getSuperclass (),
39+ target->getASTContext ().getProtocol (kpk))
40+ .isInvalid ();
6441}
6542
6643// / Retrieve the variable name for the purposes of encoding/decoding.
@@ -134,25 +111,22 @@ static bool validateCodingKeysEnum(const DerivedConformance &derived,
134111 // If there are any remaining properties which the CodingKeys did not cover,
135112 // we can skip them on encode. On decode, though, we can only skip them if
136113 // they have a default value.
137- if (!properties.empty () &&
138- derived.Protocol ->isSpecificProtocol (KnownProtocolKind::Decodable)) {
139- for (auto it = properties.begin (); it != properties.end (); ++it) {
140- // If the var is default initializable, then it need not have an explicit
141- // initial value.
142- auto *varDecl = it->second ;
143- if (auto pbd = varDecl->getParentPatternBinding ()) {
144- if (pbd->isDefaultInitializable ())
145- continue ;
114+ if (derived.Protocol ->isSpecificProtocol (KnownProtocolKind::Decodable)) {
115+ for (auto &entry : properties) {
116+ const auto *pbd = entry.second ->getParentPatternBinding ();
117+ if (pbd && pbd->isDefaultInitializable ()) {
118+ continue ;
146119 }
147120
148- if (varDecl ->isParentInitialized ())
121+ if (entry. second ->isParentInitialized ()) {
149122 continue ;
123+ }
150124
151125 // The var was not default initializable, and did not have an explicit
152126 // initial value.
153127 propertiesAreValid = false ;
154- it-> second ->diagnose (diag::codable_non_decoded_property_here,
155- derived.getProtocolType (), it-> first );
128+ entry. second ->diagnose (diag::codable_non_decoded_property_here,
129+ derived.getProtocolType (), entry. first );
156130 }
157131 }
158132
@@ -265,8 +239,8 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
265239 // For classes which inherit from something Encodable or Decodable, we
266240 // provide case `super` as the first key (to be used in encoding super).
267241 auto *classDecl = dyn_cast<ClassDecl>(target);
268- if (classDecl &&
269- ( superclassIsEncodable ( classDecl) || superclassIsDecodable (classDecl) )) {
242+ if (superclassConformsTo ( classDecl, KnownProtocolKind::Encodable) ||
243+ superclassConformsTo ( classDecl, KnownProtocolKind::Decodable )) {
270244 // TODO: Ensure the class doesn't already have or inherit a variable named
271245 // "`super`"; otherwise we will generate an invalid enum. In that case,
272246 // diagnose and bail.
@@ -279,9 +253,11 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
279253 // Each of these vars needs a case in the enum. For each var decl, if the type
280254 // conforms to {En,De}codable, add it to the enum.
281255 bool allConform = true ;
256+ auto *conformanceDC = derived.getConformanceContext ();
282257 for (auto *varDecl : target->getStoredProperties ()) {
283- if (!varDecl->isUserAccessible ())
258+ if (!varDecl->isUserAccessible ()) {
284259 continue ;
260+ }
285261
286262 auto target =
287263 conformanceDC->mapTypeIntoContext (varDecl->getValueInterfaceType ());
@@ -578,8 +554,8 @@ deriveBodyEncodable_encode(AbstractFunctionDecl *encodeDecl, void *) {
578554 }
579555
580556 // Classes which inherit from something Codable should encode super as well.
581- auto *classDecl = dyn_cast<ClassDecl>(targetDecl);
582- if (classDecl && superclassIsEncodable (classDecl )) {
557+ if ( superclassConformsTo ( dyn_cast<ClassDecl>(targetDecl),
558+ KnownProtocolKind::Encodable )) {
583559 // Need to generate `try super.encode(to: container.superEncoder())`
584560
585561 // superEncoder()
@@ -661,8 +637,8 @@ static FuncDecl *deriveEncodable_encode(DerivedConformance &derived) {
661637
662638 // This method should be marked as 'override' for classes inheriting Encodable
663639 // conformance from a parent class.
664- auto *classDecl = dyn_cast<ClassDecl>(derived.Nominal );
665- if (classDecl && superclassIsEncodable (classDecl )) {
640+ if ( superclassConformsTo ( dyn_cast<ClassDecl>(derived.Nominal ),
641+ KnownProtocolKind::Encodable )) {
666642 auto *attr = new (C) OverrideAttr (/* IsImplicit=*/ true );
667643 encodeDecl->getAttrs ().add (attr);
668644 }
@@ -869,7 +845,7 @@ deriveBodyDecodable_init(AbstractFunctionDecl *initDecl, void *) {
869845 // superclass is Decodable, or super.init() if it is not.
870846 if (auto *classDecl = dyn_cast<ClassDecl>(targetDecl)) {
871847 if (auto *superclassDecl = classDecl->getSuperclassDecl ()) {
872- if (superclassIsDecodable (classDecl)) {
848+ if (superclassConformsTo (classDecl, KnownProtocolKind::Decodable )) {
873849 // Need to generate `try super.init(from: container.superDecoder())`
874850
875851 // container.superDecoder
@@ -903,7 +879,8 @@ deriveBodyDecodable_init(AbstractFunctionDecl *initDecl, void *) {
903879 statements.push_back (tryExpr);
904880 } else {
905881 // The explicit constructor name is a compound name taking no arguments.
906- DeclName initName (C, DeclBaseName::createConstructor (), ArrayRef<Identifier>());
882+ DeclName initName (C, DeclBaseName::createConstructor (),
883+ ArrayRef<Identifier>());
907884
908885 // We need to look this up in the superclass to see if it throws.
909886 auto result = superclassDecl->lookupDirect (initName);
@@ -1075,16 +1052,14 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) {
10751052 }
10761053 }
10771054
1078- // If the target already has a valid CodingKeys enum, we won't need to
1079- // synthesize one.
10801055 switch (classifyCodingKeys (derived)) {
10811056 case CodingKeysClassification::Invalid:
10821057 return false ;
10831058 case CodingKeysClassification::NeedsSynthesizedCodingKeys: {
10841059 auto *synthesizedEnum = synthesizeCodingKeysEnum (derived);
10851060 if (!synthesizedEnum)
10861061 return false ;
1087- }
1062+ }
10881063 LLVM_FALLTHROUGH;
10891064 case CodingKeysClassification::Valid:
10901065 return true ;
0 commit comments