Skip to content

Commit b7fd4e1

Browse files
Merge pull request #77179 from nate-chandler/general-coro/20241017/1
[CoroutineAccessors] Permit read requirement.
2 parents 4a12979 + f797e19 commit b7fd4e1

9 files changed

+1301
-27
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ ERROR(static_var_decl_global_scope,none,
255255
(StaticSpellingKind))
256256
ERROR(expected_getset_in_protocol,none,
257257
"expected get or set in a protocol property", ())
258+
ERROR(expected_getreadset_in_protocol,none,
259+
"expected get, read, or set in a protocol property", ())
258260
ERROR(unexpected_getset_implementation_in_protocol,none,
259261
"protocol property %0 cannot have a default implementation specified "
260262
"here; use extension instead", (StringRef))

lib/Parse/ParseDecl.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7806,14 +7806,14 @@ static bool isAllowedWhenParsingLimitedSyntax(AccessorKind kind, bool forSIL) {
78067806
case AccessorKind::Get:
78077807
case AccessorKind::DistributedGet:
78087808
case AccessorKind::Set:
7809+
case AccessorKind::Read2:
78097810
return true;
78107811

78117812
case AccessorKind::Address:
78127813
case AccessorKind::MutableAddress:
78137814
case AccessorKind::WillSet:
78147815
case AccessorKind::DidSet:
78157816
case AccessorKind::Read:
7816-
case AccessorKind::Read2:
78177817
case AccessorKind::Modify:
78187818
case AccessorKind::Modify2:
78197819
return false;
@@ -8144,7 +8144,10 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags, ParameterList *Indices,
81448144

81458145
// parsingLimitedSyntax mode cannot have a body.
81468146
if (parsingLimitedSyntax) {
8147-
diagnose(Tok, diag::expected_getset_in_protocol);
8147+
auto diag = Context.LangOpts.hasFeature(Feature::CoroutineAccessors)
8148+
? diag::expected_getreadset_in_protocol
8149+
: diag::expected_getset_in_protocol;
8150+
diagnose(Tok, diag);
81488151
Status |= makeParserError();
81498152
break;
81508153
}
@@ -8178,7 +8181,10 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags, ParameterList *Indices,
81788181
// avoid having to deal with them everywhere.
81798182
if (parsingLimitedSyntax && !isAllowedWhenParsingLimitedSyntax(
81808183
Kind, SF.Kind == SourceFileKind::SIL)) {
8181-
diagnose(Loc, diag::expected_getset_in_protocol);
8184+
auto diag = Context.LangOpts.hasFeature(Feature::CoroutineAccessors)
8185+
? diag::expected_getreadset_in_protocol
8186+
: diag::expected_getset_in_protocol;
8187+
diagnose(Loc, diag);
81828188
continue;
81838189
}
81848190

lib/Sema/TypeCheckStorage.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,9 @@ OpaqueReadOwnershipRequest::evaluate(Evaluator &evaluator,
859859
return OpaqueReadOwnership::Borrowed;
860860
};
861861

862+
if (storage->getAccessor(AccessorKind::Read2))
863+
return OpaqueReadOwnership::Borrowed;
864+
862865
if (storage->getAttrs().hasAttribute<BorrowedAttr>())
863866
return usesBorrowed(DiagKind::BorrowedAttr);
864867

@@ -3846,9 +3849,13 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
38463849
readImpl = ReadImplKind::Get;
38473850
writeImpl = WriteImplKind::Set;
38483851
readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
3849-
} else if (storage->getParsedAccessor(AccessorKind::Get)) {
3852+
}
3853+
if (storage->getParsedAccessor(AccessorKind::Get)) {
38503854
readImpl = ReadImplKind::Get;
38513855
}
3856+
if (storage->getParsedAccessor(AccessorKind::Read2)) {
3857+
readImpl = ReadImplKind::Read2;
3858+
}
38523859

38533860
StorageImplInfo info(readImpl, writeImpl, readWriteImpl);
38543861
finishStorageImplInfo(storage, info);

test/IRGen/coroutine_accessors.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ public var irm: Int {
3737
modify {
3838
yield &_i
3939
}
40-
// CHECK-OLD-LABEL: define{{.*}} {{i64|i32}} @"$s19coroutine_accessors1SV3irmSivg"(
41-
// CHECK-OLD-SAME: ptr %0,
42-
// CHECK-OLD-SAME: [[INT]] %1
43-
// CHECK-OLD-SAME: ) #0
40+
// CHECK-OLD-LABEL: define{{.*}} { ptr, {{i64|i32}} } @"$s19coroutine_accessors1SV3irmSivr"(
41+
// CHECK-OLD-SAME: ptr noalias dereferenceable({{32|16}}) %0,
42+
// CHECK-OLD-SAME: ptr %1,
43+
// CHECK-OLD-SAME: [[INT]] %2
44+
// CHECK-OLD-SAME: )
4445
// CHECK-OLD-SAME: {
4546
// CHECK-OLD: }
4647
// CHECK-OLD-LABEL: define{{.*}} void @"$s19coroutine_accessors1SV3irmSivs"(

test/Parse/coroutine_accessors.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,18 @@ var ir_rm_m: Int {
326326
fatalError()
327327
}
328328
}
329+
330+
// =============================================================================
331+
// Protocol Requirements
332+
// =============================================================================
333+
334+
protocol P {
335+
var goodP: Int { read set } //expected-disabled-error{{property in protocol must have explicit { get } or { get set } specifier}}
336+
//expected-disabled-error@-1{{expected get or set in a protocol property}}
337+
var badP: Int { read modify } //expected-enabled-error{{expected get, read, or set in a protocol property}}
338+
//expected-disabled-error@-1{{property in protocol must have explicit { get } or { get set } specifier}}
339+
//expected-disabled-error@-2{{expected get or set in a protocol property}}
340+
subscript(goodS goodS: Int) -> Int { read set } //expected-disabled-error{{expected get or set in a protocol property}}
341+
subscript(badS badS: Int) -> Int { read modify } //expected-enabled-error{{expected get, read, or set in a protocol property}}
342+
//expected-disabled-error@-1{{expected get or set in a protocol property}}
343+
}

test/SILGen/coroutine_accessors.swift

Lines changed: 83 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,26 @@ public var irm: Int {
3838
modify {
3939
yield &_i
4040
}
41-
// CHECK-LABEL: sil {{.*}}[ossa] @$s19coroutine_accessors1SV3irmSivg :
42-
// CHECK-SAME: $@convention(method)
41+
// CHECK-LABEL: sil{{.*}} [ossa] @$s19coroutine_accessors1SV3irmSivr :
42+
// CHECK-SAME: $@yield_once
43+
// CHECK-SAME: @convention(method)
4344
// CHECK-SAME: (@guaranteed S)
4445
// CHECK-SAME: ->
45-
// CHECK-SAME: Int
46+
// CHECK-SAME: @yields Int
4647
// CHECK-SAME: {
4748
// CHECK: bb0(
48-
// CHECK-SAME: [[SELF:%[^,]+]] :
49-
// CHECK-SAME: ):
50-
// CHECK: [[READ_ACCESSOR:%[^,]+]] = function_ref @$s19coroutine_accessors1SV3irmSivy
51-
// CHECK: ([[VALUE:%[^,]+]],
52-
// CHECK-SAME: [[TOKEN:%[^,]+]],
53-
// CHECK-SAME: [[ALLOCATION:%[^)]+]])
54-
// CHECK-SAME: = begin_apply [[READ_ACCESSOR]]([[SELF]])
49+
// CHECK: [[SELF:%[^,]+]] :
50+
// CHECK: ):
51+
// CHECK: [[READER2:%[^,]+]] = function_ref @$s19coroutine_accessors1SV3irmSivy
52+
// CHECK: ([[VALUE_ADDRESS:%[^,]+]], [[TOKEN:%[^,]+]], [[ALLOCATION:%[^,]+]]) = begin_apply [[READER2]]([[SELF]])
5553
// CHECK: end_apply [[TOKEN]]
56-
// CHECK: dealloc_stack [[ALLOCATION]]
57-
// CHECK: return [[VALUE:%[^,]+]]
58-
// CHECK-LABEL: } // end sil function '$s19coroutine_accessors1SV3irmSivg'
54+
// CHECK: yield [[VALUE_ADDRESS]] : $Int, resume bb1, unwind bb2
55+
// CHECK: bb1:
56+
// CHECK: dealloc_stack [[ALLOCATION]] : $*Builtin.SILToken
57+
// CHECK: bb2:
58+
// CHECK: dealloc_stack [[ALLOCATION]] : $*Builtin.SILToken
59+
// CHECK: unwind
60+
// CHECK-LABEL: } // end sil function '$s19coroutine_accessors1SV3irmSivr'
5961

6062
// CHECK-LABEL: sil {{.*}}[ossa] @$s19coroutine_accessors1SV3irmSivs :
6163
// CHECK-SAME: $@convention(method)
@@ -95,12 +97,14 @@ public var irm: Int {
9597
// CHECK-SAME: [[TOKEN:%[^,]+]],
9698
// CHECK-SAME: [[ALLOCATION:%[^)]+]])
9799
// CHECK-SAME: = begin_apply [[MODIFY_ACCESSOR]]([[SELF_ACCESS]])
98-
// CHECK: yield [[VALUE_ADDRESS:%[^,]+]] : $*Int, resume bb1, unwind bb2
99-
// CHECK: bb1:
100+
// CHECK: yield [[VALUE_ADDRESS]]
101+
// CHECK-SAME: resume [[RESUME_BB:bb[0-9]+]]
102+
// CHECK-SAME: unwind [[UNWIND_BB:bb[0-9]+]]
103+
// CHECK: [[RESUME_BB]]:
100104
// CHECK: end_apply [[TOKEN]]
101105
// CHECK: end_access [[SELF_ACCESS]]
102106
// CHECK: dealloc_stack [[ALLOCATION]]
103-
// CHECK: bb2:
107+
// CHECK: [[UNWIND_BB]]:
104108
// CHECK: end_apply [[TOKEN]]
105109
// CHECK: dealloc_stack [[ALLOCATION]]
106110
// CHECK: end_access [[SELF_ACCESS]]
@@ -123,7 +127,7 @@ public var irm: Int {
123127
// CHECK: store [[NEW_VALUE:%[^,]+]] to [trivial] [[NEW_VALUE_ADDR]]
124128
// CHECK: [[SELF_ACCESS:%[^,]+]] = begin_access [modify] [unknown] [[SELF]]
125129
// CHECK: [[MODIFY_ACCESSOR:%[^,]+]] = function_ref @$s19coroutine_accessors1SV3irmSivx
126-
// CHECK: ([[VALUE_ADDR:%[^,]+]],
130+
// CHECK: ([[VALUE_ADDR:%[^,]+]],
127131
// CHECK-SAME: [[TOKEN:%[^,]+]],
128132
// CHECK-SAME: [[ALLOCATION:%[^)]+]])
129133
// CHECK-SAME: = begin_apply [[MODIFY_ACCESSOR]]([[SELF_ACCESS]])
@@ -164,3 +168,65 @@ func update<T : Equatable>(at location: inout T, to newValue: T) throws -> T {
164168
location = newValue
165169
return oldValue
166170
}
171+
172+
protocol ReadableTitle {
173+
var title: String { read }
174+
}
175+
class OverridableGetter : ReadableTitle {
176+
var title: String = ""
177+
}
178+
// The read witness thunk does a direct call to the concrete read accessor.
179+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s19coroutine_accessors17OverridableGetterCAA13ReadableTitleA2aDP5titleSSvrTW
180+
// CHECK: function_ref @$s19coroutine_accessors17OverridableGetterC5titleSSvr
181+
// CHECK-LABEL: // end sil function '$s19coroutine_accessors17OverridableGetterCAA13ReadableTitleA2aDP5titleSSvrTW'
182+
// The concrete read accessor is generated on-demand and does a class dispatch to the getter.
183+
// CHECK-LABEL: sil shared [ossa] @$s19coroutine_accessors17OverridableGetterC5titleSSvr
184+
// CHECK: class_method %0 : $OverridableGetter, #OverridableGetter.title!getter
185+
// CHECK-LABEL: // end sil function '$s19coroutine_accessors17OverridableGetterC5titleSSvr'
186+
187+
class ImplementedReader : ReadableTitle {
188+
var _title: String = ""
189+
var title: String {
190+
read {
191+
yield _title
192+
}
193+
}
194+
}
195+
196+
protocol GettableTitle {
197+
var title: String { get }
198+
}
199+
200+
// CHECK-LABEL: sil{{.*}} [ossa] @$s19coroutine_accessors17OverridableReaderCAA13GettableTitleA2aDP5titleSSvgTW : {{.*}} {
201+
// CHECK: bb0(
202+
// CHECK-SAME: [[SELF_ADDR:%[^,]+]] :
203+
// CHECK-SAME: ):
204+
// CHECK: [[SELF:%[^,]+]] = load_borrow [[SELF_ADDR]]
205+
// CHECK: [[GETTER:%[^,]+]] = function_ref @$s19coroutine_accessors17OverridableReaderC5titleSSvg
206+
// CHECK: [[RETVAL:%[^,]+]] = apply [[GETTER]]([[SELF]])
207+
// CHECK: end_borrow [[SELF]]
208+
// CHECK: return [[RETVAL]]
209+
// CHECK-LABEL: } // end sil function '$s19coroutine_accessors17OverridableReaderCAA13GettableTitleA2aDP5titleSSvgTW'
210+
// CHECK-LABEL: sil{{.*}} [ossa] @$s19coroutine_accessors17OverridableReaderC5titleSSvg : {{.*}} {
211+
// CHECK: bb0(
212+
// CHECK-SAME: [[SELF:%[^,]+]] :
213+
// CHECK-SAME: ):
214+
// CHECK: [[READER:%[^,]+]] = class_method [[SELF]] : $OverridableReader, #OverridableReader.title!read
215+
// CHECK: ([[TITLE:%[^,]+]], [[TOKEN:%[^,]+]]) = begin_apply [[READER]]([[SELF]])
216+
// CHECK: [[RETVAL:%[^,]+]] = copy_value [[TITLE]]
217+
// CHECK: end_apply [[TOKEN]] as $()
218+
// CHECK: return [[RETVAL]]
219+
// CHECK-LABEL: } // end sil function '$s19coroutine_accessors17OverridableReaderC5titleSSvg'
220+
221+
// CHECK-LABEL: sil_witness_table{{.*}} OverridableReader: GettableTitle {{.*}} {
222+
// CHECK-NEXT: method #GettableTitle.title!getter
223+
// CHECK-SAME: @$s19coroutine_accessors17OverridableReaderCAA13GettableTitleA2aDP5titleSSvgTW
224+
// CHECK-NEXT: }
225+
class OverridableReader : GettableTitle {
226+
var _title: String = ""
227+
var title: String {
228+
read {
229+
yield _title
230+
}
231+
}
232+
}

0 commit comments

Comments
 (0)