Jens
1
Hi!
After updating to Xcode 15.3, I get the warning:
Main actor-isolated property 'foo' can not be mutated from a non-isolated context; this is an error in Swift 6
in code constructs like this:
@MainActor
final class SomeViewModel: ObservableObject {
@Published private(set) var state = ...
private let foo: String
private let bar: (String) -> Void
nonisolated init(
foo: String,
bar: @escaping (String) -> Void
) {
self.foo = foo // <-- No warning here
self.bar = bar // <-- Warning here
}
...
}
Questions:
-
Why shouldn't I be able to set private constants in the initialiser of a class like this from a non-isolated context? (The instance is not created, so how can it be "mutating" the private let property?
-
Why do I only get the warning for bar and not also for foo?
-
Is adding nonisolated to the private let property with the warning an acceptable fix for this?
1 Like
vns
2
String conforms to Sendable, so it is safe for foo to cross isolation boundary. Closure you pass to init is not. Adding @Sendable attribute will fix the warning.
Because bar property by not being sendable cannot safely cross isolation boundary (from main-actor isolation to nonisolated context) at the time of assign. Probably, compiler message here not that descriptive; the case not in "mutability", but non-Sendable closure is crossing isolation boundary.
3 Likes
Jens
3
- Is adding
nonisolated to the private let property with the warning an acceptable fix for this?
Hmm, the warning is still there after adding nonisolated like this:
nonisolated private let bar: (String) -> Void
vns
4
Depends on use case, e.g. you would need to access this nonisolated property from nonisolated context. Making it @Sendable will make it usable within the class easily, and probably this is better strategy to resolve the warning.
1 Like
hborla
(Holly Borla)
5
There's an explanation for why this happens at Assigning to a `let` instance variable in nonisolated init - #4 by hborla
tldr; the compiler should not let you write nonisolated on stored properties of Sendable/actor-isolated types when the stored property type is not Sendable. This is fixed in the Swift 6 language mode.
2 Likes
Using Xcode 16 beta and enable Swift 6, I can remove the warning with below code
@MainActor
final class SomeViewModel: ObservableObject {
@Published private(set) var state = ...
private let foo: String
nonisolated private let bar: @Sendable (String) -> Void
nonisolated init(foo: String,
bar: @Sendable @escaping (String) -> Void) {
self.foo = foo
self.bar = bar
}
}
1 Like