Skip to content

Commit bee33b2

Browse files
committed
Revise for style and flow
- Adjusted the framing of the examples to be specifically about main-actor isolation, since they use @mainactor, as a concrete example of the global-actor isolation rules. - Removed the headings for classes and protocols -- both of them can be explained in one section together. Although level 4 headings are supported by the tools, using them should be rare. - Added announceDeparture() so the code shows an example of each listed inference rule. - Marked a few places to discuss/fill in with XXX.
1 parent 0f1df57 commit bee33b2

File tree

1 file changed

+74
-46
lines changed

1 file changed

+74
-46
lines changed

TSPL.docc/LanguageGuide/Concurrency.md

Lines changed: 74 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,7 +1371,6 @@ if you try to add concurrent code to this function,
13711371
introducing a possible suspension point,
13721372
you'll get compile-time error instead of introducing a bug.
13731373

1374-
13751374
## Global Actors
13761375

13771376
The main actor is a global singleton instance of the [`MainActor`][] type.
@@ -1392,17 +1391,18 @@ You can define your own singleton global actors
13921391
using the `@globalActor` attribute,
13931392
as described in <doc:Attributes#globalActor>.
13941393

1395-
### Isolation inference
1396-
1397-
Swift infers global actor isolation in the code you write based on
1398-
class inheritance and protocol conformances.
1394+
## Isolation Inference
13991395

1400-
#### Classes
1396+
<!-- XXX introduction
1397+
- it would be tedious (or introduce errors) to not have these rules
1398+
- these inference rules apply to the main actor and other global actors
1399+
-->
14011400

1402-
If a superclass has global actor isolation, Swift infers that global actor
1403-
on subclasses. For example, the code below has a main-actor
1404-
isolated class `Vehicle`, and a subclass `Train` that inherits
1405-
from `Vehicle`:
1401+
For classes that are isolated to a global actor,
1402+
Swift infers their subclasses have the same isolation.
1403+
For example,
1404+
the code below declares a main-actor isolated class `Vehicle`,
1405+
and a subclass `Train` that inherits from `Vehicle`:
14061406

14071407
```swift
14081408
@MainActor
@@ -1414,20 +1414,30 @@ class Vehicle {
14141414
}
14151415

14161416
class Train: Vehicle {
1417+
func announceDeparture() {
1418+
print("All aboard!")
1419+
}
14171420
override func makeNoise() {
14181421
print("Choo Choo")
14191422
}
14201423
}
14211424
```
14221425

1423-
In the above example, all methods and properties in `Vehicle`
1424-
are isolated to the main actor. The `Train` class inherits all
1425-
methods, properties, and global actor isolation from the `Vehicle`
1426-
superclass, so Swift infers main-actor isolation for the `makeNoise`
1427-
override.
1428-
1429-
Swift also infers global-actor isolation from individual overridden
1430-
methods. For example, the following code isolates one method of the
1426+
In the example above,
1427+
the `Vehicle` class is isolated to the main actor ---
1428+
writing `@MainActor` on the type
1429+
isolates all of its methods and properties to the main actor.
1430+
The `Train` subclass of `Vehicle` inherits this main-actor isolation,
1431+
which isolates all of the following to the main actor:
1432+
1433+
- Methods and properties it inherits, such as `currentSpeed`.
1434+
- Methods and properties it adds, such as `announceDeparture()`.
1435+
- Methods and properties in overrides, such as `makeNoise()`.
1436+
1437+
When subclassing a type that isn't isolated to a global actor,
1438+
Swift infers that overrides to any global-actor methods
1439+
are also isolated to that global actor.
1440+
For example, the following code isolates one method of the
14311441
`Vehicle` class to the main actor instead of the entire class:
14321442

14331443
```swift
@@ -1447,17 +1457,23 @@ class Train: Vehicle {
14471457
}
14481458
```
14491459

1450-
Swift infers main-actor isolation for the `makeNoise` override of
1451-
the `Train` subclass based on the isolation of the `makeNoise` method
1452-
in `Vehicle`.
1453-
1454-
#### Protocols
1455-
1456-
Swift infers global-actor isolation from protocol conformances.
1457-
When a type conforms to a protocol, Swift infers actor isolation from
1458-
the protocol itself, and from individual protocol requirements.
1459-
For example, the following code has a main-actor isolated protocol
1460-
`Togglable`, and a conforming struct `Switch`:
1460+
Because the `makeNoise()` method of `Vehicle` is marked `@MainActor`,
1461+
Swift infers that an override in a subclass
1462+
is also isolated to the main actor.
1463+
In the code above, the `makeNoise()` method of `Train`
1464+
isn't explicitly marked `@MainActor`
1465+
but its main-actor isolation is inferred
1466+
from the method on `Vehicle` that it overrides.
1467+
1468+
In addition to the places shown above
1469+
where Swift infers isolation from a superclass,
1470+
Swift also infers isolation from protocol conformances.
1471+
When a type conforms to a protocol,
1472+
Swift infers isolation from the protocol itself,
1473+
and from individual protocol requirements.
1474+
For example,
1475+
the following code has a main-actor isolated protocol `Togglable`,
1476+
and a conforming struct `Switch`:
14611477

14621478
```swift
14631479
@MainActor
@@ -1474,16 +1490,19 @@ struct Switch: Togglable {
14741490
}
14751491
```
14761492

1477-
In the above example, `Togglable` and all of its requirements
1478-
are isolated to the main actor. Swift infers main-actor isolation
1479-
on types that conform to `Togglable`, so all methods and properties
1480-
of `Switch` are isolated to the main actor, including the `isOn`
1481-
property and the `toggle` method.
1482-
1483-
Swift only infers isolation from protocols when you write the conformance
1484-
at the primary declaration. If you write the conformance in
1485-
an extension, then isolation inference only applies to requirements that
1486-
are implemented in the extension. For example, the following code
1493+
In the example above,
1494+
the `Togglable` protocol is marked `@MainActor`
1495+
to indicate that all of its requirements are isolated to the main actor.
1496+
Swift infers main-actor isolation on types that conform to `Togglable`,
1497+
so all methods and properties of `Switch` are isolated to the main actor,
1498+
including the `isOn` property and the `toggle` method.
1499+
1500+
Swift infers isolation from protocols
1501+
only when you write the conformance as part of the type's declaration.
1502+
If you write the conformance in an extension,
1503+
then isolation inference applies to
1504+
only requirements that are part of that the extension.
1505+
For example, the following code
14871506
implements a conformance of `Switch` to `Togglable` in an extension:
14881507

14891508
```swift
@@ -1492,7 +1511,7 @@ protocol Togglable {
14921511
mutating func toggle()
14931512
}
14941513

1495-
struct Switch: Togglable {
1514+
struct Switch {
14961515
var isOn: Bool = false
14971516
}
14981517

@@ -1503,13 +1522,22 @@ extension Switch: Togglable {
15031522
}
15041523
```
15051524

1506-
Swift does not infer global-actor isolation on the `Switch` type itself;
1507-
the `Switch` type is `nonisolated`, and the methods and properties directly
1508-
inside the type are `nonisolated`. Swift infers global-actor isolation for
1509-
the protocol requirements implemented in the extension that declares the
1510-
conformance to `Togglable`, so the `toggle` method is isolated to the
1511-
main actor.
1525+
<!-- XXX TR:
1526+
Was it intentional that Switch declaration listed conformance to Togglable
1527+
without implementing the protocol requirement? When I build the code with
1528+
that, I get an error about redundant conformance in the extension, and it
1529+
didn't quite match the prose, so I removed it.
1530+
-->
15121531

1532+
Because the declaration of `Switch`
1533+
doesn't include conformance to the `Togglable` protocol,
1534+
`Switch` is understood as `nonisolated`,
1535+
and the methods and properties declared inside it are also `nonisolated`.
1536+
However,
1537+
Swift infers main-actor isolation
1538+
for the extension because it implements `Togglable`,
1539+
which is a main-actor-isolated protocol.
1540+
This inference means the `toggle()` method is isolated to the main actor.
15131541

15141542
<!--
15151543
OUTLINE

0 commit comments

Comments
 (0)