@@ -61,59 +61,6 @@ static bool superclassIsDecodable(ClassDecl *target) {
61
61
C.getProtocol (KnownProtocolKind::Decodable));
62
62
}
63
63
64
- // / Represents the possible outcomes of checking whether a decl conforms to
65
- // / Encodable or Decodable.
66
- enum CodableConformanceType {
67
- TypeNotValidated,
68
- DoesNotConform,
69
- Conforms
70
- };
71
-
72
- // / Returns whether the given type conforms to the given {En,De}codable
73
- // / protocol.
74
- // /
75
- // / \param context The \c DeclContext the var declarations belong to.
76
- // /
77
- // / \param target The \c Type to validate.
78
- // /
79
- // / \param proto The \c ProtocolDecl to check conformance to.
80
- static CodableConformanceType typeConformsToCodable (DeclContext *context,
81
- Type target, bool isIUO,
82
- ProtocolDecl *proto) {
83
- target = context->mapTypeIntoContext (target);
84
-
85
- if (isIUO)
86
- target = target->lookThroughSingleOptionalType ();
87
-
88
- auto conf = TypeChecker::conformsToProtocol (target, proto, context);
89
- return conf.isInvalid () ? DoesNotConform : Conforms;
90
- }
91
-
92
- // / Returns whether the given variable conforms to the given {En,De}codable
93
- // / protocol.
94
- // /
95
- // / \param DC The \c DeclContext in which to check conformance.
96
- // /
97
- // / \param varDecl The \c VarDecl to validate.
98
- // /
99
- // / \param proto The \c ProtocolDecl to check conformance to.
100
- static CodableConformanceType
101
- varConformsToCodable (DeclContext *DC, VarDecl *varDecl, ProtocolDecl *proto) {
102
- // If the decl doesn't yet have a type, we may be seeing it before the type
103
- // checker has gotten around to evaluating its type. For example:
104
- //
105
- // func foo() {
106
- // let b = Bar(from: decoder) // <- evaluates Bar conformance to Codable,
107
- // // forcing derivation
108
- // }
109
- //
110
- // struct Bar : Codable {
111
- // var x: Int // <- we get to valuate x's var decl here, but its type
112
- // // hasn't yet been evaluated
113
- // }
114
- bool isIUO = varDecl->isImplicitlyUnwrappedOptional ();
115
- return typeConformsToCodable (DC, varDecl->getValueInterfaceType (), isIUO,
116
- proto);
117
64
}
118
65
119
66
// / Retrieve the variable name for the purposes of encoding/decoding.
@@ -164,34 +111,20 @@ static bool validateCodingKeysEnum(DerivedConformance &derived,
164
111
}
165
112
166
113
// We have a property to map to. Ensure it's {En,De}codable.
167
- auto conformance =
168
- varConformsToCodable (conformanceDC, it->second , derived.Protocol );
169
- switch (conformance) {
170
- case Conforms:
171
- // The property was valid. Remove it from the list.
172
- properties.erase (it);
173
- break ;
174
-
175
- case DoesNotConform: {
176
- // We use a TypeLoc here so diagnostics can show the type
177
- // as written by the user in source if possible. This is useful
178
- // when the user has written an IUO type for example, since
179
- // diagnostics would show the type as 'T?' instead of 'T!' if
180
- // we use a Type instead.
181
- TypeLoc typeLoc = {
182
- it->second ->getTypeReprOrParentPatternTypeRepr (),
183
- it->second ->getType (),
184
- };
185
- it->second ->diagnose (diag::codable_non_conforming_property_here,
186
- derived.getProtocolType (), typeLoc);
187
- LLVM_FALLTHROUGH;
188
- }
189
-
190
- case TypeNotValidated:
191
- // We don't produce a diagnostic for a type which failed to validate.
192
- // This will produce a diagnostic elsewhere anyway.
193
- propertiesAreValid = false ;
194
- continue ;
114
+ auto target =
115
+ conformanceDC->mapTypeIntoContext (it->second ->getValueInterfaceType ());
116
+ if (TypeChecker::conformsToProtocol (target, derived.Protocol , conformanceDC)
117
+ .isInvalid ()) {
118
+ TypeLoc typeLoc = {
119
+ it->second ->getTypeReprOrParentPatternTypeRepr (),
120
+ it->second ->getType (),
121
+ };
122
+ it->second ->diagnose (diag::codable_non_conforming_property_here,
123
+ derived.getProtocolType (), typeLoc);
124
+ propertiesAreValid = false ;
125
+ } else {
126
+ // The property was valid. Remove it from the list.
127
+ properties.erase (it);
195
128
}
196
129
}
197
130
@@ -344,44 +277,23 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) {
344
277
if (!varDecl->isUserAccessible ())
345
278
continue ;
346
279
347
- // Despite creating the enum in the context of the type, we're
348
- // concurrently checking the variables for the current protocol
349
- // conformance being synthesized, for which we use the conformance
350
- // context, not the type.
351
- auto conformance = varConformsToCodable (derived.getConformanceContext (),
352
- varDecl, derived.Protocol );
353
- switch (conformance) {
354
- case Conforms:
355
- {
356
- auto *elt = new (C) EnumElementDecl (SourceLoc (),
357
- getVarNameForCoding (varDecl),
358
- nullptr , SourceLoc (), nullptr ,
359
- enumDecl);
360
- elt->setImplicit ();
361
- enumDecl->addMember (elt);
362
- break ;
363
- }
364
-
365
- case DoesNotConform: {
366
- // We use a TypeLoc here so diagnostics can show the type
367
- // as written by the user in source if possible. This is useful
368
- // when the user has written an IUO type for example, since
369
- // diagnostics would show the type as 'T?' instead of 'T!' if
370
- // we use a Type instead.
371
- TypeLoc typeLoc = {
372
- varDecl->getTypeReprOrParentPatternTypeRepr (),
373
- varDecl->getType (),
374
- };
375
- varDecl->diagnose (diag::codable_non_conforming_property_here,
376
- derived.getProtocolType (), typeLoc);
377
- LLVM_FALLTHROUGH;
378
- }
379
-
380
- case TypeNotValidated:
381
- // We don't produce a diagnostic for a type which failed to validate.
382
- // This will produce a diagnostic elsewhere anyway.
383
- allConform = false ;
384
- continue ;
280
+ auto target =
281
+ conformanceDC->mapTypeIntoContext (varDecl->getValueInterfaceType ());
282
+ if (TypeChecker::conformsToProtocol (target, derived.Protocol , conformanceDC)
283
+ .isInvalid ()) {
284
+ TypeLoc typeLoc = {
285
+ varDecl->getTypeReprOrParentPatternTypeRepr (),
286
+ varDecl->getType (),
287
+ };
288
+ varDecl->diagnose (diag::codable_non_conforming_property_here,
289
+ derived.getProtocolType (), typeLoc);
290
+ allConform = false ;
291
+ } else {
292
+ auto *elt =
293
+ new (C) EnumElementDecl (SourceLoc (), getVarNameForCoding (varDecl),
294
+ nullptr , SourceLoc (), nullptr , enumDecl);
295
+ elt->setImplicit ();
296
+ enumDecl->addMember (elt);
385
297
}
386
298
}
387
299
0 commit comments