There is going to be "weird" somewhere with async access to properties. This proposal draws the line at setting. If we allowed setting, we would draw the line at inout
. I also feel like piece-meal setting of actor state property-by-property might be something we don't want to support long-term, so this felt safer.
This is a good idea. I've incorporated much of this, thanks!
Sure, they're gone.
I've added some rationale.
No, I don't think so. We could add it later if it's important.
@ktoso was arguing that it's not an API we should actually provide. I'll let him give his reasons.
Yes, I agree that it would be possible to call such a thing by, say, unsafely casting the function type. The restriction is there to point out a potential pitfall... but I'm okay with removing it. Perhaps at some point we'll gain a way to have multiple actor instances that are statically known to share a concurrency domain/executor.
I'm fine with introducing additional motivation first, and the some reshuffling to bring it later, but nonisolated
is directly related to isolated
and has proven to be an important part of the model, so it will remain in this proposal. I've gone ahead and done this.
Sure, fixed.
Yes, this is absolutely required. There is no code with correctly-annotated @concurrent
functions yet, and we can not instantaneously update the world to introduce the appropriate @concurrent
annotations. We can start lifting this restriction from code that's getting recompiled under the structured Swift Concurrency model, but it will take time.
Lots of basic callback things happen "later" and would introduce data races, and the main thread is particularly important for safety.
Dispatch.sync is semantically fine (albeit a performance nightmare), because the caller is blocked. You want concurrentPerform to prove your point, and yes: the @escaping
approach described in this proposal is not 100% bulletproof. But experience with the model shows that it is extremely valuable in catching concurrent executions when working with the Swift ecosystem we have today.
We can talk about more effective ways to phase out this @escaping
or time, but I'll be blunt: that @escaping
implies non-isolated capture is not negotiable.
Sure, thanks for the example.
... or Sendable
, as it were. Done.
I can look into improving the presentation here, but I think your suggestions here are all deeply influenced by your feeling that nonisolated
is unimportant and should not be part of the model.
I see what you mean here; it's effectively applying the principle that one can asynchronously access synchronous methods to partial applications. This can be made to work, although it runs afoul of one of the principles we've maintained thus far, which is that the type of a reference to a declaration (e.g., the type of otherA.f
) is not dependent on whether otherA
is isolated or not in this context.
The rules here from the need to not escape isolated actor instances. Remember that self.g
is @escaping
when there is no context forcing it to be noescape, e.g.,
let fn = self.g
produces an @escaping
function type.
Isolated conformances are the ones that are different from any other kind of conformance we have in the type system, because they only apply to a subset of the values of a given type, and necessarily have other restrictions on what kinds of protocols can work with them. Non-isolated conformances apply to every instance of the type, like all other conformances in Swift. One of the two must have a qualifier, and isolated
conformances---which work only on isolated
parameters and are different from all other conformances---should be have the qualifier.
It was called simply Actor
, and we dropped it at one point because one couldn't actually do anything with it. However, I'd like to bring it back as an empty protocol (to be filled in by the custom executors proposal) to reserve the name and give a place where we can hang the Sendable
conformance. If we add runOnActor
, that's where we would do it.
Doug