mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Enable ConcurrentValue checking as part of Concurrency mode.
Drop the separate flag guarding this checking.
This commit is contained in:
@@ -244,9 +244,6 @@ namespace swift {
|
||||
/// Enable experimental concurrency model.
|
||||
bool EnableExperimentalConcurrency = false;
|
||||
|
||||
/// Enable experimental ConcurrentValue checking.
|
||||
bool EnableExperimentalConcurrentValueChecking = false;
|
||||
|
||||
/// Enable experimental flow-sensitive concurrent captures.
|
||||
bool EnableExperimentalFlowSensitiveConcurrentCaptures = false;
|
||||
|
||||
|
||||
@@ -218,10 +218,6 @@ def enable_experimental_concurrency :
|
||||
Flag<["-"], "enable-experimental-concurrency">,
|
||||
HelpText<"Enable experimental concurrency model">;
|
||||
|
||||
def enable_experimental_concurrent_value_checking :
|
||||
Flag<["-"], "enable-experimental-concurrent-value-checking">,
|
||||
HelpText<"Enable ConcurrentValue checking">;
|
||||
|
||||
def enable_experimental_flow_sensitive_concurrent_captures :
|
||||
Flag<["-"], "enable-experimental-flow-sensitive-concurrent-captures">,
|
||||
HelpText<"Enable flow-sensitive concurrent captures">;
|
||||
|
||||
@@ -385,8 +385,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
|
||||
|
||||
Opts.EnableExperimentalConcurrency |=
|
||||
Args.hasArg(OPT_enable_experimental_concurrency);
|
||||
Opts.EnableExperimentalConcurrentValueChecking |=
|
||||
Args.hasArg(OPT_enable_experimental_concurrent_value_checking);
|
||||
Opts.EnableExperimentalFlowSensitiveConcurrentCaptures |=
|
||||
Args.hasArg(OPT_enable_experimental_flow_sensitive_concurrent_captures);
|
||||
|
||||
|
||||
@@ -823,7 +823,7 @@ bool swift::diagnoseNonConcurrentTypesInReference(
|
||||
ConcreteDeclRef declRef, const DeclContext *dc, SourceLoc loc,
|
||||
ConcurrentReferenceKind refKind) {
|
||||
// Bail out immediately if we aren't supposed to do this checking.
|
||||
if (!dc->getASTContext().LangOpts.EnableExperimentalConcurrentValueChecking)
|
||||
if (!dc->getASTContext().LangOpts.EnableExperimentalConcurrency)
|
||||
return false;
|
||||
|
||||
// For functions, check the parameter and result types.
|
||||
@@ -1118,7 +1118,7 @@ namespace {
|
||||
if (!indexExpr || !indexExpr->getType())
|
||||
continue;
|
||||
|
||||
if (ctx.LangOpts.EnableExperimentalConcurrentValueChecking &&
|
||||
if (ctx.LangOpts.EnableExperimentalConcurrency &&
|
||||
!isConcurrentValueType(getDeclContext(), indexExpr->getType())) {
|
||||
ctx.Diags.diagnose(
|
||||
component.getLoc(), diag::non_concurrent_keypath_capture,
|
||||
|
||||
@@ -158,16 +158,22 @@ func blender(_ peeler : () -> Void) {
|
||||
|
||||
@OrangeActor func makeSmoothie() async {
|
||||
await wisk({})
|
||||
// expected-warning@-1{{cannot pass argument of non-concurrent-value type 'Any' across actors}}
|
||||
await wisk(1)
|
||||
// expected-warning@-1{{cannot pass argument of non-concurrent-value type 'Any' across actors}}
|
||||
await (peelBanana)()
|
||||
await (((((peelBanana)))))()
|
||||
await (((wisk)))((wisk)((wisk)(1)))
|
||||
// expected-warning@-1 3{{cannot pass argument of non-concurrent-value type 'Any' across actors}}
|
||||
|
||||
blender((peelBanana)) // expected-error {{global function 'peelBanana()' isolated to global actor 'BananaActor' can not be referenced from different global actor 'OrangeActor'}}
|
||||
await wisk(peelBanana) // expected-error {{global function 'peelBanana()' isolated to global actor 'BananaActor' can not be referenced from different global actor 'OrangeActor'}}
|
||||
// expected-warning@-1{{cannot pass argument of non-concurrent-value type 'Any' across actors}}
|
||||
|
||||
await wisk(wisk) // expected-error {{global function 'wisk' isolated to global actor 'BananaActor' can not be referenced from different global actor 'OrangeActor'}}
|
||||
// expected-warning@-1{{cannot pass argument of non-concurrent-value type 'Any' across actors}}
|
||||
await (((wisk)))(((wisk))) // expected-error {{global function 'wisk' isolated to global actor 'BananaActor' can not be referenced from different global actor 'OrangeActor'}}
|
||||
// expected-warning@-1{{cannot pass argument of non-concurrent-value type 'Any' across actors}}
|
||||
|
||||
// expected-warning@+2 {{no calls to 'async' functions occur within 'await' expression}}
|
||||
// expected-error@+1 {{global function 'wisk' isolated to global actor 'BananaActor' can not be referenced from different global actor 'OrangeActor'}}
|
||||
@@ -205,13 +211,18 @@ actor Calculator {
|
||||
|
||||
@OrangeActor func doSomething() async {
|
||||
let _ = (await bananaAdd(1))(2)
|
||||
// expected-warning@-1{{cannot call function returning non-concurrent-value type}}
|
||||
let _ = await (await bananaAdd(1))(2) // expected-warning{{no calls to 'async' functions occur within 'await' expression}}
|
||||
// expected-warning@-1{{cannot call function returning non-concurrent-value type}}
|
||||
|
||||
let calc = Calculator()
|
||||
|
||||
let _ = (await calc.addCurried(1))(2)
|
||||
// expected-warning@-1{{cannot call function returning non-concurrent-value type}}
|
||||
let _ = await (await calc.addCurried(1))(2) // expected-warning{{no calls to 'async' functions occur within 'await' expression}}
|
||||
// expected-warning@-1{{cannot call function returning non-concurrent-value type}}
|
||||
|
||||
let plusOne = await calc.addCurried(await calc.add(0, 1))
|
||||
// expected-warning@-1{{cannot call function returning non-concurrent-value type}}
|
||||
let _ = plusOne(2)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ func test_cancellation_guard_isCancelled(_ any: Any) async -> PictureData {
|
||||
return PictureData.value("...")
|
||||
}
|
||||
|
||||
struct SomeFile {
|
||||
struct SomeFile: ConcurrentValue {
|
||||
func close() {}
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ func test_taskGroup_quorum_thenCancel() async {
|
||||
case yay
|
||||
case nay
|
||||
}
|
||||
struct Follower {
|
||||
struct Follower: ConcurrentValue {
|
||||
init(_ name: String) {}
|
||||
func vote() async throws -> Vote {
|
||||
// "randomly" vote yes or no
|
||||
@@ -181,13 +181,13 @@ func test_taskGroup_quorum_thenCancel() async {
|
||||
_ = await gatherQuorum(followers: [Follower("A"), Follower("B"), Follower("C")])
|
||||
}
|
||||
|
||||
extension Collection {
|
||||
extension Collection where Self: ConcurrentValue, Element: ConcurrentValue, Self.Index: ConcurrentValue {
|
||||
|
||||
/// Just another example of how one might use task groups.
|
||||
func map<T>(
|
||||
func map<T: ConcurrentValue>(
|
||||
parallelism requestedParallelism: Int? = nil/*system default*/,
|
||||
// ordered: Bool = true, /
|
||||
_ transform: (Element) async throws -> T
|
||||
_ transform: @concurrent (Element) async throws -> T
|
||||
) async throws -> [T] { // TODO: can't use rethrows here, maybe that's just life though; rdar://71479187 (rethrows is a bit limiting with async functions that use task groups)
|
||||
let defaultParallelism = 2
|
||||
let parallelism = requestedParallelism ?? defaultParallelism
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency -enable-experimental-concurrent-value-checking
|
||||
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
|
||||
// REQUIRES: concurrency
|
||||
|
||||
class NotConcurrent { }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency -enable-experimental-concurrent-value-checking
|
||||
// RUN: %target-typecheck-verify-swift -enable-experimental-concurrency
|
||||
|
||||
// REQUIRES: concurrency
|
||||
// REQUIRES: objc_interop
|
||||
|
||||
@@ -86,7 +86,7 @@ func testCaseTrivialValue4() {
|
||||
// expected-note @-8 {{capturing use}}
|
||||
}
|
||||
|
||||
class Klass {
|
||||
class Klass: UnsafeConcurrentValue {
|
||||
var next: Klass? = nil
|
||||
}
|
||||
func inoutUserKlass(_ k: inout Klass) {}
|
||||
@@ -130,7 +130,7 @@ func testCaseClassInoutField() {
|
||||
// Non Trivial Value Type //
|
||||
////////////////////////////
|
||||
|
||||
struct NonTrivialValueType {
|
||||
struct NonTrivialValueType: ConcurrentValue {
|
||||
var i: Int
|
||||
var k: Klass? = nil
|
||||
|
||||
@@ -182,7 +182,7 @@ protocol MyProt {
|
||||
var k: Klass? { get set }
|
||||
}
|
||||
|
||||
func testCaseAddressOnlyAllocBoxToStackable<T : MyProt>(i : T) {
|
||||
func testCaseAddressOnlyAllocBoxToStackable<T : MyProt & ConcurrentValue>(i : T) {
|
||||
var i2 = i
|
||||
f {
|
||||
print(i2.i + 17)
|
||||
@@ -199,7 +199,7 @@ func testCaseAddressOnlyAllocBoxToStackable<T : MyProt>(i : T) {
|
||||
|
||||
// Alloc box to stack can't handle this test case, so show off a bit and make
|
||||
// sure we can emit a great diagnostic here!
|
||||
func testCaseAddressOnlyNoAllocBoxToStackable<T : MyProt>(i : T) {
|
||||
func testCaseAddressOnlyNoAllocBoxToStackable<T : MyProt & ConcurrentValue>(i : T) {
|
||||
let f2 = F()
|
||||
var i2 = i
|
||||
f2.useConcurrent {
|
||||
|
||||
@@ -34,6 +34,7 @@ actor MyActor {
|
||||
// CHECK: @objc func doBigJobOrFail(_: Int) async throws -> (AnyObject, Int)
|
||||
// CHECK-DUMP: func_decl{{.*}}doBigJobOrFail{{.*}}foreign_async=@convention(block) (Optional<AnyObject>, Int, Optional<Error>) -> (),completion_handler_param=1,error_param=2
|
||||
@objc func doBigJobOrFail(_: Int) async throws -> (AnyObject, Int) { return (self, 0) }
|
||||
// expected-warning@-1{{cannot call function returning non-concurrent-value type '(AnyObject, Int)' across actors}}
|
||||
|
||||
// Actor-isolated entities cannot be exposed to Objective-C.
|
||||
@objc func synchronousBad() { } // expected-error{{actor-isolated instance method 'synchronousBad()' cannot be @objc}}
|
||||
|
||||
Reference in New Issue
Block a user