Skip to content

Commit 2a2b600

Browse files
committed
[PropertyWrappers] Refactor property wrapper mutability check into local function and use it to check if self requires an lvalue
1 parent 4831608 commit 2a2b600

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

lib/Sema/TypeCheckStorage.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -735,23 +735,40 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
735735
}
736736

737737
bool isMemberLValue = isLValue;
738+
auto propertyWrapperMutability =
739+
[&](Decl *decl) -> Optional<std::pair<bool, bool>> {
740+
if (accessor->isCoroutine())
741+
return None;
742+
auto var = dyn_cast<VarDecl>(decl);
743+
if (!var)
744+
return None;
745+
auto mut = var->getPropertyWrapperMutability();
746+
if (!mut)
747+
return None;
748+
return std::make_pair(mut->Getter == PropertyWrapperMutability::Mutating,
749+
mut->Setter == PropertyWrapperMutability::Mutating);
750+
};
738751

739-
// If we're acessing a property wrapper, determine if the
752+
// If we're accessing a property wrapper, determine if the
740753
// intermediate access requires an lvalue.
741-
if (!accessor->isCoroutine()) {
742-
if (auto var = dyn_cast<VarDecl>(accessor->getStorage())) {
743-
if (auto mut = var->getPropertyWrapperMutability()) {
744-
isMemberLValue = mut->Getter == PropertyWrapperMutability::Mutating;
745-
if (isLValue)
746-
isMemberLValue |= mut->Setter == PropertyWrapperMutability::Mutating;
747-
}
748-
}
754+
if (auto mut = propertyWrapperMutability(accessor->getStorage())) {
755+
isMemberLValue = mut->first;
756+
if (isLValue)
757+
isMemberLValue |= mut->second;
749758
}
750759

751760
bool isSelfLValue = storage->isGetterMutating();
752761
if (isMemberLValue)
753762
isSelfLValue |= storage->isSetterMutating();
754763

764+
// If we're accessing a property wrapper, determine if
765+
// the self requires an lvalue.
766+
if (auto mut = propertyWrapperMutability(storage)) {
767+
isSelfLValue = mut->first;
768+
if (isMemberLValue)
769+
isSelfLValue |= mut->second;
770+
}
771+
755772
Expr *selfDRE =
756773
buildSelfReference(selfDecl, selfAccessKind, isSelfLValue,
757774
ctx);

test/SILGen/property_wrappers.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,14 +534,32 @@ class ClassWrapper<T> {
534534
}
535535

536536

537-
struct SR_11603 {
537+
struct SR_11603_1 {
538538
@StructWrapper @ClassWrapper var prop: Int
539539

540540
func foo() {
541541
prop = 1234
542542
}
543543
}
544544

545+
@propertyWrapper
546+
struct MutatingGetNonMutatingSetWrapper<T> {
547+
private var fixed: T
548+
549+
var wrappedValue: T {
550+
mutating get { fixed }
551+
nonmutating set { }
552+
}
553+
554+
init(wrappedValue initialValue: T) {
555+
fixed = initialValue
556+
}
557+
}
558+
559+
struct SR_11603_2 {
560+
@MutatingGetNonMutatingSetWrapper var text: String = ""
561+
}
562+
545563
// CHECK-LABEL: sil_vtable ClassUsingWrapper {
546564
// CHECK-NEXT: #ClassUsingWrapper.x!getter.1: (ClassUsingWrapper) -> () -> Int : @$s17property_wrappers17ClassUsingWrapperC1xSivg // ClassUsingWrapper.x.getter
547565
// CHECK-NEXT: #ClassUsingWrapper.x!setter.1: (ClassUsingWrapper) -> (Int) -> () : @$s17property_wrappers17ClassUsingWrapperC1xSivs // ClassUsingWrapper.x.setter

0 commit comments

Comments
 (0)