<div dir="ltr"><div>Do you mean something like this, then?</div><div><br></div><div>```</div><div><div>struct Foo: Equatable {</div><div>  let x: Int</div><div>}</div><div><br></div><div>func test&lt;T: Equatable&gt;(_ lhs: T, _ rhs: T) -&gt; Bool {</div><div>  return lhs == rhs</div><div>}</div><div><br></div><div>extension Foo {</div><div>  static func == (lhs: Foo, rhs: Foo) -&gt; Bool {</div><div>    return lhs.x % 2 == rhs.x % 2</div><div>  }</div><div>}</div><div><br></div><div>print(test(Foo(x: 5), Foo(x: 7)))  // true</div></div><div>```</div><div><br></div><div>That seems to work.</div><div><br></div>I just tested the Annoying example as well and yes, the version from the Annoying extension is what gets called in my implementation.<div><br></div><div>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&#39;re not controlled by the user, correct?</div><div><br></div><div>This also seems consistent with the way regular methods are resolved if we take synthesis completely out of the equation:</div><div><br></div><div>```</div><div><div>protocol Fooquatable {</div><div>  static func foo(lhs: Self, rhs: Self) -&gt; Bool</div><div>}</div><div><br></div><div>protocol Annoying {}</div><div>extension Annoying {</div><div>  static func foo(lhs: Self, rhs: Self) -&gt; Bool {</div><div>    print(&quot;annoying&quot;)</div><div>    return true</div><div>  }</div><div>}</div><div>struct Foo: Fooquatable, Annoying {</div><div>  let x: Int</div><div>}</div><div><br></div><div>func foo&lt;T: Fooquatable&gt;(_ lhs: T, _ rhs: T) -&gt; Bool {</div><div>  return T.foo(lhs: lhs, rhs: rhs)</div><div>}</div><div><br></div><div>print(foo(Foo(x: 5), Foo(x: 6)))  // annoying, true</div></div><div>```</div><div><br></div><div>Does this seems reasonable? (Assuming I&#39;m testing the right thing. :)</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Aug 10, 2017 at 2:58 PM Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com">jordan_rose@apple.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><br><div><br><blockquote type="cite"><div>On Aug 10, 2017, at 14:48, Tony Allevato &lt;<a href="mailto:tony.allevato@gmail.com" target="_blank">tony.allevato@gmail.com</a>&gt; wrote:</div><br class="m_-8169050703577354051Apple-interchange-newline"><div><div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Thu, Aug 10, 2017 at 11:05 AM Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" target="_blank">jordan_rose@apple.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div>[Proposal: <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md</a>]</div><div><br></div>Hi, Tony. Glad to see this back again!<div><br></div><div>Overall I&#39;m an enthusiastic +1. The restrictions and future work you&#39;ve listed make sense, and I think this is the right starting place. I just have one thing I&#39;d want to clarify:</div><div><br></div><div><blockquote type="cite">Any user-provided implementations of == or hashValue will override the default implementations that would be provided by the compiler.<br></blockquote><br>Does this include implementations in (possibly constrained) protocol extensions? I assume yes, but that&#39;s probably worth calling out explicitly. Still, it could be confusing to some users.<br></div></div></blockquote><div><br></div><div>Yes, manual implementations added in extensions override the compiler-synthesized default:</div><div><br></div><div>Without constraints:</div><div><div>(swift) struct Foo: Equatable { let x: Int }</div><div>(swift) Foo(x: 5) == Foo(x: 6)</div><div>// r0 : Bool = false</div><div>(swift) Foo(x: 5) == Foo(x: 5)</div><div>// r1 : Bool = true</div><div>(swift) extension Foo { static func ==(lhs: Foo, rhs: Foo) -&gt; Bool { return lhs.x % 2 == rhs.x % 2 } }</div><div>(swift) Foo(x: 5) == Foo(x: 6)</div><div>// r2 : Bool = false</div><div>(swift) Foo(x: 5) == Foo(x: 7)</div><div>// r3 : Bool = true</div></div><div><br></div><div>With constraints:</div><div><div>(swift) struct Foo&lt;T: Equatable&gt;: Equatable { let t: T }</div><div>(swift) extension Foo where T == String { static func ==(lhs: Foo&lt;T&gt;, rhs: Foo&lt;T&gt;) -&gt; Bool { return lhs.t.characters.count == rhs.t.characters.count } }</div><div>(swift) Foo(t: &quot;foo&quot;) == Foo(t: &quot;bar&quot;)</div><div>// r0 : Bool = true</div><div>(swift) Foo(t: 5) == Foo(t: 7)</div><div>// r1 : Bool = false</div></div><div><br></div><div>I can update the text to make this explicit.</div></div></div></div></blockquote><br></div></div><div style="word-wrap:break-word;line-break:after-white-space"><div>Ah, that&#39;s not quite the example I meant, <i>and</i> your example isn&#39;t a correct demonstration for the REPL. If you want to test the == that&#39;s used in the Equatable conformance, you have to call a function that&#39;s generic on Equatable.</div><div><br></div><div>Anyway, this is the example I meant:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>protocol Annoying {}</div><div>extension Annoying {</div></blockquote></div><div style="word-wrap:break-word;line-break:after-white-space"><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>  static func ==(lhs: Self, rhs: Self) -&gt; Bool {</div></blockquote></div><div style="word-wrap:break-word;line-break:after-white-space"><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>    print(&quot;annoying&quot;)</div><div>    return true</div><div>  }</div><div>}</div><div>struct Foo: Equatable, Annoying {</div><div>  let x: Int</div><div>}</div><div>print(Foo(x: 5) == Foo(x: 6))</div></blockquote><div><br></div><div>I think the correct behavior here is to call the version from Annoying, but I can also see how that would be surprising.</div></div><div style="word-wrap:break-word;line-break:after-white-space"><div><br></div><div>Jordan</div><br></div></blockquote></div>