@@ -29,38 +29,15 @@ using namespace swift;
29
29
30
30
// / Returns whether the type represented by the given ClassDecl inherits from a
31
31
// / 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 ()) {
38
34
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 ();
64
41
}
65
42
66
43
// / Retrieve the variable name for the purposes of encoding/decoding.
@@ -134,25 +111,22 @@ static bool validateCodingKeysEnum(const DerivedConformance &derived,
134
111
// If there are any remaining properties which the CodingKeys did not cover,
135
112
// we can skip them on encode. On decode, though, we can only skip them if
136
113
// 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 ;
146
119
}
147
120
148
- if (varDecl ->isParentInitialized ())
121
+ if (entry. second ->isParentInitialized ()) {
149
122
continue ;
123
+ }
150
124
151
125
// The var was not default initializable, and did not have an explicit
152
126
// initial value.
153
127
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 );
156
130
}
157
131
}
158
132
@@ -265,8 +239,8 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
265
239
// For classes which inherit from something Encodable or Decodable, we
266
240
// provide case `super` as the first key (to be used in encoding super).
267
241
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 )) {
270
244
// TODO: Ensure the class doesn't already have or inherit a variable named
271
245
// "`super`"; otherwise we will generate an invalid enum. In that case,
272
246
// diagnose and bail.
@@ -279,9 +253,11 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
279
253
// Each of these vars needs a case in the enum. For each var decl, if the type
280
254
// conforms to {En,De}codable, add it to the enum.
281
255
bool allConform = true ;
256
+ auto *conformanceDC = derived.getConformanceContext ();
282
257
for (auto *varDecl : target->getStoredProperties ()) {
283
- if (!varDecl->isUserAccessible ())
258
+ if (!varDecl->isUserAccessible ()) {
284
259
continue ;
260
+ }
285
261
286
262
auto target =
287
263
conformanceDC->mapTypeIntoContext (varDecl->getValueInterfaceType ());
@@ -578,8 +554,8 @@ deriveBodyEncodable_encode(AbstractFunctionDecl *encodeDecl, void *) {
578
554
}
579
555
580
556
// 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 )) {
583
559
// Need to generate `try super.encode(to: container.superEncoder())`
584
560
585
561
// superEncoder()
@@ -661,8 +637,8 @@ static FuncDecl *deriveEncodable_encode(DerivedConformance &derived) {
661
637
662
638
// This method should be marked as 'override' for classes inheriting Encodable
663
639
// 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 )) {
666
642
auto *attr = new (C) OverrideAttr (/* IsImplicit=*/ true );
667
643
encodeDecl->getAttrs ().add (attr);
668
644
}
@@ -869,7 +845,7 @@ deriveBodyDecodable_init(AbstractFunctionDecl *initDecl, void *) {
869
845
// superclass is Decodable, or super.init() if it is not.
870
846
if (auto *classDecl = dyn_cast<ClassDecl>(targetDecl)) {
871
847
if (auto *superclassDecl = classDecl->getSuperclassDecl ()) {
872
- if (superclassIsDecodable (classDecl)) {
848
+ if (superclassConformsTo (classDecl, KnownProtocolKind::Decodable )) {
873
849
// Need to generate `try super.init(from: container.superDecoder())`
874
850
875
851
// container.superDecoder
@@ -903,7 +879,8 @@ deriveBodyDecodable_init(AbstractFunctionDecl *initDecl, void *) {
903
879
statements.push_back (tryExpr);
904
880
} else {
905
881
// 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>());
907
884
908
885
// We need to look this up in the superclass to see if it throws.
909
886
auto result = superclassDecl->lookupDirect (initName);
@@ -1075,16 +1052,14 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) {
1075
1052
}
1076
1053
}
1077
1054
1078
- // If the target already has a valid CodingKeys enum, we won't need to
1079
- // synthesize one.
1080
1055
switch (classifyCodingKeys (derived)) {
1081
1056
case CodingKeysClassification::Invalid:
1082
1057
return false ;
1083
1058
case CodingKeysClassification::NeedsSynthesizedCodingKeys: {
1084
1059
auto *synthesizedEnum = synthesizeCodingKeysEnum (derived);
1085
1060
if (!synthesizedEnum)
1086
1061
return false ;
1087
- }
1062
+ }
1088
1063
LLVM_FALLTHROUGH;
1089
1064
case CodingKeysClassification::Valid:
1090
1065
return true ;
0 commit comments