@@ -1201,6 +1201,93 @@ SynthesizeMemberwiseInitRequest::evaluate(Evaluator &evaluator,
1201
1201
return ctor;
1202
1202
}
1203
1203
1204
+ llvm::Expected<ConstructorDecl *>
1205
+ ResolveEffectiveMemberwiseInitRequest::evaluate (Evaluator &evaluator,
1206
+ NominalTypeDecl *decl) const {
1207
+ // Compute the access level for the memberwise initializer. The minimum of:
1208
+ // - Public, by default. This enables public nominal types to have public
1209
+ // memberwise initializers.
1210
+ // - The `public` default is important for synthesized member types, e.g.
1211
+ // `TangentVector` structs synthesized during `Differentiable` derived
1212
+ // conformances. Manually extending these types to define a public
1213
+ // memberwise initializer causes a redeclaration error.
1214
+ // - The minimum access level of memberwise-initialized properties in the
1215
+ // nominal type declaration.
1216
+ auto accessLevel = AccessLevel::Public;
1217
+ for (auto *member : decl->getMembers ()) {
1218
+ auto *var = dyn_cast<VarDecl>(member);
1219
+ if (!var ||
1220
+ !var->isMemberwiseInitialized (/* preferDeclaredProperties*/ true ))
1221
+ continue ;
1222
+ accessLevel = std::min (accessLevel, var->getFormalAccess ());
1223
+ }
1224
+ auto &ctx = decl->getASTContext ();
1225
+
1226
+ // If a memberwise initializer exists, set its access level and return it.
1227
+ if (auto *initDecl = decl->getMemberwiseInitializer ()) {
1228
+ initDecl->overwriteAccess (accessLevel);
1229
+ return initDecl;
1230
+ }
1231
+
1232
+ auto isEffectiveMemberwiseInitializer = [&](ConstructorDecl *initDecl) {
1233
+ // Check for `nullptr`.
1234
+ if (!initDecl)
1235
+ return false ;
1236
+ // Get all stored properties, excluding `let` properties with initial
1237
+ // values.
1238
+ SmallVector<VarDecl *, 8 > storedProperties;
1239
+ for (auto *vd : decl->getStoredProperties ()) {
1240
+ if (vd->isLet () && vd->hasInitialValue ())
1241
+ continue ;
1242
+ storedProperties.push_back (vd);
1243
+ }
1244
+ // Return false if initializer does not have interface type set. It is not
1245
+ // possible to determine whether it is a memberwise initializer.
1246
+ if (!initDecl->hasInterfaceType ())
1247
+ return false ;
1248
+ auto initDeclType =
1249
+ initDecl->getMethodInterfaceType ()->getAs <AnyFunctionType>();
1250
+ // Return false if initializer does not have a valid interface type.
1251
+ if (!initDeclType)
1252
+ return false ;
1253
+ // Return false if stored property count does not have parameter count.
1254
+ if (storedProperties.size () != initDeclType->getNumParams ())
1255
+ return false ;
1256
+ // Return true if all stored property types/names match initializer
1257
+ // parameter types/labels.
1258
+ return llvm::all_of (
1259
+ llvm::zip (storedProperties, initDeclType->getParams ()),
1260
+ [&](std::tuple<VarDecl *, AnyFunctionType::Param> pair) {
1261
+ auto *storedProp = std::get<0 >(pair);
1262
+ auto param = std::get<1 >(pair);
1263
+ return storedProp->getInterfaceType ()->isEqual (
1264
+ param.getPlainType ()) &&
1265
+ storedProp->getName () == param.getLabel ();
1266
+ });
1267
+ };
1268
+
1269
+ // Otherwise, look for a user-defined effective memberwise initializer.
1270
+ ConstructorDecl *memberwiseInitDecl = nullptr ;
1271
+ auto initDecls = decl->lookupDirect (DeclBaseName::createConstructor ());
1272
+ for (auto *decl : initDecls) {
1273
+ auto *initDecl = dyn_cast<ConstructorDecl>(decl);
1274
+ if (!isEffectiveMemberwiseInitializer (initDecl))
1275
+ continue ;
1276
+ assert (!memberwiseInitDecl && " Memberwise initializer already found" );
1277
+ memberwiseInitDecl = initDecl;
1278
+ }
1279
+
1280
+ // Otherwise, create a memberwise initializer, set its access level, and
1281
+ // return it.
1282
+ if (!memberwiseInitDecl) {
1283
+ memberwiseInitDecl = createImplicitConstructor (
1284
+ decl, ImplicitConstructorKind::Memberwise, ctx);
1285
+ memberwiseInitDecl->overwriteAccess (accessLevel);
1286
+ decl->addMember (memberwiseInitDecl);
1287
+ }
1288
+ return memberwiseInitDecl;
1289
+ }
1290
+
1204
1291
llvm::Expected<bool >
1205
1292
HasDefaultInitRequest::evaluate (Evaluator &evaluator,
1206
1293
NominalTypeDecl *decl) const {
@@ -1263,3 +1350,22 @@ SynthesizeDefaultInitRequest::evaluate(Evaluator &evaluator,
1263
1350
ctor->setBodySynthesizer (synthesizeSingleReturnFunctionBody);
1264
1351
return ctor;
1265
1352
}
1353
+
1354
+ ValueDecl *swift::getProtocolRequirement (ProtocolDecl *protocol,
1355
+ Identifier name) {
1356
+ auto lookup = protocol->lookupDirect (name);
1357
+ // Erase declarations that are not protocol requirements.
1358
+ // This is important for removing default implementations of the same name.
1359
+ llvm::erase_if (lookup, [](ValueDecl *v) {
1360
+ return !isa<ProtocolDecl>(v->getDeclContext ()) ||
1361
+ !v->isProtocolRequirement ();
1362
+ });
1363
+ assert (lookup.size () == 1 && " Ambiguous protocol requirement" );
1364
+ return lookup.front ();
1365
+ }
1366
+
1367
+ bool swift::hasLetStoredPropertyWithInitialValue (NominalTypeDecl *nominal) {
1368
+ return llvm::any_of (nominal->getStoredProperties (), [&](VarDecl *v) {
1369
+ return v->isLet () && v->hasInitialValue ();
1370
+ });
1371
+ }
0 commit comments