Challenged yes, but not stuck!
This is well-known class of problem called a "Protocol Conformance Isolation Mismatch". In the case of a MainActor type, my personal favorite solution is a preconcurrency conformance.
@MainActor
class MyClass {
var value = 1
}
extension MyClass: @preconcurrency Equatable {
static func == (lhs: MyClass, rhs: MyClass) -> Bool {
lhs.value == rhs.value
}
}
It looks weird, because Equatable
is not actually "preconcurrency", but it expresses the semantics perfectly. It is only meaningful to compare these types when also MainActor-isolated. The ability to constrain a conformance to a specific isolation domain is so handy that this is going come to the language as an "isolated conformance". It's part of the vision document, and one I'm pretty excited about personally!
Now, for actors, the situation gets more complex. There are valid cases for conforming an actor to a protocol with synchronous requirements, but they are limited. This can also be an indication that you have reached for an actor when a non-Sendable
type is more appropriate. But those are super hard to use in combination with concurrency. Thankfully, that will also be getting way easier, via isolation inheritance changes.