You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: proposals/0411-isolated-default-values.md
+22-9Lines changed: 22 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,14 +29,14 @@ class C {
29
29
}
30
30
```
31
31
32
-
The above code allows any context to initialize an instance of `C()` through a synchronous, non-isolated`init` that synchronously calls both a `@MainActor`-isolated and a `@AnotherActor`-isolated function, violating actor isolation checking and enabling `requiresMainActor()` and `requiresAnotherActor()`to run concurrently with other code on those respective actors.
32
+
The above code allows any context to initialize an instance of `C()` through a synchronous, nonisolated`init`. The initializer synchronously calls both `requiresMainActor()` and `requiresAnotherActor()`, which are `@MainActor`-isolated and `@AnotherActor`-isolated, respectively. This violates actor isolation checking because `requiresMainActor()` and `requiresAnotherActor()`may run concurrently with other code on their respective global actors.
33
33
34
-
The current actor isolation rules for default argument values do not admit data races, but default argument values are always `nonisolated` which is overly restrictive. This rule prohibits programmers from making `@MainActor`-isolated calls in default argument values of `@MainActor`-isolated functions that are only ever called from the main actor. For example, the following code is not valid even though it is perfectly safe:
34
+
The current actor isolation rules for default argument values do not admit data races, but default argument values are always `nonisolated` which is overly restrictive. This rule prohibits programmers from making `@MainActor`-isolated calls in default argument values of `@MainActor`-isolated functions. For example, the following code is not valid even though it is perfectly safe:
35
35
36
36
```swift
37
-
@MainActorclassC {...}
37
+
@MainActorclassC {}
38
38
39
-
@MainActorfuncf(c: C =C()) {...} // error
39
+
@MainActorfuncf(c: C =C()) {} // error: Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
40
40
41
41
@MainActorfuncuseFromMainActor() {
42
42
f()
@@ -45,23 +45,37 @@ The current actor isolation rules for default argument values do not admit data
45
45
46
46
## Proposed solution
47
47
48
-
I propose allowing default value expressions to impose an isolation requirement at the call-site. The isolation requirement is inferred from the default value expression, and it must match the isolation of the enclosing function or the corresponding stored property. If the caller does not meet the isolation requirement, then the call must be made asynchronously and must be explicitly marked with `await`. For default stored property initializers that are implicitly invoked in the body of an `init`, the initialization must be written out explicitly if the default expression requires a different isolation from the `init` itself.
48
+
I propose allowing default value expressions to have the same isolation as the enclosing function or the corresponding stored property. As usual, if the caller is not already in the isolation domain of the callee, then the call must be made asynchronously and must be explicitly marked with `await`. For isolated default values of stored properties, the implicit initialization only happens in the body of an `init` with the same isolation.
49
49
50
-
These rule makes the stored property example above invalid at the point of the `nonisolated` initializer, because the isolation requirement of the default values for the stored properties is not satisfied. Calling `requiresMainActor` explicitly with `await` resolves the issue:
50
+
These rule makes the stored property example above invalid at the `nonisolated` initializer:
nonisolatedinit() {} // error: 'self.x2' and 'self.x2' are not initialized
61
+
}
62
+
```
63
+
64
+
Calling `requiresMainActor()` and `requiresAnotherActor()` explicitly with `await` resolves the issue:
65
+
66
+
```swift
67
+
classC {
68
+
@MainActorvar x1 =requiresMainActor()
69
+
@AnotherActorvar x2 =requiresAnotherActor()
57
70
58
71
nonisolatedinit() async {
59
72
self.x1=awaitrequiresMainActor()
73
+
self.x2=awaitrequiresAnotherActor()
60
74
}
61
75
}
62
76
```
63
77
64
-
This rule also makes the default argument example above valid, because the `@MainActor` isolation requirement for the default argument of `f` is satisfied by the caller.
78
+
This rule also makes the default argument example above valid, because the default argument and the enclosing function are both `@MainActor`-isolated.
65
79
66
80
## Detailed design
67
81
@@ -132,8 +146,7 @@ In the above example, `useDefault` has default arguments that are isolated to `@
132
146
For a given call, argument evaluation happens in the following order:
133
147
134
148
1. Left-to-right evalution of explicit r-value arguments
135
-
2. Left-to-right evaluation of default arguments
136
-
3. Left-to-right evaluation of formal access arguments
149
+
2. Left-to-right evaluation of default arguments and formal access arguments
0 commit comments