Skip to content

Commit 6ff225d

Browse files
committed
[AST/Sema] TypeWrapper: Implement synthesis of init(storageWrapper:) initializer
1 parent 27e6b97 commit 6ff225d

File tree

3 files changed

+79
-1
lines changed

3 files changed

+79
-1
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1616,7 +1616,32 @@ void swift::addNonIsolatedToSynthesized(
16161616
static std::pair<BraceStmt *, /*isTypeChecked=*/bool>
16171617
synthesizeTypeWrappedTypeStorageWrapperInitializerBody(
16181618
AbstractFunctionDecl *decl, void *) {
1619-
return {nullptr, /*isTypeChecked=*/false};
1619+
auto &ctx = decl->getASTContext();
1620+
auto *ctor = cast<ConstructorDecl>(decl);
1621+
auto *wrappedType = ctor->getDeclContext()->getSelfNominalTypeDecl();
1622+
auto *storageProperty = wrappedType->getTypeWrapperProperty();
1623+
1624+
// self.$storage = storageWrapper
1625+
SmallVector<ASTNode, 2> body;
1626+
{
1627+
auto *storageVarRef = UnresolvedDotExpr::createImplicit(
1628+
ctx,
1629+
new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()},
1630+
/*Loc=*/DeclNameLoc(), /*Implicit=*/true),
1631+
storageProperty->getName());
1632+
1633+
auto *paramRef = new (ctx)
1634+
DeclRefExpr(ctor->getParameters()->get(0), /*Loc=*/DeclNameLoc(),
1635+
/*Implicit=*/true);
1636+
1637+
body.push_back(new (ctx) AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(),
1638+
paramRef,
1639+
/*Implicit=*/true));
1640+
}
1641+
1642+
return {BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), body,
1643+
/*rbloc=*/ctor->getLoc(), /*implicit=*/true),
1644+
/*isTypeChecked=*/false};
16201645
}
16211646

16221647
ConstructorDecl *SynthesizeTypeWrappedTypeStorageWrapperInitializer::evaluate(

test/Interpreter/type_wrappers.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,3 +646,23 @@ do {
646646
// CHECK-NEXT: in (reference type) getter storage: \$Storage._c, property: \TypeWithSomeDefaultedLetProperties<Array<Any>>.<{{.*}} (PropWrapper<String>)>
647647
// CHECK-NEXT: a
648648
}
649+
650+
do {
651+
@Wrapper
652+
struct Test<T> {
653+
var a: T
654+
var b: Int
655+
}
656+
657+
let wrapper = Wrapper(for: Test<[Float?]>.self, storage: Test<[Float?]>.$Storage(a: [1.0], b: 42))
658+
// CHECK: Wrapper.init(for: Test<Array<Optional<Float>>>, storage: $Storage(a: [Optional(1.0)], b: 42))
659+
660+
var test = Test(storageWrapper: wrapper)
661+
662+
print(test.a)
663+
print(test.b)
664+
// CHECK-NEXT: in getter storage: \$Storage.a, property: \Test<Array<Optional<Float>>>.<{{.*}} (Array<Optional<Float>>)>
665+
// CHECK-NEXT: [Optional(1.0)]
666+
// CHECK-NEXT: in getter storage: \$Storage.b, property: \Test<Array<Optional<Float>>>.b
667+
// CHECK-NEXT: 42
668+
}

test/type/type_wrapper.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ do {
146146

147147
@typeWrapper
148148
struct NoopWrapper<W, S> {
149+
// expected-note@-1 {{arguments to generic parameter 'W' ('Test1' and 'Test2') are expected to be equal}}
150+
// expected-note@-2 {{arguments to generic parameter 'S' ('Test1.$Storage' and 'Test2.$Storage') are expected to be equal}}
151+
149152
init(for: W.Type, storage: S) {}
150153

151154
subscript<V>(propertyKeyPath _: KeyPath<W, V>, storageKeyPath path: KeyPath<S, V>) -> V {
@@ -608,3 +611,33 @@ do {
608611
var name: String
609612
}
610613
}
614+
615+
do {
616+
@NoopWrapper
617+
struct Test1 {
618+
var a: Int
619+
var b: [String]
620+
}
621+
622+
let wrapper = NoopWrapper(for: Test1.self, storage: Test1.$Storage(a: 42, b: [""]))
623+
_ = Test1(storageWrapper: wrapper) // Ok
624+
625+
@NoopWrapper
626+
struct Test2 {
627+
}
628+
629+
_ = Test2(storageWrapper: NoopWrapper(for: Test2.self, storage: Test2.$Storage())) // Ok
630+
_ = Test2(storageWrapper: wrapper)
631+
// expected-error@-1 {{cannot convert value of type 'NoopWrapper<Test1, Test1.$Storage>' to expected argument type 'NoopWrapper<Test2, Test2.$Storage>'}}
632+
633+
@NoopWrapper
634+
struct Test3 { // expected-note {{'init(a:b:)' declared here}}
635+
var a: Int
636+
@typeWrapperIgnored var b: String
637+
}
638+
639+
// @typeWrapperIgnored suppresses `storageWrapper:` initializer
640+
_ = Test3(storageWrapper: NoopWrapper(for: Test3.self, storage: Test3.$Storage(a: 42)))
641+
// expected-error@-1 {{missing arguments for parameters 'a', 'b' in call}}
642+
// expected-error@-2 {{extra argument 'storageWrapper' in call}}
643+
}

0 commit comments

Comments
 (0)