Skip to content

Commit 1b3aa87

Browse files
authored
Merge pull request #73666 from hborla/implicit-global-actor-sendable
[Concurrency] Implicit global actor attributes imply `Sendable`.
2 parents ffba38d + 1b0dca0 commit 1b3aa87

File tree

3 files changed

+32
-15
lines changed

3 files changed

+32
-15
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6059,7 +6059,7 @@ ProtocolConformance *swift::deriveImplicitSendableConformance(
60596059
}
60606060

60616061
// A non-protocol type with a global actor is implicitly Sendable.
6062-
if (nominal->getGlobalActorAttr()) {
6062+
if (getActorIsolation(nominal).isGlobalActor()) {
60636063
// Form the implicit conformance to Sendable.
60646064
return formConformance(nullptr);
60656065
}

test/Concurrency/sendable_checking.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,3 +407,23 @@ struct DowngradeForPreconcurrency {
407407
}
408408
}
409409
}
410+
411+
@available(SwiftStdlib 5.1, *)
412+
@MainActor protocol InferMainActor {}
413+
414+
@available(SwiftStdlib 5.1, *)
415+
struct ImplicitSendableViaMain: InferMainActor {}
416+
417+
@available(SwiftStdlib 5.1, *)
418+
extension ImplicitSendableViaMain {
419+
nonisolated func capture() {
420+
Task { @MainActor in
421+
_ = self
422+
}
423+
}
424+
}
425+
426+
@available(SwiftStdlib 5.1, *)
427+
struct TestImplicitSendable: Sendable {
428+
var x: ImplicitSendableViaMain
429+
}

validation-test/Sema/SwiftUI/rdar76252310.swift

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 -swift-version 5 -strict-concurrency=targeted
1+
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 -swift-version 5 -strict-concurrency=complete
22

33
// REQUIRES: objc_interop
44
// REQUIRES: OS=macosx
55

66
import SwiftUI
77

8-
class Visibility: ObservableObject { // expected-note 2{{class 'Visibility' does not conform to the 'Sendable' protocol}}
8+
@MainActor
9+
class Visibility: ObservableObject {
10+
nonisolated init() {}
11+
912
@Published var yes = false // some nonsense
1013
}
1114

12-
struct CoffeeTrackerView: View { // expected-note 4{{consider making struct 'CoffeeTrackerView' conform to the 'Sendable' protocol}}
15+
struct CoffeeTrackerView: View {
16+
nonisolated init() {}
17+
1318
@ObservedObject var showDrinkList: Visibility = Visibility()
1419

1520
var storage: Visibility = Visibility()
@@ -34,24 +39,16 @@ func fromMainActor() async {
3439

3540

3641
func fromConcurrencyAware() async {
37-
// expected-note@+3 {{calls to initializer 'init()' from outside of its actor context are implicitly asynchronous}}
38-
// expected-warning@+2 {{expression is 'async' but is not marked with 'await'}}
39-
// expected-warning@+1 {{non-sendable type 'CoffeeTrackerView' returned by call to main actor-isolated function cannot cross actor boundary}}
40-
let view = CoffeeTrackerView()
42+
let view = CoffeeTrackerView() // synthesized 'init' is 'nonisolated'
4143

42-
// expected-warning@+4 {{non-sendable type 'CoffeeTrackerView' passed in implicitly asynchronous call to main actor-isolated property 'body' cannot cross actor boundary}}
4344
// expected-note@+3 {{property access is 'async'}}
4445
// expected-warning@+2 {{non-sendable type 'some View' in implicitly asynchronous access to main actor-isolated property 'body' cannot cross actor boundary}}
4546
// expected-warning@+1 {{expression is 'async' but is not marked with 'await'}}
4647
_ = view.body
4748

48-
// expected-warning@+4 {{non-sendable type 'CoffeeTrackerView' passed in implicitly asynchronous call to main actor-isolated property 'showDrinkList' cannot cross actor boundary}}
49-
// expected-note@+3 {{property access is 'async'}}
50-
// expected-warning@+2 {{non-sendable type 'Visibility' in implicitly asynchronous access to main actor-isolated property 'showDrinkList' cannot cross actor boundary}}
49+
// expected-note@+2 {{property access is 'async'}}
5150
// expected-warning@+1 {{expression is 'async' but is not marked with 'await'}}
5251
_ = view.showDrinkList
5352

54-
// expected-warning@+2 {{non-sendable type 'CoffeeTrackerView' passed in implicitly asynchronous call to main actor-isolated property 'storage' cannot cross actor boundary}}
55-
// expected-warning@+1 {{non-sendable type 'Visibility' in implicitly asynchronous access to main actor-isolated property 'storage' cannot cross actor boundary}}
56-
_ = await view.storage
53+
_ = view.storage
5754
}

0 commit comments

Comments
 (0)