Calling though `super` ==

There seems to be no way to call the autosynwthesized EQ / hash implementation from within a custom implementation:

static func == (lhs: Self, rhs: Self) -> Bool {
    // pseudo code:
    var result = "original authosynthesized eq" (lhs, rhs)
    ....
    return result
}
func hash(into hasher: inout Hasher) {
    // pseudo code:
    "original authosynthesized hash" (into: hasher)
    ....
}

Currently as a workaround I either implement EQ/hash manually (the obvious risk is adding new fields and forgetting adding them in the EQ/hash methods), or when the structure is too big and it would be too painful doing EQ/hash manually I wrap the struct:

struct Wrapper: Hashable {
    var bs: BigStruct // Hashable

    static func == (lhs: Self, rhs: Self) -> Bool {
        var result = lhs.bs == rhs.bs
        ....
        return result
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(bs)
        ....
    }
}

with the downside that now I need to use "variable.bs.field" instead of just "variable.field". Which in theory I can further "fix" by having a multitude of:

struct Wrapper: Hashable {
    var bs: BigStruct
    ...
    var foo: T {
       get { bs.foo }
       set { bs.foo = newValue }
    }
    var bar: T {
       get { bs.foo }
       set { bs.foo = newValue }
    }
    func baz(....) { bs.baz(....) }
}

which would be rather painful.

Is this something property wrappers can help with?

You could use dynamic member lookup to make the property access less painful:

@dynamicMemberLookup struct Wrapper: Hashable {
    var bs: BigStruct
    subscript<T>(dynamicMember keyPath: WritableKeyPath<BigStruct, T>) -> T {
        get { bs[keyPath: keyPath] }
        set { bs[keyPath: keyPath] = newValue }
    }
}

I don't think this is possible through a property wrapper alone, unless you limit yourself to _x == _y rather than x == y.

1 Like