Skip to content

Commit 7809d9c

Browse files
committed
[SE-0258] Determine mutating-ness of accessors based on the storage declaration.
With property wrappers, the mutating-ness of the accessors can be determined non-locally by the property wrapper type itself. Ensure that the storage declaration is consulted to determine the mutating-ness of accessors, eliminating a crash involving willSet/didSet and property wrappers. Fixes rdar://problem/51669930.
1 parent 81f4b90 commit 7809d9c

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,6 +1863,24 @@ static void validateSelfAccessKind(TypeChecker &TC, FuncDecl *FD) {
18631863
FD->setSelfAccessKind(SelfAccessKind::NonMutating);
18641864
else if (FD->getAttrs().hasAttribute<ConsumingAttr>())
18651865
FD->setSelfAccessKind(SelfAccessKind::__Consuming);
1866+
else if (auto accessor = dyn_cast<AccessorDecl>(FD)) {
1867+
if (accessor->getAccessorKind() == AccessorKind::Get ||
1868+
accessor->getAccessorKind() == AccessorKind::Set ||
1869+
accessor->getAccessorKind() == AccessorKind::DidSet ||
1870+
accessor->getAccessorKind() == AccessorKind::WillSet) {
1871+
auto storage = accessor->getStorage();
1872+
TC.validateDecl(storage);
1873+
if (accessor->getAccessorKind() == AccessorKind::Get) {
1874+
FD->setSelfAccessKind(storage->isGetterMutating()
1875+
? SelfAccessKind::Mutating
1876+
: SelfAccessKind::NonMutating);
1877+
} else {
1878+
FD->setSelfAccessKind(storage->isSetterMutating()
1879+
? SelfAccessKind::Mutating
1880+
: SelfAccessKind::NonMutating);
1881+
}
1882+
}
1883+
}
18661884

18671885
if (FD->isMutating()) {
18681886
if (!FD->isInstanceMember() ||

test/SILGen/property_wrappers.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,55 @@ func testComposition() {
346346
_ = CompositionMembers(p1: nil)
347347
}
348348

349+
// Observers with non-default mutatingness.
350+
@propertyWrapper
351+
struct NonMutatingSet<T> {
352+
private var fixed: T
353+
354+
var wrappedValue: T {
355+
get { fixed }
356+
nonmutating set { }
357+
}
358+
359+
init(initialValue: T) {
360+
fixed = initialValue
361+
}
362+
}
363+
364+
@propertyWrapper
365+
struct MutatingGet<T> {
366+
private var fixed: T
367+
368+
var wrappedValue: T {
369+
mutating get { fixed }
370+
set { }
371+
}
372+
373+
init(initialValue: T) {
374+
fixed = initialValue
375+
}
376+
}
377+
378+
struct ObservingTest {
379+
// ObservingTest.text.setter
380+
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers13ObservingTestV4textSSvs : $@convention(method) (@owned String, @guaranteed ObservingTest) -> ()
381+
// CHECK: function_ref @$s17property_wrappers14NonMutatingSetV12wrappedValuexvg
382+
@NonMutatingSet var text: String = "" {
383+
didSet { }
384+
}
385+
386+
@NonMutatingSet var integer: Int = 17 {
387+
willSet { }
388+
}
389+
390+
@MutatingGet var text2: String = "" {
391+
didSet { }
392+
}
393+
394+
@MutatingGet var integer2: Int = 17 {
395+
willSet { }
396+
}
397+
}
349398

350399
// CHECK-LABEL: sil_vtable ClassUsingWrapper {
351400
// CHECK: #ClassUsingWrapper.x!getter.1: (ClassUsingWrapper) -> () -> Int : @$s17property_wrappers17ClassUsingWrapperC1xSivg // ClassUsingWrapper.x.getter

0 commit comments

Comments
 (0)