Cleaning up in deinit with self, and complete concurrency checking

Applying a global actor attribute will implicitly conform a type to Sendable. Since a Sendable reference type can be freely shared across any isolation domain, its final reference could go away from any isolation domain, and thus we don't have guarantees about where deinit will be called from. There have been discussions about ways to address this, but language changes have not yet landed to support it.

To suppress the implicit Sendable conformance you could do this:

@available(*, unavailable)
extension Trampoline: Sendable {}

I think, combined with annotating the type with @MainActor should give you the guarantee of "a type which can only be created from the main actor and not transferred to another isolation domain, and so must be deinitialized from the main actor", but I am not 100% confident in my intuition here. But it looks like even with that workaround, the deinit won't recognize it statically (because my assumption is incorrect?), but you could then wrap the body of the deinit in MainActor.assumeIsolated { ... } to call main-actor-isolated functions synchronously. Note that this will crash if you are not, in fact, on the main actor.

2 Likes