Thanks Doug, no problem. I appreciate your time here. I'll likewise just do a quick point by point recap, but I agree that this is probably not the most conducive way to get to convergence.
That is a helpful step and I'm in favor of it or something like it, but the current approach is a big fork for the universe, and the subsequent AsyncSequence proposals are further unzipping the world, e.g. by adding Zipped, Enumerated, etc async clones of the sync types. This is all follow-on from the first async clone of a protocol, I'm concerned that this will play itself out across the ecosystem. We'll see though, there are many balls in the air so it is difficult to see how they all land.
But values have types. Encoding this behavior into a type (whether or not it is a first class type, or a parameter-only type like "inout") is strictly more powerful than being value driven. Perhaps I don't understand your meaning of "cannot".
I agree that the unsafe things are orthogonal, however, the nonisolated proposal does two things in the proposal: 1) it is the basis for a pretty problematic model for protocol conformance by actors, and 2) it is a sugary feature that allows eliminating some awaits in some cases.
I feel that we really need to address #1 somehow, and once we do that, I personally don't think that #2 is worth the complexity added to the language to support it.
Agreed, that would be a strict improvement.
As I mentioned, I'm generally infavor of something like reasync, but Slava has pointed out on other threads one major concern with this approach: unlike rethrows, there isn't a really good implementation strategy for reasync. Code with the "reasync" ABI has to support suspension, and calling into code that supports suspension from code that doesn't is... tricky. I'm not at all an expert on these codegen details though, so I hope this is solvable.
Yes, I can see your point about this being helpful modeling tool in some cases where you're dealing with a lot of immutable state in an actor. Here are my major concerns with this:
-
With the ConcurrentValue proposal, we will have a safe way to share bags of immutable state across actors: you can just have a final class with a bunch of lets in it.
-
The protocol model proposed on top of nonisolated is very concerning to me, because it doesn't support protocol extensions in a consistent way with the rest of Swift.
-
There is a lot of conceptual complexity introduced by nonisolated that would be nice to avoid if possible.
Personally, my priority is to get the protocol conformance situation squared away, that is my #2 goal and priority for the actor design now (#1 was memory safety with ConcurrentValue etc). My belief is that solving that problem has nothing to do with nonisolated. If that is the case, then nonisolated will just be a sugaring that allows avoiding some awaits in some narrow cases -- it seems like something that could be punted to a later proposal in that case.
Regardless, I'm very happy to see nonisolated(unsafe) go away (as you mention above) and for us to focus on the protocol design. If we can get to a reasonable design for protocol based abstraction, then we can see whether nonisolated holds its weight afterward.
While I agree that we need the ability to unsafely poke into mutable actor internal for the model to be fully baked, I don't think it would be acceptable to require its use to conform the general protocols. Said in a different way, protocol conformance / abstraction shouldn't require unsafe code, even if we allow it for advanced uses.
I think you and I are agreeing about the "we cannot require unsafety for protocol conformance" which is great. I would love to learn more why you don't think this approach provides safety though - it all composes and stacks out as far as I can see. If you have something specific in mind, I'd love to learn about it.
Perhaps we're talking across each other here, but "type directed" doesn't say anything about the number of values that conform to the type. I agree with you that the above can only make sense if a === b or a and b share the same serial executor.
The reason this is useful is explained in other parts of the paper. The one case where "this example" is conceptually useful is if you (as a Swift programmer) know that you have two actors that share the same serial executor and do an unsafe cast to a sync reference. Such a property is absolutely possible with John's custom executor proposal, and having a way to work with such situations seems useful.
Right.
I don't understand what this means. Can you please explain with an example instead of just stating this?
Right, I agree that this is a very important operation and that it isn't supported without something like @sync actors. I feel like you're agreeing here, but I'm not sure given how you're wording this and arguing against specific examples as "not too motivating" above. For clarity, my rationale for giving many different examples was to illustrate how the type system composes and works out: it wasn't to prove all the small examples are "motivating" or "useful".
Agreed, I think this would be a strict progression.
The white paper also mentions that the Equatable example isn't actually very useful. However, your statement above shows exactly why such a thing "theoretically could" be useful: we allow actor instances to be pinned to the same serial executor, and should support unsafe casts so the programmer can tell the language about that. In such a world, you'd have multiple instances of a @sync actor type floating around. I don't think this would be widely utilized, but for code that does this, we should provide the ability to work with this in a memory safe way.
That said, to reiterate, I included the Equatable example to show how the type system mechanics work, I don't think it this is a generally useful thing to do for reasons stated in the paper.
Coming back to the top of the writeup, I would see it as good progress if nonisolated(unsafe) were to go away. I would really love to know your thoughts about the protocol conformance and abstraction problems discussed in the motivation section. I consider them to be a showstopper for the actors design.
Once that gets addressed, my objection to nonisolated is just that it adds a bunch of complexity for incremental expressive value. It seems like something that could be punted to a future proposal or a future release of swift when we have more experience with the actor model and agree that this problem is worth addressing by adding more complexity to the language.
-Chris