Skip to content

Commit f584bc4

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-next
2 parents 8be3f22 + 4c85dd6 commit f584bc4

File tree

4 files changed

+108
-9
lines changed

4 files changed

+108
-9
lines changed

lib/Sema/TypeCheckStorage.cpp

+29-8
Original file line numberDiff line numberDiff line change
@@ -743,8 +743,6 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
743743
bool isMemberLValue = isLValue;
744744
auto propertyWrapperMutability =
745745
[&](Decl *decl) -> Optional<std::pair<bool, bool>> {
746-
if (accessor->isCoroutine())
747-
return None;
748746
auto var = dyn_cast<VarDecl>(decl);
749747
if (!var)
750748
return None;
@@ -1527,7 +1525,7 @@ synthesizeSetterBody(AccessorDecl *setter, ASTContext &ctx) {
15271525
return synthesizePropertyWrapperSetterBody(setter, ctx);
15281526
}
15291527

1530-
// Synthesize a getter for the storage wrapper property of a property
1528+
// Synthesize a setter for the storage wrapper property of a property
15311529
// with an attached wrapper.
15321530
if (auto original = var->getOriginalWrappedProperty(
15331531
PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) {
@@ -1572,6 +1570,19 @@ synthesizeCoroutineAccessorBody(AccessorDecl *accessor, ASTContext &ctx) {
15721570
? TargetImpl::Ordinary
15731571
: TargetImpl::Implementation);
15741572

1573+
// If this is a variable with an attached property wrapper, then
1574+
// the accessors need to yield the wrappedValue or projectedValue.
1575+
if (auto var = dyn_cast<VarDecl>(storage)) {
1576+
if (var->hasAttachedPropertyWrapper()) {
1577+
target = TargetImpl::Wrapper;
1578+
}
1579+
1580+
if (var->getOriginalWrappedProperty(
1581+
PropertyWrapperSynthesizedPropertyKind::StorageWrapper)) {
1582+
target = TargetImpl::WrapperStorage;
1583+
}
1584+
}
1585+
15751586
SourceLoc loc = storage->getLoc();
15761587
SmallVector<ASTNode, 1> body;
15771588

@@ -1602,8 +1613,11 @@ synthesizeReadCoroutineBody(AccessorDecl *read, ASTContext &ctx) {
16021613
static std::pair<BraceStmt *, bool>
16031614
synthesizeModifyCoroutineBody(AccessorDecl *modify, ASTContext &ctx) {
16041615
#ifndef NDEBUG
1605-
auto impl = modify->getStorage()->getReadWriteImpl();
1606-
assert(impl != ReadWriteImplKind::Modify &&
1616+
auto storage = modify->getStorage();
1617+
auto impl = storage->getReadWriteImpl();
1618+
auto hasWrapper = isa<VarDecl>(storage) &&
1619+
cast<VarDecl>(storage)->hasAttachedPropertyWrapper();
1620+
assert((hasWrapper || impl != ReadWriteImplKind::Modify) &&
16071621
impl != ReadWriteImplKind::Immutable);
16081622
#endif
16091623
return synthesizeCoroutineAccessorBody(modify, ctx);
@@ -2249,9 +2263,15 @@ PropertyWrapperMutabilityRequest::evaluate(Evaluator &,
22492263
isProjectedValue = true;
22502264
}
22512265

2252-
if (var->getParsedAccessor(AccessorKind::Get))
2266+
// Make sure we don't ignore .swiftinterface files, because those will
2267+
// have the accessors printed
2268+
auto varSourceFile = var->getDeclContext()->getParentSourceFile();
2269+
auto isVarNotInInterfaceFile =
2270+
varSourceFile && varSourceFile->Kind != SourceFileKind::Interface;
2271+
2272+
if (var->getParsedAccessor(AccessorKind::Get) && isVarNotInInterfaceFile)
22532273
return None;
2254-
if (var->getParsedAccessor(AccessorKind::Set))
2274+
if (var->getParsedAccessor(AccessorKind::Set) && isVarNotInInterfaceFile)
22552275
return None;
22562276

22572277
// Figure out which member we're looking through.
@@ -2548,7 +2568,8 @@ static void finishPropertyWrapperImplInfo(VarDecl *var,
25482568
}
25492569

25502570
if (wrapperSetterIsUsable)
2551-
info = StorageImplInfo::getMutableComputed();
2571+
info = StorageImplInfo(ReadImplKind::Get, WriteImplKind::Set,
2572+
ReadWriteImplKind::Modify);
25522573
else
25532574
info = StorageImplInfo::getImmutableComputed();
25542575
}

test/ModuleInterface/property_wrappers.swift

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public struct HasWrappers {
4444
// CHECK: @TestResilient.Wrapper public var x: {{(Swift.)?}}Int {
4545
// CHECK-NEXT: get
4646
// CHECK-NEXT: set
47+
// CHECK-NEXT: _modify
4748
// CHECK-NEXT: }
4849
@Wrapper public var x: Int
4950

@@ -59,6 +60,7 @@ public struct HasWrappers {
5960
// CHECK: @TestResilient.WrapperWithInitialValue @_projectedValueProperty($z) public var z: Swift.Bool {
6061
// CHECK-NEXT: get
6162
// CHECK-NEXT: set
63+
// CHECK-NEXT: _modify
6264
// CHECK-NEXT: }
6365
@WrapperWithInitialValue(alternate: false) public var z
6466
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
@propertyWrapper
4+
struct TestWrapper<ValueType> {
5+
var wrappedValue: ValueType
6+
}
7+
8+
struct State {
9+
@TestWrapper var values: [String] = []
10+
}
11+
12+
protocol StateProtocol {
13+
@_borrowed var someValues: [String] { get set }
14+
}
15+
16+
struct State1: StateProtocol {
17+
@TestWrapper var someValues: [String] = []
18+
}
19+
20+
var state = State()
21+
state.values = Array(repeating: "", count: 20000)
22+
state.values[1000] = "foo"
23+
24+
let state1 = State1()
25+
_ = state1.someValues
26+
27+
// >> Check that the subscript assignment uses the _modify coroutine
28+
29+
// CHECK: {{%.*}} = begin_access [modify] [dynamic] {{%.*}} : $*State
30+
// CHECK: [[REF_VALUES_MODIFY:%.*]] = function_ref @$s26property_wrapper_coroutine5StateV6valuesSaySSGvM : $@yield_once @convention(method) (@inout State) -> @yields @inout Array<String>
31+
// CHECK: ([[RES1:%.*]], {{%.*}}) = begin_apply [[REF_VALUES_MODIFY]]({{%.*}}) : $@yield_once @convention(method) (@inout State) -> @yields @inout Array<String>
32+
// CHECK: [[REF_ARRAY_SUBSCRIPT:%.*]] = function_ref @$sSayxSiciM : $@yield_once @convention(method) <τ_0_0> (Int, @inout Array<τ_0_0>) -> @yields @inout τ_0_0
33+
// CHECK: ({{%.*}}, {{%.*}}) = begin_apply [[REF_ARRAY_SUBSCRIPT]]<String>({{%.*}}, [[RES1]]) : $@yield_once @convention(method) <τ_0_0> (Int, @inout Array<τ_0_0>) -> @yields @inout τ_0_0
34+
35+
// >> Check that the _modify coroutine is synthesized properly
36+
37+
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s26property_wrapper_coroutine5StateV6valuesSaySSGvM : $@yield_once @convention(method) (@inout State) -> @yields @inout Array<String> {
38+
// CHECK: bb0([[STATE:%.*]] : $*State):
39+
// CHECK: debug_value_addr [[STATE]] : $*State, var, name "self", argno {{.*}}
40+
// CHECK: [[BEGIN_ACCESS:%.*]] = begin_access [modify] [unknown] [[STATE]] : $*State
41+
// CHECK: [[BACKING_ADDR:%.*]] = struct_element_addr [[BEGIN_ACCESS]] : $*State, #State._values
42+
// CHECK: [[VALUE_ADDR:%.*]] = struct_element_addr [[BACKING_ADDR]] : $*TestWrapper<Array<String>>, #TestWrapper.wrappedValue
43+
// CHECK: yield [[VALUE_ADDR]] : $*Array<String>, resume bb1, unwind bb2
44+
//
45+
// CHECK: bb1:
46+
// CHECK: end_access [[BEGIN_ACCESS]] : $*State
47+
// CHECK: [[RETURN:%.*]] = tuple ()
48+
// CHECK: return [[RETURN]] : $()
49+
//
50+
// CHECK: bb2:
51+
// CHECK: end_access [[BEGIN_ACCESS]] : $*State
52+
// CHECK: unwind
53+
// CHECK-END: }
54+
55+
// >> Check that the _read coroutine is synthesized properly
56+
57+
// CHECK-LABEL: sil shared [ossa] @$s26property_wrapper_coroutine6State1V10someValuesSaySSGvr : $@yield_once @convention(method) (@guaranteed State1) -> @yields @guaranteed Array<String> {
58+
// CHECK: bb0([[STATE1:%.*]] : @guaranteed $State1):
59+
// CHECK: debug_value [[SELF:%.*]] : $State1, let, name "self", argno {{.*}}
60+
// CHECK: [[EXTRACT_VALUE:%.*]] = struct_extract %0 : $State1, #State1._someValues
61+
// CHECK: [[COPY_VALUE:%.*]] = copy_value [[EXTRACT_VALUE]] : $TestWrapper<Array<String>>
62+
// CHECK: [[BEGIN_BORROW:%.*]] = begin_borrow [[COPY_VALUE]] : $TestWrapper<Array<String>>
63+
// CHECK: [[EXTRACT_WRAPPEDVALUE:%.*]] = struct_extract [[BEGIN_BORROW]] : $TestWrapper<Array<String>>, #TestWrapper.wrappedValue
64+
// CHECK: yield [[EXTRACT_WRAPPEDVALUE]] : $Array<String>, resume bb1, unwind bb2
65+
//
66+
// CHECK: bb1:
67+
// CHECK: end_borrow [[BEGIN_BORROW]] : $TestWrapper<Array<String>>
68+
// CHECK: destroy_value [[COPY_VALUE]] : $TestWrapper<Array<String>>
69+
// CHECK: [[RETURN:%.*]] = tuple ()
70+
// CHECK: return [[RETURN]] : $()
71+
//
72+
// CHECK: bb2:
73+
// CHECK: end_borrow [[BEGIN_BORROW]] : $TestWrapper<Array<String>>
74+
// CHECK: destroy_value [[COPY_VALUE]] : $TestWrapper<Array<String>>
75+
// CHECK: unwind
76+
// CHECK-END: }

test/decl/var/property_wrappers_synthesis.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct UseWrapper<T: DefaultInit> {
2121

2222
// CHECK: accessor_decl{{.*}}_modify_for=wrapped
2323
// CHECK: yield_stmt
24-
// CHECK: member_ref_expr{{.*}}UseWrapper.wrapped
24+
// CHECK: member_ref_expr{{.*}}Wrapper.wrappedValue
2525
@Wrapper
2626
var wrapped = T()
2727

0 commit comments

Comments
 (0)