Skip to content

Commit 2f42bb7

Browse files
committed
[Release Notes] Improve the release note for SE-0412.
1 parent 6226993 commit 2f42bb7

File tree

1 file changed

+44
-17
lines changed

1 file changed

+44
-17
lines changed

CHANGELOG.md

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,28 +111,55 @@ strict concurrency checking ahead of Swift 6.
111111

112112
* [SE-0412][]:
113113

114-
Under strict concurrency checking, every global or static variable must be either isolated to a global actor or be both immutable and of `Sendable` type.
114+
Global and static variables are prone to data races because they provide memory that can be accessed from any program context. Strict concurrency checking in Swift 5.10 prevents data races on global and static variables by requiring them to be either:
115115

116-
```swift
117-
var mutableGlobal = 1
118-
// warning: var 'mutableGlobal' is not concurrency-safe because it is non-isolated global shared mutable state
119-
// (unless it is top-level code which implicitly isolates to @MainActor)
116+
1. isolated to a global actor, or
117+
2. immutable and of `Sendable` type.
120118

121-
final class NonsendableType {
122-
init() {}
123-
}
119+
or example:
124120

125-
struct S {
126-
static let immutableNonsendable = NonsendableType()
127-
// warning: static property 'immutableNonsendable' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor
128-
}
129-
```
121+
```swift
122+
var mutableGlobal = 1
123+
// warning: var 'mutableGlobal' is not concurrency-safe because it is non-isolated global shared mutable state
124+
// (unless it is top-level code which implicitly isolates to @MainActor)
130125

131-
The attribute `nonisolated(unsafe)` can be used to annotate a global variable (or any form of storage) to disable static checking of data isolation, but note that without correct implementation of a synchronization mechanism to achieve data isolation, dynamic run-time analysis from exclusivity enforcement or tools such as Thread Sanitizer could still identify failures.
126+
@MainActor func mutateGlobalFromMain() {
127+
mutableGlobal += 1
128+
}
132129

133-
```swift
134-
nonisolated(unsafe) var global: String
135-
```
130+
nonisolated func mutateGlobalFromNonisolated() async {
131+
mutableGlobal += 10
132+
}
133+
134+
struct S {
135+
static let immutableSendable = 10
136+
// okay; 'immutableSendable' is safe to access concurrently because it's immutable and 'Int' is 'Sendable'
137+
}
138+
```
139+
140+
A new `nonisolated(unsafe)` modifier can be used to annotate a global or static variable to suppress data isolation violations when manual synchronization is provided:
141+
142+
```swift
143+
// This global is only set in one part of the program
144+
nonisolated(unsafe) var global: String!
145+
```
146+
147+
`nonisolated(unsafe)` can be used on any form of storage, including stored properties and local variables, as a more granular opt out for `Sendable` checking, eliminating the need for `@unchecked Sendable` wrapper types in many use cases:
148+
149+
```swift
150+
import Dispatch
151+
152+
// 'MutableData' is not 'Sendable'
153+
class MutableData { ... }
154+
155+
final class MyModel: Sendable {
156+
private let queue = DispatchQueue(...)
157+
// 'protectedState' is manually isolated by 'queue'
158+
nonisolated(unsafe) private var protectedState: MutableData
159+
}
160+
```
161+
162+
Note that without correct implementation of a synchronization mechanism to achieve data isolation, dynamic run-time analysis from exclusivity enforcement or tools such as the Thread Sanitizer could still identify failures.
136163

137164
* [SE-0411][]:
138165

0 commit comments

Comments
 (0)