@@ -232,6 +232,9 @@ enum class ImplicitConstructorKind {
232
232
// / the instance variables from a parameter of the same type and
233
233
// / name.
234
234
Memberwise,
235
+ // / The constructor of a type wrapped type that accepts an instance of
236
+ // / type wrapper i.e. `init(storageWrapper: Wrapper<Self, $Storage>)`.
237
+ TypeWrapperStorage,
235
238
// / The memberwise constructor of a type wrapped type which is going to
236
239
// / initialize underlying storage for all applicable properties.
237
240
TypeWrapperMemberwise,
@@ -358,6 +361,37 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
358
361
359
362
params.push_back (arg);
360
363
}
364
+ } else if (ICK == ImplicitConstructorKind::TypeWrapperStorage) {
365
+ accessLevel = AccessLevel::Public;
366
+
367
+ auto *typeWrapper = decl->getTypeWrapper ();
368
+
369
+ auto *arg = new (ctx) ParamDecl (SourceLoc (), Loc, ctx.Id_storageWrapper ,
370
+ Loc, ctx.Id_storageWrapper , decl);
371
+
372
+ auto typeWrapperType = typeWrapper->getDeclaredInterfaceType ();
373
+
374
+ TypeSubstitutionMap subs;
375
+ {
376
+ auto genericParams =
377
+ typeWrapper->getGenericSignature ().getInnermostGenericParams ();
378
+ // Wrapped -> wrapped type
379
+ subs[genericParams[0 ]->getCanonicalType ()->castTo <SubstitutableType>()] =
380
+ decl->getDeclaredInterfaceType ();
381
+ // Storage -> $Storage
382
+ subs[genericParams[1 ]->getCanonicalType ()->castTo <SubstitutableType>()] =
383
+ decl->getTypeWrapperStorageDecl ()->getDeclaredInterfaceType ();
384
+ }
385
+
386
+ auto paramType = typeWrapperType.subst (SubstitutionMap::get (
387
+ typeWrapper->getGenericSignature (), QueryTypeSubstitutionMap{subs},
388
+ LookUpConformanceInModule (decl->getParentModule ())));
389
+
390
+ arg->setSpecifier (ParamSpecifier::Default);
391
+ arg->setInterfaceType (paramType);
392
+ arg->setImplicit ();
393
+
394
+ params.push_back (arg);
361
395
} else if (ICK == ImplicitConstructorKind::TypeWrapperMemberwise) {
362
396
// Access to the initializer should match that of its parent type.
363
397
accessLevel = decl->getEffectiveAccess ();
@@ -1247,6 +1281,11 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
1247
1281
if (!shouldAttemptInitializerSynthesis (decl)) {
1248
1282
if (decl->hasTypeWrapper ()) {
1249
1283
auto &ctx = decl->getASTContext ();
1284
+
1285
+ // Synthesize a special `init(storageWrapper: <Wrapper>)`
1286
+ // initializer if possible.
1287
+ (void )decl->getTypeWrappedTypeStorageInitializer ();
1288
+
1250
1289
// If declaration is type wrapped and there are no
1251
1290
// designated initializers, synthesize a special
1252
1291
// memberwise initializer that would instantiate `$storage`.
@@ -1574,6 +1613,34 @@ void swift::addNonIsolatedToSynthesized(
1574
1613
value->getAttrs ().add (new (ctx) NonisolatedAttr (/* isImplicit=*/ true ));
1575
1614
}
1576
1615
1616
+ static std::pair<BraceStmt *, /* isTypeChecked=*/ bool >
1617
+ synthesizeTypeWrappedTypeStorageWrapperInitializerBody (
1618
+ AbstractFunctionDecl *decl, void *) {
1619
+ return {nullptr , /* isTypeChecked=*/ false };
1620
+ }
1621
+
1622
+ ConstructorDecl *SynthesizeTypeWrappedTypeStorageWrapperInitializer::evaluate (
1623
+ Evaluator &evaluator, NominalTypeDecl *wrappedType) const {
1624
+ if (!wrappedType->hasTypeWrapper ())
1625
+ return nullptr ;
1626
+
1627
+ // `@typeWrapperIgnored` properties suppress this initializer.
1628
+ if (llvm::any_of (wrappedType->getMembers (), [&](Decl *member) {
1629
+ return member->getAttrs ().hasAttribute <TypeWrapperIgnoredAttr>();
1630
+ }))
1631
+ return nullptr ;
1632
+
1633
+ // Create the implicit type wrapper storage constructor.
1634
+ auto &ctx = wrappedType->getASTContext ();
1635
+ auto ctor = createImplicitConstructor (
1636
+ wrappedType, ImplicitConstructorKind::TypeWrapperStorage, ctx);
1637
+ wrappedType->addMember (ctor);
1638
+
1639
+ ctor->setBodySynthesizer (
1640
+ synthesizeTypeWrappedTypeStorageWrapperInitializerBody);
1641
+ return ctor;
1642
+ }
1643
+
1577
1644
static std::pair<BraceStmt *, /* isTypeChecked=*/ bool >
1578
1645
synthesizeTypeWrappedTypeMemberwiseInitializerBody (AbstractFunctionDecl *decl,
1579
1646
void *) {
0 commit comments