@@ -184,8 +184,7 @@ static bool
184
184
validateCodingKeysEnum (TypeChecker &tc, EnumDecl *codingKeysDecl,
185
185
NominalTypeDecl *target, ProtocolDecl *proto) {
186
186
// Look through all var decls in the given type.
187
- // * Filter out lazy/computed vars (currently already done by
188
- // getStoredProperties).
187
+ // * Filter out lazy/computed vars.
189
188
// * Filter out ones which are present in the given decl (by name).
190
189
//
191
190
// If any of the entries in the CodingKeys decl are not present in the type
@@ -197,6 +196,9 @@ validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
197
196
// against its CodingKey entry, it will get removed.
198
197
llvm::SmallDenseMap<Identifier, VarDecl *, 8 > properties;
199
198
for (auto *varDecl : target->getStoredProperties (/* skipInaccessible=*/ true )) {
199
+ if (varDecl->getAttrs ().hasAttribute <LazyAttr>())
200
+ continue ;
201
+
200
202
properties[varDecl->getName ()] = varDecl;
201
203
}
202
204
@@ -242,7 +244,7 @@ validateCodingKeysEnum(TypeChecker &tc, EnumDecl *codingKeysDecl,
242
244
// we can skip them on encode. On decode, though, we can only skip them if
243
245
// they have a default value.
244
246
if (!properties.empty () &&
245
- proto == tc. Context . getProtocol (KnownProtocolKind::Decodable)) {
247
+ proto-> isSpecificProtocol (KnownProtocolKind::Decodable)) {
246
248
for (auto it = properties.begin (); it != properties.end (); ++it) {
247
249
if (it->second ->getParentInitializer () != nullptr ) {
248
250
// Var has a default value.
@@ -303,6 +305,9 @@ static CodingKeysValidity hasValidCodingKeysEnum(TypeChecker &tc,
303
305
return CodingKeysValidity (/* hasType=*/ true , /* isValid=*/ false );
304
306
}
305
307
308
+ // If the decl hasn't been validated yet, do so.
309
+ tc.validateDecl (codingKeysTypeDecl);
310
+
306
311
// CodingKeys may be a typealias. If so, follow the alias to its canonical
307
312
// type.
308
313
auto codingKeysType = codingKeysTypeDecl->getDeclaredInterfaceType ();
@@ -381,6 +386,9 @@ static EnumDecl *synthesizeCodingKeysEnum(TypeChecker &tc,
381
386
// conforms to {En,De}codable, add it to the enum.
382
387
bool allConform = true ;
383
388
for (auto *varDecl : target->getStoredProperties (/* skipInaccessible=*/ true )) {
389
+ if (varDecl->getAttrs ().hasAttribute <LazyAttr>())
390
+ continue ;
391
+
384
392
auto conformance = varConformsToCodable (tc, target->getDeclContext (),
385
393
varDecl, proto);
386
394
switch (conformance) {
@@ -528,7 +536,7 @@ static CallExpr *createContainerKeyedByCall(ASTContext &C, DeclContext *DC,
528
536
// / Synthesizes the body for `func encode(to encoder: Encoder) throws`.
529
537
// /
530
538
// / \param encodeDecl The function decl whose body to synthesize.
531
- static BraceStmt * deriveBodyEncodable_encode (AbstractFunctionDecl *encodeDecl) {
539
+ static void deriveBodyEncodable_encode (AbstractFunctionDecl *encodeDecl) {
532
540
// struct Foo : Codable {
533
541
// var x: Int
534
542
// var y: String
@@ -696,8 +704,9 @@ static BraceStmt *deriveBodyEncodable_encode(AbstractFunctionDecl *encodeDecl) {
696
704
statements.push_back (tryExpr);
697
705
}
698
706
699
- return BraceStmt::create (C, SourceLoc (), statements, SourceLoc (),
700
- /* implicit=*/ true );
707
+ auto *body = BraceStmt::create (C, SourceLoc (), statements, SourceLoc (),
708
+ /* implicit=*/ true );
709
+ encodeDecl->setBody (body);
701
710
}
702
711
703
712
// / Synthesizes a function declaration for `encode(to: Encoder) throws` with a
@@ -756,7 +765,7 @@ static FuncDecl *deriveEncodable_encode(TypeChecker &tc, Decl *parentDecl,
756
765
TypeLoc::withoutLoc (returnType),
757
766
target);
758
767
encodeDecl->setImplicit ();
759
- encodeDecl->setBody (deriveBodyEncodable_encode (encodeDecl) );
768
+ encodeDecl->setBodySynthesizer (deriveBodyEncodable_encode);
760
769
761
770
// This method should be marked as 'override' for classes inheriting Encodable
762
771
// conformance from a parent class.
@@ -962,10 +971,10 @@ static BraceStmt *deriveBodyDecodable_init(TypeChecker &tc,
962
971
// superclass is Decodable, or super.init() if it is not.
963
972
if (auto *classDecl = dyn_cast<ClassDecl>(targetDecl)) {
964
973
if (auto *superclassDecl = classDecl->getSuperclassDecl ()) {
965
- auto superType = superclassDecl->getDeclaredInterfaceType ();
974
+ auto superType = superclassDecl->getDeclaredInterfaceType ();
966
975
if (tc.conformsToProtocol (superType,
967
976
C.getProtocol (KnownProtocolKind::Decodable),
968
- superclassDecl, ConformanceCheckFlags::Used )) {
977
+ superclassDecl, ConformanceCheckOptions () )) {
969
978
// Need to generate `try super.init(from: container.superDecoder())`
970
979
971
980
// container.superDecoder
@@ -984,7 +993,7 @@ static BraceStmt *deriveBodyDecodable_init(TypeChecker &tc,
984
993
SourceLoc (), /* Implicit=*/ true );
985
994
986
995
// super.init(from:)
987
- auto initName = DeclName (C, C.Id_init , (Identifier[ 1 ]){ C.Id_from } );
996
+ auto initName = DeclName (C, C.Id_init , C.Id_from );
988
997
auto *initCall = new (C) UnresolvedDotExpr (superRef, SourceLoc (),
989
998
initName, DeclNameLoc (),
990
999
/* Implicit=*/ true );
@@ -1005,21 +1014,12 @@ static BraceStmt *deriveBodyDecodable_init(TypeChecker &tc,
1005
1014
DeclName initName (C, C.Id_init , ArrayRef<Identifier>());
1006
1015
1007
1016
// We need to look this up in the superclass to see if it throws.
1008
- // We should have bailed one level up if super.init() is not available.
1009
1017
ConstructorDecl *superInitDecl = nullptr ;
1010
- for (auto *decl : superclassDecl->getMembers ()) {
1011
- auto *ctorDecl = dyn_cast<ConstructorDecl>(decl);
1012
- if (!ctorDecl)
1013
- continue ;
1014
-
1015
- if (ctorDecl->getParameters ()->size () == 0 ) {
1016
- superInitDecl = ctorDecl;
1017
- break ;
1018
- }
1019
- }
1018
+ auto result = superclassDecl->lookupDirect (initName);
1020
1019
1021
1020
// We should have bailed one level up if this were not available.
1022
- assert (superInitDecl);
1021
+ assert (!result.empty () &&
1022
+ (superInitDecl = dyn_cast<ConstructorDecl>(result.front ())));
1023
1023
1024
1024
// super
1025
1025
auto *superRef = new (C) SuperRefExpr (initDecl->getImplicitSelfDecl (),
@@ -1030,18 +1030,20 @@ static BraceStmt *deriveBodyDecodable_init(TypeChecker &tc,
1030
1030
initName, DeclNameLoc (),
1031
1031
/* Implicit=*/ true );
1032
1032
// super.init() call
1033
- auto *callExpr = CallExpr::createImplicit (C, superInitRef,
1033
+ Expr *callExpr = CallExpr::createImplicit (C, superInitRef,
1034
1034
ArrayRef<Expr *>(),
1035
1035
ArrayRef<Identifier>());
1036
1036
1037
- if (superInitDecl->hasThrows ()) {
1038
- // try super.init()
1039
- auto *tryExpr = new (C) TryExpr (SourceLoc (), callExpr, Type (),
1040
- /* Implicit=*/ true );
1041
- statements.push_back (tryExpr);
1042
- } else {
1043
- statements.push_back (callExpr);
1044
- }
1037
+ // If super.init is failable, super.init()!
1038
+ if (superInitDecl->getFailability () != OTK_None)
1039
+ callExpr = new (C) ForceValueExpr (callExpr, SourceLoc ());
1040
+
1041
+ // If super.init throws, try super.init()
1042
+ if (superInitDecl->hasThrows ())
1043
+ callExpr = new (C) TryExpr (SourceLoc (), callExpr, Type (),
1044
+ /* Implicit=*/ true );
1045
+
1046
+ statements.push_back (callExpr);
1045
1047
}
1046
1048
}
1047
1049
}
@@ -1178,14 +1180,14 @@ static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
1178
1180
// synthesize CodingKeys.
1179
1181
ASTContext &C = tc.Context ;
1180
1182
auto *classDecl = dyn_cast<ClassDecl>(target);
1181
- if (proto == C. getProtocol (KnownProtocolKind::Decodable) && classDecl) {
1183
+ if (proto-> isSpecificProtocol (KnownProtocolKind::Decodable) && classDecl) {
1182
1184
if (auto *superclassDecl = classDecl->getSuperclassDecl ()) {
1183
1185
DeclName memberName;
1184
1186
auto superType = superclassDecl->getDeclaredInterfaceType ();
1185
1187
if (tc.conformsToProtocol (superType, proto, superclassDecl,
1186
1188
ConformanceCheckFlags::Used)) {
1187
1189
// super.init(from:) must be accessible.
1188
- memberName = cast<ConstructorDecl>(requirement)->getEffectiveFullName ();
1190
+ memberName = cast<ConstructorDecl>(requirement)->getFullName ();
1189
1191
} else {
1190
1192
// super.init() must be accessible.
1191
1193
// Passing an empty params array constructs a compound name with no
@@ -1199,15 +1201,16 @@ static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
1199
1201
if (result.empty ()) {
1200
1202
// No super initializer for us to call.
1201
1203
tc.diagnose (superclassDecl, diag::decodable_no_super_init_here,
1202
- requirement->getFullName ());
1204
+ requirement->getFullName (), memberName );
1203
1205
return false ;
1204
1206
} else if (result.size () > 1 ) {
1205
1207
// There are multiple results for this lookup. We'll end up producing a
1206
1208
// diagnostic later complaining about duplicate methods (if we haven't
1207
1209
// already), so just bail with a general error.
1208
1210
return false ;
1209
1211
} else {
1210
- auto *initializer = cast<ConstructorDecl>(result.front ().Decl );
1212
+ auto *initializer =
1213
+ cast<ConstructorDecl>(result.front ().getValueDecl ());
1211
1214
if (!initializer->isDesignatedInit ()) {
1212
1215
// We must call a superclass's designated initializer.
1213
1216
tc.diagnose (initializer,
@@ -1221,6 +1224,11 @@ static bool canSynthesize(TypeChecker &tc, NominalTypeDecl *target,
1221
1224
requirement->getFullName (), memberName,
1222
1225
accessScope.accessibilityForDiagnostics ());
1223
1226
return false ;
1227
+ } else if (initializer->getFailability () != OTK_None) {
1228
+ // We can't call super.init() if it's failable, since init(from:)
1229
+ // isn't failable.
1230
+ tc.diagnose (initializer, diag::decodable_super_init_is_failable_here,
1231
+ requirement->getFullName (), memberName);
1224
1232
}
1225
1233
}
1226
1234
}
0 commit comments