Skip to content

Commit 534d0fb

Browse files
committed
[AST/Sema] TypeWrapper: Implement synthesis of init(storageWrapper:) initializer
1 parent 9df15d4 commit 534d0fb

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
@@ -1630,7 +1630,32 @@ void swift::addNonIsolatedToSynthesized(
16301630
static std::pair<BraceStmt *, /*isTypeChecked=*/bool>
16311631
synthesizeTypeWrappedTypeStorageWrapperInitializerBody(
16321632
AbstractFunctionDecl *decl, void *) {
1633-
return {nullptr, /*isTypeChecked=*/false};
1633+
auto &ctx = decl->getASTContext();
1634+
auto *ctor = cast<ConstructorDecl>(decl);
1635+
auto *wrappedType = ctor->getDeclContext()->getSelfNominalTypeDecl();
1636+
auto *storageProperty = wrappedType->getTypeWrapperProperty();
1637+
1638+
// self.$storage = storageWrapper
1639+
SmallVector<ASTNode, 2> body;
1640+
{
1641+
auto *storageVarRef = UnresolvedDotExpr::createImplicit(
1642+
ctx,
1643+
new (ctx) DeclRefExpr({ctor->getImplicitSelfDecl()},
1644+
/*Loc=*/DeclNameLoc(), /*Implicit=*/true),
1645+
storageProperty->getName());
1646+
1647+
auto *paramRef = new (ctx)
1648+
DeclRefExpr(ctor->getParameters()->get(0), /*Loc=*/DeclNameLoc(),
1649+
/*Implicit=*/true);
1650+
1651+
body.push_back(new (ctx) AssignExpr(storageVarRef, /*EqualLoc=*/SourceLoc(),
1652+
paramRef,
1653+
/*Implicit=*/true));
1654+
}
1655+
1656+
return {BraceStmt::create(ctx, /*lbloc=*/ctor->getLoc(), body,
1657+
/*rbloc=*/ctor->getLoc(), /*implicit=*/true),
1658+
/*isTypeChecked=*/false};
16341659
}
16351660

16361661
ConstructorDecl *SynthesizeTypeWrappedTypeStorageWrapperInitializer::evaluate(

test/Interpreter/type_wrappers.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,3 +625,23 @@ do {
625625
// CHECK-NEXT: in read-only getter storage: \$Storage.b, property: \TypeWithLetProperties<Optional<Array<Int>>>.b
626626
// CHECK-NEXT: 0
627627
}
628+
629+
do {
630+
@Wrapper
631+
struct Test<T> {
632+
var a: T
633+
var b: Int
634+
}
635+
636+
let wrapper = Wrapper(for: Test<[Float?]>.self, storage: Test<[Float?]>.$Storage(a: [1.0], b: 42))
637+
// CHECK: Wrapper.init(for: Test<Array<Optional<Float>>>, storage: $Storage(a: [Optional(1.0)], b: 42))
638+
639+
var test = Test(storageWrapper: wrapper)
640+
641+
print(test.a)
642+
print(test.b)
643+
// CHECK-NEXT: in getter storage: \$Storage.a, property: \Test<Array<Optional<Float>>>.<{{.*}} (Array<Optional<Float>>)>
644+
// CHECK-NEXT: [Optional(1.0)]
645+
// CHECK-NEXT: in getter storage: \$Storage.b, property: \Test<Array<Optional<Float>>>.b
646+
// CHECK-NEXT: 42
647+
}

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)