Skip to content

Commit eef11bc

Browse files
authored
Merge pull request #653 from swiftwasm/master
[pull] swiftwasm from master
2 parents 320d89c + 263cdd0 commit eef11bc

File tree

7 files changed

+136
-18
lines changed

7 files changed

+136
-18
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4806,6 +4806,13 @@ class AbstractStorageDecl : public ValueDecl {
48064806
/// Does this storage require a 'modify' accessor in its opaque-accessors set?
48074807
bool requiresOpaqueModifyCoroutine() const;
48084808

4809+
/// Does this storage have any explicit observers (willSet or didSet) attached
4810+
/// to it?
4811+
bool hasObservers() const {
4812+
return getParsedAccessor(AccessorKind::WillSet) ||
4813+
getParsedAccessor(AccessorKind::DidSet);
4814+
}
4815+
48094816
SourceRange getBracesRange() const {
48104817
if (auto info = Accessors.getPointer())
48114818
return info->getBracesRange();

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,8 +1691,7 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) {
16911691
// Make sure that the overriding property doesn't have storage.
16921692
if ((overrideASD->hasStorage() ||
16931693
overrideASD->getAttrs().hasAttribute<LazyAttr>()) &&
1694-
!(overrideASD->getParsedAccessor(AccessorKind::WillSet) ||
1695-
overrideASD->getParsedAccessor(AccessorKind::DidSet))) {
1694+
!overrideASD->hasObservers()) {
16961695
bool downgradeToWarning = false;
16971696
if (!ctx.isSwiftVersionAtLeast(5) &&
16981697
overrideASD->getAttrs().hasAttribute<LazyAttr>()) {

lib/Sema/TypeCheckStorage.cpp

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,8 +1556,7 @@ synthesizeSetterBody(AccessorDecl *setter, ASTContext &ctx) {
15561556
}
15571557

15581558
if (var->hasAttachedPropertyWrapper()) {
1559-
if (var->getParsedAccessor(AccessorKind::WillSet) ||
1560-
var->getParsedAccessor(AccessorKind::DidSet)) {
1559+
if (var->hasObservers()) {
15611560
return synthesizeObservedSetterBody(setter, TargetImpl::Wrapper, ctx);
15621561
}
15631562

@@ -1670,14 +1669,17 @@ synthesizeCoroutineAccessorBody(AccessorDecl *accessor, ASTContext &ctx) {
16701669

16711670
// If this is a variable with an attached property wrapper, then
16721671
// the accessors need to yield the wrappedValue or projectedValue.
1673-
if (auto var = dyn_cast<VarDecl>(storage)) {
1674-
if (var->hasAttachedPropertyWrapper()) {
1675-
target = TargetImpl::Wrapper;
1676-
}
1672+
if (accessor->getAccessorKind() == AccessorKind::Read ||
1673+
storageReadWriteImpl == ReadWriteImplKind::Modify) {
1674+
if (auto var = dyn_cast<VarDecl>(storage)) {
1675+
if (var->hasAttachedPropertyWrapper()) {
1676+
target = TargetImpl::Wrapper;
1677+
}
16771678

1678-
if (var->getOriginalWrappedProperty(
1679-
PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) {
1680-
target = TargetImpl::WrapperStorage;
1679+
if (var->getOriginalWrappedProperty(
1680+
PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) {
1681+
target = TargetImpl::WrapperStorage;
1682+
}
16811683
}
16821684
}
16831685

@@ -2134,8 +2136,7 @@ IsAccessorTransparentRequest::evaluate(Evaluator &evaluator,
21342136
// FIXME: This should be folded into the WriteImplKind below.
21352137
if (auto var = dyn_cast<VarDecl>(storage)) {
21362138
if (var->hasAttachedPropertyWrapper()) {
2137-
if (var->getParsedAccessor(AccessorKind::DidSet) ||
2138-
var->getParsedAccessor(AccessorKind::WillSet))
2139+
if (var->hasObservers())
21392140
return false;
21402141

21412142
break;
@@ -2683,11 +2684,17 @@ static void finishPropertyWrapperImplInfo(VarDecl *var,
26832684
}
26842685
}
26852686

2686-
if (wrapperSetterIsUsable)
2687+
if (!wrapperSetterIsUsable) {
2688+
info = StorageImplInfo::getImmutableComputed();
2689+
return;
2690+
}
2691+
2692+
if (var->hasObservers()) {
2693+
info = StorageImplInfo::getMutableComputed();
2694+
} else {
26872695
info = StorageImplInfo(ReadImplKind::Get, WriteImplKind::Set,
26882696
ReadWriteImplKind::Modify);
2689-
else
2690-
info = StorageImplInfo::getImmutableComputed();
2697+
}
26912698
}
26922699

26932700
static void finishNSManagedImplInfo(VarDecl *var,
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
// 1. Make sure the wrapped property setter calls the observers
4+
// 2. Make sure the synthesized _modify coroutine calls the wrapped property setter
5+
6+
@propertyWrapper
7+
struct Foo {
8+
private var _storage: [Int] = []
9+
10+
init(wrappedValue value: [Int]) {
11+
self._storage = value
12+
}
13+
14+
var wrappedValue: [Int] {
15+
get { _storage }
16+
set { _storage = newValue }
17+
}
18+
}
19+
20+
class Bar {
21+
@Foo var someArray = [1, 2, 3] {
22+
willSet {}
23+
didSet {}
24+
}
25+
}
26+
27+
// Bar.someArray.setter
28+
29+
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_observers3BarC9someArraySaySiGvs : $@convention(method) (@owned Array<Int>, @guaranteed Bar) -> () {
30+
// CHECK: bb0([[VALUE:%.*]] : @owned $Array<Int>, [[BAR:%.*]] : @guaranteed $Bar):
31+
32+
// CHECK: [[WILLSET:%.*]] = function_ref @$s26property_wrapper_observers3BarC9someArraySaySiGvw : $@convention(method) (@guaranteed Array<Int>, @guaranteed Bar) -> ()
33+
// CHECK-NEXT: [[RESULT_WS:%.*]] = apply [[WILLSET]](%{{[0-9]+}}, [[BAR]]) : $@convention(method) (@guaranteed Array<Int>, @guaranteed Bar) -> ()
34+
35+
// CHECK: [[WRAPPED_VALUE_SETTER:%.*]] = function_ref @$s26property_wrapper_observers3FooV12wrappedValueSaySiGvs : $@convention(method) (@owned Array<Int>, @inout Foo) -> ()
36+
// CHECK-NEXT: [[RESULT_WVS:%.*]] = apply [[WRAPPED_VALUE_SETTER]](%{{[0-9]+}}, %{{[0-9]+}}) : $@convention(method) (@owned Array<Int>, @inout Foo) -> ()
37+
38+
// CHECK: [[DIDSET:%.*]] = function_ref @$s26property_wrapper_observers3BarC9someArraySaySiGvW : $@convention(method) (@guaranteed Bar) -> ()
39+
// CHECK-NEXT: [[RESULT_DS:%.*]] = apply [[DIDSET]]([[BAR]]) : $@convention(method) (@guaranteed Bar) -> ()
40+
// CHECK: }
41+
42+
// Bar.someArray.modify
43+
44+
// CHECK-LABEL: sil hidden [ossa] @$s26property_wrapper_observers3BarC9someArraySaySiGvM : $@yield_once @convention(method) (@guaranteed Bar) -> @yields @inout Array<Int> {
45+
// CHECK: bb0([[BAR:%.*]] : @guaranteed $Bar):
46+
// CHECK-NEXT: debug_value [[BAR]] : $Bar, let, name "self", argno 1
47+
// CHECK-NEXT: [[ALLOC_STACK:%.*]] = alloc_stack $Array<Int>
48+
// CHECK-NEXT: // function_ref Bar.someArray.getter
49+
// CHECK-NEXT: [[GETTER:%.*]] = function_ref @$s26property_wrapper_observers3BarC9someArraySaySiGvg : $@convention(method) (@guaranteed Bar) -> @owned Array<Int>
50+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[GETTER]]([[BAR]]) : $@convention(method) (@guaranteed Bar) -> @owned Array<Int>
51+
// CHECK-NEXT: store [[RESULT]] to [init] [[ALLOC_STACK]] : $*Array<Int>
52+
// CHECK-NEXT: yield [[ALLOC_STACK]] : $*Array<Int>, resume bb1, unwind bb2
53+
54+
// CHECK: bb1:
55+
// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[ALLOC_STACK]] : $*Array<Int>
56+
// CHECK-NEXT: // function_ref Bar.someArray.setter
57+
// CHECK-NEXT: [[SETTER:%.*]] = function_ref @$s26property_wrapper_observers3BarC9someArraySaySiGvs : $@convention(method) (@owned Array<Int>, @guaranteed Bar) -> ()
58+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[SETTER]]([[VALUE]], [[BAR]]) : $@convention(method) (@owned Array<Int>, @guaranteed Bar) -> ()
59+
// CHECK-NEXT: dealloc_stack [[ALLOC_STACK]] : $*Array<Int>
60+
// CHECK-NEXT: [[TUPLE:%.*]] = tuple ()
61+
// CHECK-NEXT: return [[TUPLE]] : $()
62+
63+
// CHECK: bb2:
64+
// CHECK-NEXT: [[NEWVALUE:%.*]] = load [copy] [[ALLOC_STACK]] : $*Array<Int>
65+
// CHECK-NEXT: // function_ref Bar.someArray.setter
66+
// CHECK-NEXT: [[SETTER:%.*]] = function_ref @$s26property_wrapper_observers3BarC9someArraySaySiGvs : $@convention(method) (@owned Array<Int>, @guaranteed Bar) -> ()
67+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[SETTER]]([[NEWVALUE]], [[BAR]]) : $@convention(method) (@owned Array<Int>, @guaranteed Bar) -> ()
68+
// CHECK-NEXT: destroy_addr [[ALLOC_STACK]] : $*Array<Int>
69+
// CHECK-NEXT: dealloc_stack [[ALLOC_STACK]] : $*Array<Int>
70+
// CHECK-NEXT: unwind
71+
// CHECK-END: }
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-run-simple-swift
2+
3+
// REQUIRES: executable_test
4+
5+
@propertyWrapper
6+
struct Foo {
7+
private var _storage: [Int] = []
8+
9+
init(wrappedValue value: [Int]) {
10+
self._storage = value
11+
}
12+
13+
var wrappedValue: [Int] {
14+
get { _storage }
15+
set { _storage = newValue }
16+
}
17+
}
18+
19+
class Bar {
20+
@Foo var someArray = [1, 2, 3] {
21+
willSet {
22+
print(newValue)
23+
}
24+
25+
didSet {
26+
print(oldValue)
27+
}
28+
}
29+
}
30+
31+
let bar = Bar()
32+
// CHECK: [4, 2, 3]
33+
// CHECK: [1, 2, 3]
34+
bar.someArray[0] = 4

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,8 +1190,7 @@ static bool inferIsSettableSyntactically(const AbstractStorageDecl *D) {
11901190
}
11911191
if (D->hasParsedAccessors()) {
11921192
return D->getParsedAccessor(AccessorKind::Set) != nullptr ||
1193-
D->getParsedAccessor(AccessorKind::WillSet) != nullptr ||
1194-
D->getParsedAccessor(AccessorKind::DidSet) != nullptr;
1193+
D->hasObservers();
11951194
} else {
11961195
return true;
11971196
}

validation-test/SILOptimizer/large_string_array.swift.gyb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
1212
// REQUIRES: long_test
13+
// REQUIRES: CPU=arm64 || CPU=x86_64
1314

1415
// Check if the optimizer can optimize the whole array into a statically
1516
// initialized global

0 commit comments

Comments
 (0)