Do you mean something like this, then?

```
struct Foo: Equatable {
  let x: Int
}

func test<T: Equatable>(_ lhs: T, _ rhs: T) -> Bool {
  return lhs == rhs
}

extension Foo {
  static func == (lhs: Foo, rhs: Foo) -> Bool {
    return lhs.x % 2 == rhs.x % 2
  }
}

print(test(Foo(x: 5), Foo(x: 7)))  // true
```

That seems to work.

I just tested the Annoying example as well and yes, the version from the
Annoying extension is what gets called in my implementation.

I agree with you that that seems like the correct behavior—the manually
written version takes precedence over the synthesized version, even though
it comes from a different protocol extension; synthesized versions should
always be the last resort because they're not controlled by the user,
correct?

This also seems consistent with the way regular methods are resolved if we
take synthesis completely out of the equation:

```
protocol Fooquatable {
  static func foo(lhs: Self, rhs: Self) -> Bool
}

protocol Annoying {}
extension Annoying {
  static func foo(lhs: Self, rhs: Self) -> Bool {
    print("annoying")
    return true
  }
}
struct Foo: Fooquatable, Annoying {
  let x: Int
}

func foo<T: Fooquatable>(_ lhs: T, _ rhs: T) -> Bool {
  return T.foo(lhs: lhs, rhs: rhs)
}

print(foo(Foo(x: 5), Foo(x: 6)))  // annoying, true
```

Does this seems reasonable? (Assuming I'm testing the right thing. :)


On Thu, Aug 10, 2017 at 2:58 PM Jordan Rose <jordan_r...@apple.com> wrote:

>
>
> On Aug 10, 2017, at 14:48, Tony Allevato <tony.allev...@gmail.com> wrote:
>
> On Thu, Aug 10, 2017 at 11:05 AM Jordan Rose <jordan_r...@apple.com>
> wrote:
>
>> [Proposal:
>> https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md
>> ]
>>
>> Hi, Tony. Glad to see this back again!
>>
>> Overall I'm an enthusiastic +1. The restrictions and future work you've
>> listed make sense, and I think this is the right starting place. I just
>> have one thing I'd want to clarify:
>>
>> Any user-provided implementations of == or hashValue will override the
>> default implementations that would be provided by the compiler.
>>
>>
>> Does this include implementations in (possibly constrained) protocol
>> extensions? I assume yes, but that's probably worth calling out explicitly.
>> Still, it could be confusing to some users.
>>
>
> Yes, manual implementations added in extensions override the
> compiler-synthesized default:
>
> Without constraints:
> (swift) struct Foo: Equatable { let x: Int }
> (swift) Foo(x: 5) == Foo(x: 6)
> // r0 : Bool = false
> (swift) Foo(x: 5) == Foo(x: 5)
> // r1 : Bool = true
> (swift) extension Foo { static func ==(lhs: Foo, rhs: Foo) -> Bool {
> return lhs.x % 2 == rhs.x % 2 } }
> (swift) Foo(x: 5) == Foo(x: 6)
> // r2 : Bool = false
> (swift) Foo(x: 5) == Foo(x: 7)
> // r3 : Bool = true
>
> With constraints:
> (swift) struct Foo<T: Equatable>: Equatable { let t: T }
> (swift) extension Foo where T == String { static func ==(lhs: Foo<T>, rhs:
> Foo<T>) -> Bool { return lhs.t.characters.count == rhs.t.characters.count }
> }
> (swift) Foo(t: "foo") == Foo(t: "bar")
> // r0 : Bool = true
> (swift) Foo(t: 5) == Foo(t: 7)
> // r1 : Bool = false
>
> I can update the text to make this explicit.
>
>
> Ah, that's not quite the example I meant, *and* your example isn't a
> correct demonstration for the REPL. If you want to test the == that's used
> in the Equatable conformance, you have to call a function that's generic on
> Equatable.
>
> Anyway, this is the example I meant:
>
> protocol Annoying {}
> extension Annoying {
>
>   static func ==(lhs: Self, rhs: Self) -> Bool {
>
>     print("annoying")
>     return true
>   }
> }
> struct Foo: Equatable, Annoying {
>   let x: Int
> }
> print(Foo(x: 5) == Foo(x: 6))
>
>
> I think the correct behavior here is to call the version from Annoying,
> but I can also see how that would be surprising.
>
> Jordan
>
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to