Back to questionsWhen does Swift synthesize
MiddleCodeCommon
When does Swift synthesize Equatable/Hashable, and when must you write ==/hash(into:) by hand?
You have a User model with an id, a name, and a lastSeen date. Two users are the same when their id matches, regardless of the other fields.
Requirements:
- Make
Userconform toEquatableandHashable. - Base both equality and hashing on
idonly. - Do not rely on compiler synthesis, which would compare every stored property.
struct User {
let id: UUID
var name: String
var lastSeen: Date
// add the conformance here
}Write the == and hash(into:) implementations.
Swift synthesizes Equatable/Hashable when every stored property conforms and you declare it in the type's file. Write them by hand when equality should ignore fields — compare only id in == and feed just id to hash(into:).
- Thinking synthesis still works when a stored property doesn't conform
- Feeding different fields to
==andhash(into:), breaking the hash contract - Believing you must always write both by hand
- Why must equal values always produce equal hashes?
- Where must the conformance be declared for synthesis to kick in?
Equality and hashing are keyed on id alone:
extension User: Equatable, Hashable {
static func == (lhs: User, rhs: User) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}Compiler synthesis would compare and hash name and lastSeen too, so the same user with a newer lastSeen would count as different. Feeding only id to both methods keeps the core contract intact: equal values must produce equal hashes, and here both derive from id alone.