Skip to content

Commit 32be6f5

Browse files
committed
[Property wrappers] Handle composition and autoclosures.
Fixes the test case from rdar://problem/58986940.
1 parent af1abea commit 32be6f5

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

lib/AST/Decl.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6343,6 +6343,8 @@ Expr *swift::findOriginalPropertyWrapperInitialValue(VarDecl *var,
63436343
return { false, E };
63446344

63456345
if (auto call = dyn_cast<CallExpr>(E)) {
6346+
ASTContext &ctx = innermostNominal->getASTContext();
6347+
63466348
// We're looking for an implicit call.
63476349
if (!call->isImplicit())
63486350
return { true, E };
@@ -6352,9 +6354,19 @@ Expr *swift::findOriginalPropertyWrapperInitialValue(VarDecl *var,
63526354
// property.
63536355
if (auto tuple = dyn_cast<TupleExpr>(call->getArg())) {
63546356
if (tuple->getNumElements() > 0) {
6355-
auto elem = tuple->getElement(0);
6356-
if (elem->isImplicit() && isa<CallExpr>(elem)) {
6357-
return { true, E };
6357+
for (unsigned i : range(tuple->getNumElements())) {
6358+
if (tuple->getElementName(i) == ctx.Id_wrappedValue ||
6359+
tuple->getElementName(i) == ctx.Id_initialValue) {
6360+
auto elem = tuple->getElement(i)->getSemanticsProvidingExpr();
6361+
6362+
// Look through autoclosures.
6363+
if (auto autoclosure = dyn_cast<AutoClosureExpr>(elem))
6364+
elem = autoclosure->getSingleExpressionBody();
6365+
6366+
if (elem->isImplicit() && isa<CallExpr>(elem)) {
6367+
return { true, E };
6368+
}
6369+
}
63586370
}
63596371
}
63606372
}
@@ -6367,7 +6379,6 @@ Expr *swift::findOriginalPropertyWrapperInitialValue(VarDecl *var,
63676379

63686380
// Find the implicit initialValue/wrappedValue argument.
63696381
if (auto tuple = dyn_cast<TupleExpr>(call->getArg())) {
6370-
ASTContext &ctx = innermostNominal->getASTContext();
63716382
for (unsigned i : range(tuple->getNumElements())) {
63726383
if (tuple->getElementName(i) == ctx.Id_wrappedValue ||
63736384
tuple->getElementName(i) == ctx.Id_initialValue) {

test/SILGen/property_wrappers.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,38 @@ struct HasStaticWrapper {
642642
}
643643
}
644644

645+
@propertyWrapper
646+
struct ObservedObject<ObjectType : AnyObject > {
647+
var wrappedValue: ObjectType
648+
649+
init(defaulted: Int = 17, wrappedValue: ObjectType) {
650+
self.wrappedValue = wrappedValue
651+
}
652+
}
653+
654+
// rdar://problem/58986940 - composition of wrappers with autoclosure
655+
@propertyWrapper
656+
struct Once<Value> {
657+
enum Storage {
658+
case initialValue(() -> Value)
659+
case value(Value)
660+
}
661+
662+
var storage: Storage
663+
664+
init(defaulted: Int = 0, wrappedValue value: @escaping @autoclosure () -> Value) {
665+
storage = .initialValue(value)
666+
}
667+
668+
var wrappedValue: Value { fatalError() }
669+
}
670+
671+
class Model {}
672+
673+
struct TestAutoclosureComposition {
674+
@Once @ObservedObject var model = Model()
675+
}
676+
645677
// CHECK-LABEL: sil_vtable ClassUsingWrapper {
646678
// CHECK-NEXT: #ClassUsingWrapper.x!getter: (ClassUsingWrapper) -> () -> Int : @$s17property_wrappers17ClassUsingWrapperC1xSivg // ClassUsingWrapper.x.getter
647679
// CHECK-NEXT: #ClassUsingWrapper.x!setter: (ClassUsingWrapper) -> (Int) -> () : @$s17property_wrappers17ClassUsingWrapperC1xSivs // ClassUsingWrapper.x.setter

0 commit comments

Comments
 (0)