Skip to content

Commit 76a5896

Browse files
authored
Merge pull request #27727 from theblixguy/fix/SR-11603
[PropertyWrappers] Fix lvalue computation in buildStorageReference
2 parents b3bd35b + d311879 commit 76a5896

File tree

3 files changed

+68
-4
lines changed

3 files changed

+68
-4
lines changed

lib/Sema/TypeCheckStorage.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -743,19 +743,40 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
743743
}
744744

745745
bool isMemberLValue = isLValue;
746+
auto propertyWrapperMutability =
747+
[&](Decl *decl) -> Optional<std::pair<bool, bool>> {
748+
if (accessor->isCoroutine())
749+
return None;
750+
auto var = dyn_cast<VarDecl>(decl);
751+
if (!var)
752+
return None;
753+
auto mut = var->getPropertyWrapperMutability();
754+
if (!mut)
755+
return None;
756+
return std::make_pair(mut->Getter == PropertyWrapperMutability::Mutating,
757+
mut->Setter == PropertyWrapperMutability::Mutating);
758+
};
746759

747-
// If we're acessing a property wrapper, determine if the
760+
// If we're accessing a property wrapper, determine if the
748761
// intermediate access requires an lvalue.
749-
if (underlyingVars.size() > 0) {
750-
isMemberLValue = underlyingVars[0]->isGetterMutating();
762+
if (auto mut = propertyWrapperMutability(accessor->getStorage())) {
763+
isMemberLValue = mut->first;
751764
if (isLValue)
752-
isMemberLValue |= underlyingVars[0]->isSetterMutating();
765+
isMemberLValue |= mut->second;
753766
}
754767

755768
bool isSelfLValue = storage->isGetterMutating();
756769
if (isMemberLValue)
757770
isSelfLValue |= storage->isSetterMutating();
758771

772+
// If we're accessing a property wrapper, determine if
773+
// the self requires an lvalue.
774+
if (auto mut = propertyWrapperMutability(storage)) {
775+
isSelfLValue = mut->first;
776+
if (isMemberLValue)
777+
isSelfLValue |= mut->second;
778+
}
779+
759780
Expr *selfDRE =
760781
buildSelfReference(selfDecl, selfAccessKind, isSelfLValue,
761782
ctx);

test/SILGen/property_wrappers.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,28 @@ extension UsesMyPublished {
519519
}
520520
}
521521

522+
// SR-11603 - crash due to incorrect lvalue computation
523+
@propertyWrapper
524+
struct StructWrapper<T> {
525+
var wrappedValue: T
526+
}
527+
528+
@propertyWrapper
529+
class ClassWrapper<T> {
530+
var wrappedValue: T
531+
init(wrappedValue: T) {
532+
self.wrappedValue = wrappedValue
533+
}
534+
}
535+
536+
struct SR_11603 {
537+
@StructWrapper @ClassWrapper var prop: Int
538+
539+
func foo() {
540+
prop = 1234
541+
}
542+
}
543+
522544
// CHECK-LABEL: sil_vtable ClassUsingWrapper {
523545
// CHECK-NEXT: #ClassUsingWrapper.x!getter.1: (ClassUsingWrapper) -> () -> Int : @$s17property_wrappers17ClassUsingWrapperC1xSivg // ClassUsingWrapper.x.getter
524546
// CHECK-NEXT: #ClassUsingWrapper.x!setter.1: (ClassUsingWrapper) -> (Int) -> () : @$s17property_wrappers17ClassUsingWrapperC1xSivs // ClassUsingWrapper.x.setter
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: not --crash %target-swift-frontend -primary-file %s -emit-silgen
2+
3+
// REQUIRES: asserts
4+
5+
@propertyWrapper
6+
struct MutatingGetNonMutatingSetWrapper<T> {
7+
private var fixed: T
8+
9+
var wrappedValue: T {
10+
mutating get { fixed }
11+
nonmutating set { }
12+
}
13+
14+
init(wrappedValue initialValue: T) {
15+
fixed = initialValue
16+
}
17+
}
18+
19+
struct Foo {
20+
@MutatingGetNonMutatingSetWrapper var text: String
21+
}

0 commit comments

Comments
 (0)