Skip to content

Commit 39b1566

Browse files
committed
[Sema] TypeWrappers: convert variable init expr into initializer default
All of the stored properties are wrapped which means that their initializers are subsummed and moved to the synthesized `init` as default arguments.
1 parent a3b5430 commit 39b1566

File tree

4 files changed

+90
-0
lines changed

4 files changed

+90
-0
lines changed

lib/Sema/CodeSynthesis.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,28 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
188188
arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
189189
}
190190

191+
static void maybeAddTypeWrapperDefaultArg(ParamDecl *arg, VarDecl *var,
192+
ASTContext &ctx) {
193+
assert(var->isAccessedViaTypeWrapper());
194+
195+
if (!var->getParentPattern()->getSingleVar())
196+
return;
197+
198+
auto *PBD = var->getParentPatternBinding();
199+
200+
auto *initExpr = PBD->getInit(/*index=*/0);
201+
if (!initExpr)
202+
return;
203+
204+
// Type wrapper variables are never initialized directly,
205+
// initialization expression (if any) becomes an default
206+
// argument of the initializer synthesized by the type wrapper.
207+
PBD->setInitializerSubsumed(/*index=*/0);
208+
209+
arg->setDefaultExpr(initExpr, /*isTypeChecked=*/false);
210+
arg->setDefaultArgumentKind(DefaultArgumentKind::Normal);
211+
}
212+
191213
/// Describes the kind of implicit constructor that will be
192214
/// generated.
193215
enum class ImplicitConstructorKind {
@@ -339,6 +361,8 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
339361
arg->setInterfaceType(var->getValueInterfaceType());
340362
arg->setImplicit();
341363

364+
maybeAddTypeWrapperDefaultArg(arg, var, ctx);
365+
342366
params.push_back(arg);
343367
}
344368
}

test/Interpreter/Inputs/type_wrapper_defs.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,9 @@ public class Person<T> {
2424
public var name: String
2525
public var projects: [T]
2626
}
27+
28+
@Wrapper
29+
public struct PersonWithDefaults {
30+
public var name: String = "<no name>"
31+
public var age: Int = 99
32+
}

test/Interpreter/type_wrappers.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,48 @@ print(p.name)
3737
print(p.projects)
3838
// CHECK: in getter
3939
// CHECK-NEXT: ["A", "B", "C", "D"]
40+
41+
var pDefaults = PersonWithDefaults()
42+
// CHECK: Wrapper.init($Storage(name: "<no name>", age: 99))
43+
44+
print(pDefaults.name)
45+
// CHECK: in getter
46+
// CHECK: <no name>
47+
48+
print(pDefaults.age)
49+
// CHECK: in getter
50+
// CHECK: 99
51+
52+
pDefaults.name = "Actual Name"
53+
// CHECK-NEXT: in setter => Actual Name
54+
55+
pDefaults.age = 0
56+
// CHECK-NEXT: in setter => 0
57+
58+
print(pDefaults.name)
59+
// CHECK: in getter
60+
// CHECK: Actual Name
61+
62+
print(pDefaults.age)
63+
// CHECK: in getter
64+
// CHECK: 0
65+
66+
let pDefaultsAge = PersonWithDefaults(name: "Actual Name")
67+
68+
print(pDefaultsAge.name)
69+
// CHECK: in getter
70+
// CHECK: Actual Name
71+
72+
print(pDefaultsAge.age)
73+
// CHECK: in getter
74+
// CHECK: 99
75+
76+
let pDefaultsName = PersonWithDefaults(age: 31337)
77+
78+
print(pDefaultsName.name)
79+
// CHECK: in getter
80+
// CHECK: <no name>
81+
82+
print(pDefaultsName.age)
83+
// CHECK: in getter
84+
// CHECK: 31337

test/type/type_wrapper.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,18 @@ func testLocalWithNestedWrapper() {
147147
_ = t.test // Ok
148148
_ = t.computed // Ok
149149
}
150+
151+
func testTypeWrapperWithDefaults() {
152+
@NoopWrapper
153+
struct A {
154+
var question: String = "Ultimate Question"
155+
var answer: Int = 42
156+
}
157+
158+
let a = A()
159+
_ = a.question
160+
_ = a.answer
161+
162+
_ = A(question: "")
163+
_ = A(answer: 0)
164+
}

0 commit comments

Comments
 (0)