<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br><br>Sent from my iPad</div><div><br>On Sep 7, 2017, at 7:45 AM, Tony Allevato <<a href="mailto:tony.allevato@gmail.com">tony.allevato@gmail.com</a>> wrote:<br><br></div><blockquote type="cite"><div>Right, let's make sure we're talking about the right thing here. Gwendal, your issue isn't with synthesis in the form of Codable or the new additions to Equatable/Hashable which are opt-in-by-conformance, it's with the specific case of raw value enums or enums without associated values where the synthesis is implicit with no way to opt-out. That's a big difference.<br><br>I can definitely see the latter being an issue if it were more widespread, and I'd be supportive of those enums being required to declare their conformance for consistency (though it would be source breaking).<br></div></blockquote><div><br></div><div>Ahh, thanks for clearing that up Tony. I missed this. I agree that this could be problematic in some cases (as Gwendal found) and should be fixed. Now that we have a well established model for synthesis we should follow it consistently.</div><br><blockquote type="cite"><div><br>However, I still haven't seen a real issue that has come up because of the distinction being drawn here between default implementations vs. implementations that can access other parts of the concrete type. It sounds like this discussion is trying to protect against a hypothetical problem that hasn't happened yet and may not happen; it would be helpful to show some motivating real-world cases where this is indeed a severe problem.<br><div class="gmail_quote"><div dir="ltr">On Thu, Sep 7, 2017 at 5:37 AM Matthew Johnson via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div><br><br>Sent from my iPad</div></div><div dir="auto"><div><br>On Sep 7, 2017, at 7:07 AM, Gwendal Roué via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><div>Hello,</div><div><br></div><div>I'm interested in this debate because I've been bitten by automatic synthesis recently.</div><div><br></div><div>I'm reading your discussion, but I don't have a strong opinion. I only have an anecdote: implicit, automatic, and unavoidable code synthesis code can make it difficult to write some DSLs (aka Domain-Specific Languages).</div><div><br></div><div>I did stumble against undesired Equatable synthesis while developping a library[1] that generates SQL snippets. In this library, the `==` operator does not return a Bool: it returns an SQL expression:</div><div><br></div><div><span class="m_-3639262533266496105Apple-tab-span" style="white-space:pre-wrap">        </span>// SELECT * FROM players WHERE bestScore = 1000</div><div><span class="m_-3639262533266496105Apple-tab-span" style="white-space:pre-wrap">        </span>Player.filter(bestScore == 1000)</div><div><br></div><div>Since the library is free to define == as an operator that returns an SQL expression, this works quite well. Even when both operands have the same type:</div><div><br></div><div><div><span class="m_-3639262533266496105Apple-tab-span" style="white-space:pre-wrap">        </span>// SELECT * FROM players WHERE lastScore = bestScore</div><div><span class="m_-3639262533266496105Apple-tab-span" style="white-space:pre-wrap">        </span>Player.filter(lastScore == bestScore)</div></div><div><br></div><div>However, as soon as the type is (also) Equatable, an ambiguity occurs, and the DSL is basically broken:</div><div><br></div><div><span class="m_-3639262533266496105Apple-tab-span" style="white-space:pre-wrap">        </span>Player.filter(lastScore == bestScore) // which == please?</div><div><br></div><div>In this case, the == from synthesized Equatable conformance is not welcome at all. It prevents the library from controlling the return type of the == operator. Equatable conformance is unavoidable for enums based on String or generally any raw value type that adopts Equatable. The consequence is that my library can't allow its users to define an enum of table columns.</div><div><br></div><div>This is not a deal breaker. Everybody can live with this little caveat, and I guess I'm the only one who wishes things had been more *consistent*. But still: this story helps realizing that code synthesis can bite in plenty of unexpected ways.</div></div></blockquote><div><br></div></div><div dir="auto">I don't understand what this has to do with synthesized Equatable. Wouldn't manually implemented Equatable have the same impact? The design of a DSL should be able to accommodate conformance to basic protocols without ambiguity.<div><br></div><div>We generally want as many types to be Equatable and Hashable as possible. Synthesized conformance means more types will have these conformance and that's a good thing in all cases (so long as the implementation is correct). </div></div><div dir="auto"><div><div><br><blockquote type="cite"><div><div><br></div><div>Thanks for reading,</div><div>Gwendal Roué</div><div>[1] <a href="http://github.com/groue/GRDB.swift" target="_blank">http://github.com/groue/GRDB.swift</a></div><br><div><blockquote type="cite"><div>Le 7 sept. 2017 à 12:20, Haravikk via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> a écrit :</div><br class="m_-3639262533266496105Apple-interchange-newline"><div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite"><div><br class="m_-3639262533266496105Apple-interchange-newline">On 7 Sep 2017, at 00:11, Brent Royal-Gordon <<a href="mailto:brent@architechies.com" target="_blank">brent@architechies.com</a>> wrote:</div><br class="m_-3639262533266496105Apple-interchange-newline"><div><div style="word-wrap:break-word"><div><blockquote type="cite"><div>On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_-3639262533266496105Apple-interchange-newline"><div><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">This proposal idea is essentially for a new attribute @synthetic (name is up for debate). This attribute is required for any default implementation that includes reflective type compiler magic, use of the reflection API against `self` or, in future, any native Swift macros within the method (possibly limited to specific features, will depend on the macro language and its capabilities).</span></div></blockquote></div><div><br></div><div>"Use of the reflection API against `self`"? `String(describing:)` and `String(reflecting:)` sometimes do that.</div><div><br></div><div>I see zero justification for having @synthetic cover all of these random things, but not ordinary default implementations—they have the same amount of dangerous implicitness.</div></div></div></blockquote><br></div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Actually they don't; the problem here is that through reflection you are accessing and manipulating concrete types. A non-reflective default implementation<span class="m_-3639262533266496105Apple-converted-space"> </span><b>only</b> has access to what the protocol itself has defined. The synthetic alternatives are instead diving into parts of a concrete type that may have nothing to do with the protocol at all, and must therefore make assumptions that cannot be guaranteed to be correct, this is what makes them dangerous.</div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><blockquote type="cite"><div>On 6 Sep 2017, at 23:43, Nevin Brackett-Rozinsky <<a href="mailto:nevin.brackettrozinsky@gmail.com" target="_blank">nevin.brackettrozinsky@gmail.com</a>> wrote:</div><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote type="cite">On Wed, Sep 6, 2017 at 5:42 PM, Haravikk via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">the issue I'm trying to raise is that when those, and similar features, are used in synthesised behaviour (default implementations based upon the concrete type), that these behaviours should be opted into explicitly, otherwise they open up potential for all kinds of bugs, even when the assumptions being made about the concrete type are simple such as in the case for Equatable/Hashable. There's just too much potential for this kind of reflective protocol implementation to overreach; to me it feels very much like going into a restaurant and the waiter coming across and force-feeding me something I don't want instead of taking my order.<br></blockquote></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="m_-3639262533266496105HOEnZb"><div class="m_-3639262533266496105h5"></div></div></blockquote></div></div><div class="gmail_extra">I might suggest that instead it is like you have gone into a pizza shop and said, “I’d like a large veggie pizza please.” And they made you a pizza with their standard dough and their standard sauce and their standard cheese and their standard selection of vegetables.</div></div></div></blockquote><br></div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">Actually I don't think that's quite it either; to strain the analogy even further, I'd say it's more like going into a pizza shop and saying "I'd like a pizza" and the staff looking at you and deciding you look like a vegetarian and giving you a vegetarian pizza.</div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">The crux of the issue here are the assumptions that are being made; for a standard default implementation there are no assumptions, because you're operating on the basis of methods and properties that you yourself have defined as the protocol creator that, where properly implemented, have precisely defined requirements, behaviours etc. When you're doing it with some form of compile-time or run-time reflection however you're messing around with parts of a concrete type that the protocol itself doesn't actually know anything about with any certainty.</div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">It's the same reason that run-time reflection isn't something you should ever want to do, because while it might work with all of the types you test directly, if it supports arbitrary types (which it'd need to, or there'd be no point to reflecting) then there's always the risk of encountering a type where some part of it doesn't match the assumptions that you've made. Of course there are use-cases where this may not matter, e.g- if you're just dumping data from a type and don't really care if you're storing stuff that isn't important, but in other cases such as Equatable and Hashable it<span class="m_-3639262533266496105Apple-converted-space"> </span><b>can</b> make a difference, as it can drastically affect behaviour when those assumptions fail.</div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><br></div><div style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div></div><blockquote type="cite">On 7 Sep 2017, at 05:00, Andrew Thompson <<a href="mailto:mrwerdo331@me.com" target="_blank">mrwerdo331@me.com</a>> wrote:</blockquote><font color="#5856d6"><blockquote type="cite">Perhaps we could find a solution by meeting in the middle. Introduce a compiler flag that will disable the automatic synthesis and revert to the old behaviour (i.e. swiftc main.swift —disable-automatic-synthesis )</blockquote><br></font><div><div><div name="messageBodySection"><div style="margin:0px;line-height:normal;font-family:'Helvetica Neue';color:rgb(51,51,51)">Thanks for the suggestion, but that's a bit too all-or-nothing; I realise I might seem very negative but to be clear, I<span class="m_-3639262533266496105Apple-converted-space"> </span><b>do</b> want these synthesised features, I just don't want them in their current form. What I want is for them to be explicitly opted into where I, as the developer, need them to be, so that I'm in absolute, unambiguous control of when and where they are used.</div><div style="margin:0px;line-height:normal;font-family:'Helvetica Neue';color:rgb(51,51,51)"><br></div><div style="margin:0px;line-height:normal;font-family:'Helvetica Neue';color:rgb(51,51,51)">I do absolutely support features that eliminate tedious boiler-plate, I just think that doing so implicitly in invasive ways is not the right way to do it.</div></div><div name="messageReplySection" style="font-size:14px;font-family:-apple-system,BlinkMacSystemFont,sans-serif"><div></div></div></div></div></div><span style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">_______________________________________________</span><br style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><span style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important">swift-evolution mailing list</span><br style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><a href="mailto:swift-evolution@swift.org" style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank">swift-evolution@swift.org</a><br style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></div></div>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div>
</div></blockquote></body></html>