<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Hi Andrew, </div><div class=""><br class=""></div><div class="">Implicitly making Tuples Hashable should be its own proposal. Take a look at the Equable Tuple proposal as a template. </div><div class=""><a href="https://github.com/apple/swift-evolution/blob/master/proposals/0015-tuple-comparison-operators.md" class="">https://github.com/apple/swift-evolution/blob/master/proposals/0015-tuple-comparison-operators.md</a></div><div class=""><br class=""></div><div class="">Thanks</div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On May 9, 2017, at 3:45 PM, Andrew Bennett via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">You state that you will not synthesise conformance for tuples, I agree with this, but if a struct or enum holds a tuple it would be nice if it could be hashed if its members are all hashable.</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: menlo; color: rgb(4, 51, 255);" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> A {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: menlo;" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(4,51,255)" class="">var</span><span style="font-variant-ligatures:no-common-ligatures" class=""> a: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(52,149,175)" class="">Int</span><span style="font-variant-ligatures:no-common-ligatures" class="">, b: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(52,149,175)" class="">Int</span><span style="font-variant-ligatures:no-common-ligatures" class="">, c: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(52,149,175)" class="">Int</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: menlo;" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">}</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: menlo; min-height: 13px;" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: menlo; color: rgb(4, 51, 255);" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> B {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: menlo;" class=""><span style="font-variant-ligatures:no-common-ligatures" class=""> </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(4,51,255)" class="">var</span><span style="font-variant-ligatures:no-common-ligatures" class=""> tuple: (a: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(52,149,175)" class="">Int</span><span style="font-variant-ligatures:no-common-ligatures" class="">, b: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(52,149,175)" class="">Int</span><span style="font-variant-ligatures:no-common-ligatures" class="">, c: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(52,149,175)" class="">Int</span><span style="font-variant-ligatures:no-common-ligatures" class="">)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: menlo;" class=""><span style="font-variant-ligatures:no-common-ligatures" class="">}</span></div></div><div class=""><span style="font-variant-ligatures:no-common-ligatures" class=""><br class=""></span></div><div class="">I'd consider these two to be equivalent as far as this proposal is concerned, it would be nice if the proposal made that explicit.</div><div class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Tue, May 9, 2017 at 7:17 AM, Tony Allevato via swift-evolution <span dir="ltr" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class=""><br class=""><br class=""><div class="gmail_quote"><span class=""><div dir="ltr" class="">On Mon, May 8, 2017 at 2:11 PM Matthew Johnson <<a href="mailto:matthew@anandabits.com" target="_blank" class="">matthew@anandabits.com</a>> wrote:<br class=""></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" class=""><div class=""><blockquote type="cite" class=""><div class="">On May 8, 2017, at 4:02 PM, Tony Allevato <<a href="mailto:tony.allevato@gmail.com" target="_blank" class="">tony.allevato@gmail.com</a>> wrote:</div><br class="m_-4206921585179370676m_7114657150419324378Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="gmail_quote"><div dir="ltr" class="">On Sat, May 6, 2017 at 4:17 PM Chris Lattner <<a href="mailto:clattner@nondot.org" target="_blank" class="">clattner@nondot.org</a>> wrote:<br class=""></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" class="">On May 5, 2017, at 11:33 AM, Tony Allevato via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>> wrote:<br class=""></div><div style="word-wrap:break-word" class=""><div class=""><blockquote type="cite" class=""><br class="m_-4206921585179370676m_7114657150419324378m_-6169955689964255263Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><br class=""><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Can the opt-in conformance be declared in an extension? If so, can the extension be in a different module than the original declaration? If so, do you intend any restrictions, such as requiring all members of the type declared in a different module to be public? My initial thought is that this should be possible as long as all members are visible.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Declaring the conformance in an extension in the same module should definitely be allowed;</div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Please follow the precedent of the Codable proposal as closely as possible. If you’d like this to be successful for Swift 4, you should look to scope it as narrowly as possible. Because it is additive (with opt-in), it can always be extended in the future.</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_quote"><div class=""> I believe this would currently be the only way to support conditional conformances (such as the `Optional: Hashable where Wrapped: Hashable` example in the updated draft), without requiring deeper syntactic changes.</div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">This proposal doesn’t need to cover all cases, since it is just sugaring a (very common) situation. Conditional conformances to Hashable could be written manually.</div></div></div><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_quote"><div class="">I'm less sure about conformances being added in other modules,</div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">It is a bad idea, it would break resilience of the extended type.</div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""></div><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_quote"><div class="">But after writing this all out, I'm inclined to agree that I'd rather see structs/enums make it into Swift 4 even if it meant pushing classes to Swift 4+x.</div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class="">Agreed, keep it narrow to start with.</div><br class=""></div><div class="">Also, I don’t know how the rest of the core team feels about this, but I suspect that they will be reticent to take an additive proposal at this late point in the schedule, unless someone is willing to step up to provide an implementation.</div></div></blockquote><div class=""><br class=""></div><div class="">That someone is me :) I have a branch where it's working for enums (modulo some weirdness I need to fix after rebasing a two-month-old state), and adapting that logic to structs should hopefully be straightforward after that. Going with the more narrowly-scoped proposal and making conformances explicit simplifies the implementation a great deal as well (I was previously blocked with recursive types when it was implicit).</div><div class=""><br class=""></div><div class="">Thanks for the feedback—after consideration, I've pulled classes out of the proposal completely (even non-final) and mentioned the other limitations so we'd have a record of what was discussed in this thread.</div><div class=""><br class=""></div><div class="">I've created a PR for the proposal text, in the event that the core team is interested in moving this forward: <a href="https://github.com/apple/swift-evolution/pull/706" target="_blank" class="">https://github.com/<wbr class="">apple/swift-evolution/pull/706</a></div></div></div></div></blockquote><div class=""><br class=""></div></div></div><div style="word-wrap:break-word" class=""><div class="">Thanks for continuing to push this forward Tony! The current proposal looks like the right approach for getting this into Swift 4. </div><div class=""><br class=""></div><div class="">I only have one question which I will present with an example:</div><div class=""><br class=""></div><div class="">protocol Foo: Equatable {}</div><div class="">protocol Bar: Hashable {}</div><div class=""><br class=""></div><div class="">struct FooType: Foo {}</div><div class="">struct BarType: Bar {}</div><div class=""><br class=""></div><div class="">Do FooType and BarType receive synthesis?</div></div></blockquote><div class=""><span style="font-size:13px" class=""><br class=""></span></div></span><div class=""><span style="font-size:13px" class="">Great question! Yes they should. It's "explicit" transitively since the answer to "does FooType/BarType conform to Equatable/Hashable?" is still "yes". (And I've confirmed that my prototype handles this case.)</span><br class=""></div><div style="font-size:13px" class=""><br class=""></div><div class=""><span style="font-size:13px" class="">This is especially helpful since Hashable extends Equatable, so a user only needs to list conformance to the former to get correctly synthesized implementations of both, which helps to guarantee that they're implemented consistently with respect to each other.</span></div><div class=""><span style="font-size:13px" class=""><br class=""></span></div><div class=""> </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" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_quote"><div class=""><br class=""></div><div class=""> </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" class=""><div class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div><br class=""></div></blockquote></div></div>
</div></blockquote></div><br class=""></div></blockquote></div></div>
<br class="">______________________________<wbr class="">_________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
<br class=""></blockquote></div><br class=""></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>