mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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.
This commit is contained in:
@@ -188,6 +188,28 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
|
|||||||
arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
|
arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void maybeAddTypeWrapperDefaultArg(ParamDecl *arg, VarDecl *var,
|
||||||
|
ASTContext &ctx) {
|
||||||
|
assert(var->isAccessedViaTypeWrapper());
|
||||||
|
|
||||||
|
if (!var->getParentPattern()->getSingleVar())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto *PBD = var->getParentPatternBinding();
|
||||||
|
|
||||||
|
auto *initExpr = PBD->getInit(/*index=*/0);
|
||||||
|
if (!initExpr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Type wrapper variables are never initialized directly,
|
||||||
|
// initialization expression (if any) becomes an default
|
||||||
|
// argument of the initializer synthesized by the type wrapper.
|
||||||
|
PBD->setInitializerSubsumed(/*index=*/0);
|
||||||
|
|
||||||
|
arg->setDefaultExpr(initExpr, /*isTypeChecked=*/false);
|
||||||
|
arg->setDefaultArgumentKind(DefaultArgumentKind::Normal);
|
||||||
|
}
|
||||||
|
|
||||||
/// Describes the kind of implicit constructor that will be
|
/// Describes the kind of implicit constructor that will be
|
||||||
/// generated.
|
/// generated.
|
||||||
enum class ImplicitConstructorKind {
|
enum class ImplicitConstructorKind {
|
||||||
@@ -339,6 +361,8 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
|
|||||||
arg->setInterfaceType(var->getValueInterfaceType());
|
arg->setInterfaceType(var->getValueInterfaceType());
|
||||||
arg->setImplicit();
|
arg->setImplicit();
|
||||||
|
|
||||||
|
maybeAddTypeWrapperDefaultArg(arg, var, ctx);
|
||||||
|
|
||||||
params.push_back(arg);
|
params.push_back(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,3 +24,9 @@ public class Person<T> {
|
|||||||
public var name: String
|
public var name: String
|
||||||
public var projects: [T]
|
public var projects: [T]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Wrapper
|
||||||
|
public struct PersonWithDefaults {
|
||||||
|
public var name: String = "<no name>"
|
||||||
|
public var age: Int = 99
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,3 +37,48 @@ print(p.name)
|
|||||||
print(p.projects)
|
print(p.projects)
|
||||||
// CHECK: in getter
|
// CHECK: in getter
|
||||||
// CHECK-NEXT: ["A", "B", "C", "D"]
|
// CHECK-NEXT: ["A", "B", "C", "D"]
|
||||||
|
|
||||||
|
var pDefaults = PersonWithDefaults()
|
||||||
|
// CHECK: Wrapper.init($Storage(name: "<no name>", age: 99))
|
||||||
|
|
||||||
|
print(pDefaults.name)
|
||||||
|
// CHECK: in getter
|
||||||
|
// CHECK: <no name>
|
||||||
|
|
||||||
|
print(pDefaults.age)
|
||||||
|
// CHECK: in getter
|
||||||
|
// CHECK: 99
|
||||||
|
|
||||||
|
pDefaults.name = "Actual Name"
|
||||||
|
// CHECK-NEXT: in setter => Actual Name
|
||||||
|
|
||||||
|
pDefaults.age = 0
|
||||||
|
// CHECK-NEXT: in setter => 0
|
||||||
|
|
||||||
|
print(pDefaults.name)
|
||||||
|
// CHECK: in getter
|
||||||
|
// CHECK: Actual Name
|
||||||
|
|
||||||
|
print(pDefaults.age)
|
||||||
|
// CHECK: in getter
|
||||||
|
// CHECK: 0
|
||||||
|
|
||||||
|
let pDefaultsAge = PersonWithDefaults(name: "Actual Name")
|
||||||
|
|
||||||
|
print(pDefaultsAge.name)
|
||||||
|
// CHECK: in getter
|
||||||
|
// CHECK: Actual Name
|
||||||
|
|
||||||
|
print(pDefaultsAge.age)
|
||||||
|
// CHECK: in getter
|
||||||
|
// CHECK: 99
|
||||||
|
|
||||||
|
let pDefaultsName = PersonWithDefaults(age: 31337)
|
||||||
|
|
||||||
|
print(pDefaultsName.name)
|
||||||
|
// CHECK: in getter
|
||||||
|
// CHECK: <no name>
|
||||||
|
|
||||||
|
print(pDefaultsName.age)
|
||||||
|
// CHECK: in getter
|
||||||
|
// CHECK: 31337
|
||||||
|
|||||||
@@ -147,3 +147,18 @@ func testLocalWithNestedWrapper() {
|
|||||||
_ = t.test // Ok
|
_ = t.test // Ok
|
||||||
_ = t.computed // Ok
|
_ = t.computed // Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testTypeWrapperWithDefaults() {
|
||||||
|
@NoopWrapper
|
||||||
|
struct A {
|
||||||
|
var question: String = "Ultimate Question"
|
||||||
|
var answer: Int = 42
|
||||||
|
}
|
||||||
|
|
||||||
|
let a = A()
|
||||||
|
_ = a.question
|
||||||
|
_ = a.answer
|
||||||
|
|
||||||
|
_ = A(question: "")
|
||||||
|
_ = A(answer: 0)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user