@@ -246,6 +246,9 @@ enum class ImplicitConstructorKind {
246
246
// / the instance variables from a parameter of the same type and
247
247
// / name.
248
248
Memberwise,
249
+ // / The constructor of a type wrapped type that accepts an instance of
250
+ // / type wrapper i.e. `init(storageWrapper: Wrapper<Self, $Storage>)`.
251
+ TypeWrapperStorage,
249
252
// / The memberwise constructor of a type wrapped type which is going to
250
253
// / initialize underlying storage for all applicable properties.
251
254
TypeWrapperMemberwise,
@@ -372,6 +375,37 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
372
375
373
376
params.push_back (arg);
374
377
}
378
+ } else if (ICK == ImplicitConstructorKind::TypeWrapperStorage) {
379
+ accessLevel = AccessLevel::Public;
380
+
381
+ auto *typeWrapper = decl->getTypeWrapper ();
382
+
383
+ auto *arg = new (ctx) ParamDecl (SourceLoc (), Loc, ctx.Id_storageWrapper ,
384
+ Loc, ctx.Id_storageWrapper , decl);
385
+
386
+ auto typeWrapperType = typeWrapper->getDeclaredInterfaceType ();
387
+
388
+ TypeSubstitutionMap subs;
389
+ {
390
+ auto genericParams =
391
+ typeWrapper->getGenericSignature ().getInnermostGenericParams ();
392
+ // Wrapped -> wrapped type
393
+ subs[genericParams[0 ]->getCanonicalType ()->castTo <SubstitutableType>()] =
394
+ decl->getDeclaredInterfaceType ();
395
+ // Storage -> $Storage
396
+ subs[genericParams[1 ]->getCanonicalType ()->castTo <SubstitutableType>()] =
397
+ decl->getTypeWrapperStorageDecl ()->getDeclaredInterfaceType ();
398
+ }
399
+
400
+ auto paramType = typeWrapperType.subst (SubstitutionMap::get (
401
+ typeWrapper->getGenericSignature (), QueryTypeSubstitutionMap{subs},
402
+ LookUpConformanceInModule (decl->getParentModule ())));
403
+
404
+ arg->setSpecifier (ParamSpecifier::Default);
405
+ arg->setInterfaceType (paramType);
406
+ arg->setImplicit ();
407
+
408
+ params.push_back (arg);
375
409
} else if (ICK == ImplicitConstructorKind::TypeWrapperMemberwise) {
376
410
// Access to the initializer should match that of its parent type.
377
411
accessLevel = decl->getEffectiveAccess ();
@@ -1261,6 +1295,11 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
1261
1295
if (!shouldAttemptInitializerSynthesis (decl)) {
1262
1296
if (decl->hasTypeWrapper ()) {
1263
1297
auto &ctx = decl->getASTContext ();
1298
+
1299
+ // Synthesize a special `init(storageWrapper: <Wrapper>)`
1300
+ // initializer if possible.
1301
+ (void )decl->getTypeWrappedTypeStorageInitializer ();
1302
+
1264
1303
// If declaration is type wrapped and there are no
1265
1304
// designated initializers, synthesize a special
1266
1305
// memberwise initializer that would instantiate `$storage`.
@@ -1588,6 +1627,34 @@ void swift::addNonIsolatedToSynthesized(
1588
1627
value->getAttrs ().add (new (ctx) NonisolatedAttr (/* isImplicit=*/ true ));
1589
1628
}
1590
1629
1630
+ static std::pair<BraceStmt *, /* isTypeChecked=*/ bool >
1631
+ synthesizeTypeWrappedTypeStorageWrapperInitializerBody (
1632
+ AbstractFunctionDecl *decl, void *) {
1633
+ return {nullptr , /* isTypeChecked=*/ false };
1634
+ }
1635
+
1636
+ ConstructorDecl *SynthesizeTypeWrappedTypeStorageWrapperInitializer::evaluate (
1637
+ Evaluator &evaluator, NominalTypeDecl *wrappedType) const {
1638
+ if (!wrappedType->hasTypeWrapper ())
1639
+ return nullptr ;
1640
+
1641
+ // `@typeWrapperIgnored` properties suppress this initializer.
1642
+ if (llvm::any_of (wrappedType->getMembers (), [&](Decl *member) {
1643
+ return member->getAttrs ().hasAttribute <TypeWrapperIgnoredAttr>();
1644
+ }))
1645
+ return nullptr ;
1646
+
1647
+ // Create the implicit type wrapper storage constructor.
1648
+ auto &ctx = wrappedType->getASTContext ();
1649
+ auto ctor = createImplicitConstructor (
1650
+ wrappedType, ImplicitConstructorKind::TypeWrapperStorage, ctx);
1651
+ wrappedType->addMember (ctor);
1652
+
1653
+ ctor->setBodySynthesizer (
1654
+ synthesizeTypeWrappedTypeStorageWrapperInitializerBody);
1655
+ return ctor;
1656
+ }
1657
+
1591
1658
static std::pair<BraceStmt *, /* isTypeChecked=*/ bool >
1592
1659
synthesizeTypeWrappedTypeMemberwiseInitializerBody (AbstractFunctionDecl *decl,
1593
1660
void *) {
0 commit comments