# \[Pitch #4\] Actors

**URL:** <https://forums.swift.org/t/pitch-4-actors/45215>\
**Category:** Pitches\
**Created:** [March 2, 2021, 7:55am UTC](https://forums.swift.org/t/pitch-4-actors/45215 "2021-03-02T07:55:32Z")\
**Posts on this page:** 1\
**Showing post:** 42

<div class="post-metadata">

**Author:** ![Chris\_Lattner3](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/chris_lattner3/32/348_2.png) [@Chris\_Lattner3](https://forums.swift.org/u/Chris_Lattner3)\
**Post date:** [March 10, 2021, 5:49am UTC](https://forums.swift.org/t/pitch-4-actors/45215/42 "2021-03-10T05:49:12Z")

</div>

> [@Douglas\_Gregor](#):
>
> I've made a bunch of changes on the road to a "pitch #5", based on feedback here.

Even more great updates, nice work!

> [@Douglas\_Gregor](#):
>
> Add the `Actor` protocol back, as an empty protocol whose details will be filled in with a subsequent proposal for [custom executors][customexecs].

Cool. Is there a specific preference for the name `Actor`? It seems more natural to follow the established precedent of [`AnyClass`](https://developer.apple.com/documentation/swift/anyclass) "The protocol to which all class types implicitly conform.", `AnyHashable` "A type-erased hashable value." etc, and the `Any` protocol composition. The word `Any` is the unifying term for a "type erased thingy" in Swift regardless of whether that type erased thingy is a protocol (as in `AnyClass`), a structure or protocol composition. I think that aligning with `AnyClass` is itself enough reason to name it `AnyActor`.

Other random comments:

- I still don't understand why we'd introduce language complexity for `nonisolated(unsafe)` proactively, particularly when this can be handled in the library. It seems better to exclude this from the first proposal and add it when other parts of the model get baked out.
- Don't feel compelled to include the "Isolated or sync actor types" discussion in the alternative considered section, I am not at all advocating that.
- I see your subsequent post (and respond below) but I still consider it a showstopper if actors can't interact with the protocol and generics subsystem in a way that composes with implementation mixins, standard protocol oriented programming, and other things. Breaking this unifying theory across the language will manifest it significant complexity over the evolution of Swift and force programmers into weird design patterns (e.g. putting all their logic into a struct and then having a boilerplate actor wrapper that forwards the public API). We should fix the fundamental issues here, I'm happy to see you are continuing to explore this.

> [@Douglas\_Gregor](#):
>
> From my perspective, the proposal is not complete without `nonisolated` , and my read of the situation is that there is [no actual disagreement about whether `nonisolated` is a good idea](https://forums.swift.org/t/pitch-4-actors/45215/24), or it's semantics, or even it's spelling (now).

I disagree with your assessment. It isn't clear how much of the motivation for `nonisolated` would be satisfied with other facilities that we need to bake out anyway for basic protocol support, and by library support for breaking out of isolation in both safe and unsafe ways. None of this has been baked out, so a claim that `nonisolated` is required doesn't seem supported.

Furthermore, defaulting protocol conformance syntax to nonisolated conformances seems very wrong to me. Actors are all about isolation: you should have to _opt in_ to non-isolation (e.g. `actor X : nonisolated Hashable` or whatever). For this reason, I don't agree that the `nonisolated` proposal as written will allow the correct thing to be added later.

> [@Douglas\_Gregor](#):
>
> Yes, the proposal would be somewhat smaller without it,

Without it, it would be completely obvious that the proposal is insufficient for isolation, which is what actors are all about. You'd be proposing a nominal type with no support for protocols with sync requirements, making it obvious that the sync implementation logic of actors cannot be abstracted and genericized.

> [@Douglas\_Gregor](#):
>
> but at the cost of having yet another concurrency proposal that scatters the knowledge further. It fits well alongside `isolated` parameters to have the modifier that disables the implicit `isolated` on `self` . If we rewound the clock to the pre-Swift 1.0 days, could we imagine introducing `inout` without also introducing `mutating` ?

First, we already have a lot of proposals so one more isn't actually that onerous. Second, isolated self _does_ go with the base actor proposal since it is fundamental to the nature of self in an actor and has nothing to do with the `nonisolated` proposal. This is a point of confusion that would be immediately more clear if you split out the `nonisolated` proposal. This is what I mean about the `nonisolated` proposal confusing the core model.

> [@Douglas\_Gregor](#):
>
> The actual disagreement, as I understand it, is whether another feature, called isolated conformances in the future directions of this proposal, is also a critical part of the model. We have neither a set of agreed-upon examples nor a complete design to evaluate that feature. My own experience is that I have not needed this feature. We should keep exploring it further, but we shouldn't hold up progress on actors themselves waiting for it.

If you are serious about that, then please split out the `nonisolated` concepts to its own follow-on proposal and we can evaluate the "isolated" features of actors without it, then evaluate the `nonisolated` features and the details of the additions based on its own motivation. This splits the motivation sections for the two proposals, since they really have two different things going on.

* * *

It is perhaps the wrong time to discuss this, but I think that the word `isolated` for "actor self" is confusing regardless of what happens with `nonisolated`. The thing we want to convey here is that a function has "direct" access (as opposed to async/mailbox access) to the actor its argument is bound to -- we're not saying that the actor /type/ is `nonisolated`.

I'm really not sure what the right spelling of this is though, you could imagine several yucky options like:

- `func f(a: direct YourActor)`
- `func f(a: nonmailbox YourActor)`
- `func f(a: within YourActor)`

etc. `nonisolated` conveys that you've got an actor that doesn't obey the isolation rules, which is not what is going on. Does anyone else have a good suggestion here?

* * *

> [@Douglas\_Gregor](#):
>
> Maybe we can get to a shared understanding without asking you to write another white paper.

Thank you 🙌

> [@Douglas\_Gregor](#):
>
> Let's ignore all of the conformances to existing protocols from the white paper: `Sequence` , `Iterator` , `Equatable` , etc., I think that means we're focusing in on `DataProcessible` :

Sounds good. Yes, `DataProcessible` is an example that is using protocol extensions to share implementation logic across actors and other types. This is one of the key things that draft 5 is lacking.

> [@Douglas\_Gregor](#):
>
> I _think_ you might be saying something here that is fundamentally different from what's in the white paper.

Correct, I was intentionally trying to narrow the conversation in the P0 thing that I feel need to be covered, excluding 'nice to have' things that should fall out but don't "need to".

The thought process in the whitepaper is that protocols allow sharing logic and abstracting across enums/structs, as well as across enums/structs/classes in some more narrow cases. It would be odd if protocols couldn't do that at least across reference types like class/actor. That said, to reiterate, this is lower priority than allowing actors with isolated sync methods to conform to protocols that have sync requirements. I agree that actors are different in that the "client interface" and "internal interface" side of actors are unique to them.

> [@Douglas\_Gregor](#):
>
> So here's a question for you. Let's say that `DataProcessible` looks like this:
> 
> ```swift
> public protocol DataProcessible: Actor {
> var data: Data { get }
> }
> 
> ```
> 
> ...  
> the type of `compressData` is `<Self: Actor> (isolated Self) -> () -> Data` , i.e., it's a synchronous function running on the actor.

Yes, this is covering the major case I care about, this is a very promising direction to explore. Does this work with existentials? What happens when you have hierarchies like:

```swift
protocol P {...}
protocol Q : P, Actor {...}

```

?

How do associated types work?

How does this work when you want to abstract across the "external view" of an actor which is all async?

Depending on the answers above, it might be useful to think about this direction as a "different kind of protocol" which would be more naturally spelled like `actor protocol P {` or `@actor protocol P {`. The concern here is that "actor" is too broad of a word for this property though, since it speaks to whatever the internal implementation details of an actor are, not all actors uniformly. I suspect that this concept will be more closely aligned with the 'self' keyword, e.g. `nonmailbox protocol P{` or whatever.

> [@Douglas\_Gregor](#):
>
> However, this would not allow, e.g.,
> 
> ```swift
> class MyOldProcessor : DataProcessible { // error: MyOldProcessor is not an actor
> var data: Data
> }
> 
> ```

Right. This seems expendable if we get the basic abstraction functionality in place for actors. It comes at the cost of forking the protocol world, but that is better than not supporting this at all.

> [@Douglas\_Gregor](#):
>
> Does the above, where you can write synchronous protocols that work across actor types but cannot be conformed-to by non-actor types, address your concerns about "generics, protocol extensions, and PoP patterns [working] across actors"?

Yep, this is going in the right direction, thank you for exploring this!

-Chris

---

_[View the full topic](https://forums.swift.org/t/pitch-4-actors/45215)._
