Hashable Actors

Say I have an actor that I want to conform to Hashable, and this is possible because its identity and hash value derive from nonisolated lets:

actor MyActor: Hashable {
    let id: UUID

    nonisolated func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
    
    nonisolated static func == (lhs: MyActor, rhs: MyActor) -> Bool {
        return lhs.id == rhs.id
    }
}

When compiling I get an error:
Property 'hashValue" can not satify corresponding requirements from protocol 'Hashable'

So I have to add the deprecated declaration for that too:

nonisolated var hashValue: Int {
    return id.hashValue
} 

Is this really the recommended way to do this? Can the code synthesizer not be smarter here?

2 Likes

I don't think there is a documented recommendation anywhere, but if we look at the Source Compatibility section of SE-206, it's probably better to write it like this:

nonisolated var hashValue: Int {
    var hasher = Hasher()
    self.hash(into: &hasher)
    return hasher.finalize()
}

so you get to use the new Hasher-based hashing.

I think the compiler should be smarter here, and it's worth filing a bug report for it.

4 Likes

filed SR-15432

1 Like

This was fixed via Make derived hashValue/hash(into:) nonisolated. by DougGregor ยท Pull Request #38620 ยท apple/swift ยท GitHub but hasn't made it into a release.

5 Likes
Terms of Service

Privacy Policy

Cookie Policy