Calling through original implementations of autogenerated methods

Reminded me of this great idea of @itaiferber.

When I conform this type:

struct S {
    var count: Int
    var contents: Data
    var capacity: Int
}

to Hashable / Equatable:

extension S: Equatable, Hashable {}

this is what I am getting by default:

// autogenerated:
extension S {
    static func == (lhs: Self, rhs: Self) -> Bool {
        (lhs.count, lhs.contents, lhs.capacity) == (rhs.count, rhs.contents, rhs.capacity) == 
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(count)
        hasher.combine(contents)
        hasher.combine(capacity)
    }
}

Unless I redefine "the essence" of the type:

extension S {
    // pseudocode
    var essence = (count, contents) // (count, contents, capacity) by default
}

in which case Equatable, Hashable will use essence:

// autogenerated:
extension S {
    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.essence == rhs.essence
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(essence)
    }
}

and in fact essence would be used in the previous example as well, it'd be just using the autogenerated essence field if it's not customised.

The followup question here is: is "essence" specific to EQ/Hashable? What about other things like Codable, should there be another "essence" field for it?

Another issue that springs to mind with the "essence" approach is that it would be error prone (you define a type and it's essence, few months later you add a new field to the type and forgot to update the essence).