<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Mon, Sep 11, 2017 at 2:05 PM Vladimir.S via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:<br>
&gt; I think I do understand Haravikk&#39;s argument (actually it seems quite straightforward<br>
&gt; to me).<br>
&gt;<br>
&gt; An example should be:<br>
&gt;<br>
&gt; struct Foo : Equatable {<br>
&gt;      var x: Int<br>
&gt;      var cachedLabel: String? = nil<br>
&gt;<br>
&gt;      init(x: Int) {<br>
&gt;          self.x = x<br>
&gt;      }<br>
&gt;<br>
&gt;      mutating func label() {<br>
&gt;          if let label = cachedLabel {<br>
&gt;              return label<br>
&gt;          }<br>
&gt;          let label = calculateLabel()<br>
&gt;          cachedLabel = label<br>
&gt;          return cachedLabel<br>
&gt;      }<br>
&gt; }<br>
&gt;<br>
&gt; var foo1 = Foo(x: 1)<br>
&gt; var foo2 = Foo(x: 1)<br>
&gt; foo1 == foo2 // true<br>
&gt; var label = foo1.label()<br>
&gt; foo1 == foo2 // now false, due to cachedString being falsely included in the comparison<br>
&gt;<br>
&gt; The problem is that the developer was not required to implement the protocol and so<br>
&gt; might forget it.<br>
&gt; The difference to other default implementations is that those use the protocol itself<br>
&gt; as building blocks and so are correct with regards to the protocol&#39;s semantics,<br>
&gt; whereas the synthesized equality reaches deeply into the private innards of a struct<br>
&gt; and therefore is much more likely to be wrong as in the example above.<br>
&gt;<br>
&gt; Why not just write<br>
&gt;<br>
&gt; *struct* Foo : *deriving* Equatable {...}<br>
&gt;<br>
&gt; to request the synthesized implementation?<br>
<br>
FWIW, +100. The same should be required for Codable. I support the opinion that<br>
&#39;synthesized&#39; methods differs from protocol-default-implementation in what &#39;kind&#39; of<br>
data they use: defined by protocol itself or internals of the conformed type. And<br>
this can lead to more un-expected problems.<br>
<br>
If protocol is able to synthesize its requirements, it should require a<br>
&#39;deriving&#39;-like marker when type conforms to it to make it absolutely clear what<br>
happens here. It would be not a confusion point, but clarify the intention to better<br>
understand the code.<br>
<br>
Thinking about *future* custom protocols that could implement requirements in default<br>
implementation by using macros/reflection, for me it seems like such protocol should<br>
*also* somehow explicitly state that some requirements are auto-synthesized, probably<br>
by conforming(derive) to some compiler-magic protocol &#39;AutoSynthesize&#39;.<br>
(i.e. &#39;protocol MySynthesizeable: AutoSynthesize {...}&#39;)<br>
<br>
So each built-in protocol like Equatable/Hashable/Codable will conform to it, and<br>
also, each custom &quot;auto-synthesizeable&quot; protocol - also should explicitly conform to<br>
AutoSynthesize. So, when type conforms to it - such type should use &#39;deriving&#39;-like<br>
marker if auto-generation of methods is expected.<br></blockquote><div><br></div><div>This doesn&#39;t align with how Swift views the role of protocols, though. One of the criteria that the core team has said they look for in a protocol is &quot;what generic algorithms would be written using this protocol?&quot; AutoSynthesize doesn&#39;t satisfy that—there are no generic algorithms that you would write with AutoEquatable that differ from what you would write with Equatable.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I also have a question regarding future direction of &#39;exclusion&#39; of fields from being<br>
included into auto-generated implementation of Equatable/Hashable/Codable/other.<br>
<br>
If we&#39;ll have this &#39;deriving&#39;-like marker, it seems naturally if we mark some member<br>
with some kind of &#39;@noderiving&#39; marker, like here:<br>
<br>
struct Foo : deriving Equatable {<br>
       var x: Int<br>
       var y: Int<br>
       var z: Int<br>
       @noderiving var cachedLabel: String? = nil<br>
}<br>
<br>
this @noderiving directive will work for protocols based on AutoSynthesize magic<br>
protocol. I.e., if you construct your own protocol with auto-synthesizeable methods,<br>
to be able to *know* which members should be &#39;excluded&#39; for your implementation, you<br>
should base your protocol on AutoSynthesize protocol.<br></blockquote><div><br></div><div>This is something I mention in the original proposal, and I agree that it would be nice to have added later since there are clear known use cases where it&#39;s important.</div><div><br></div><div>However, the feature shouldn&#39;t be tied *specifically* to derived implementations (meaning it shouldn&#39;t be named that way). What we&#39;re really talking about is &quot;transient&quot; data—data that exists for the purposes of caching/performance/etc. but which does not actually contribute to the thing&#39;s &quot;value&quot;.</div><div><br></div><div>The fact that transient data should not be ignored for equality, hashing, and serialization just happens to align with the protocols that we auto-synthesize so far, but it&#39;s not necessarily limited to those use cases. If an attribute is added for something like this, it should be *semantic* rather than speak to implementation details. In other words, it would be inappropriate to say &quot;exclude this property from synthesized operations&quot;, but it would be fine to say &quot;this property is transient data&quot; and it just so happens that Equatable, Hashable, and Codable use that information to control what they synthesize.</div><div><br></div><div>All this is a subtle, but important, distinction. One day, when Swift has the ability to introspect metadata about a type and its properties, someone may want to use a hypothetical &quot;transient&quot; attribute for something wholly unrelated to synthesis.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I hope this makes any sense :-)<br>
<br>
Vladimir.<br>
<br>
&gt;<br>
&gt; -Thorsten<br>
&gt;<br>
&gt;<br>
&gt; Am 09.09.2017 um 19:42 schrieb Xiaodi Wu via swift-evolution<br>
&gt; &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;&gt;:<br>
&gt;<br>
&gt;&gt;<br>
&gt;&gt; On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution<br>
&gt;&gt; &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt;&gt;     On 9 Sep 2017, at 09:33, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a><br>
&gt;&gt;&gt;     &lt;mailto:<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt;&gt; wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;     On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution<br>
&gt;&gt;&gt;     &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;&gt; wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         On 9 Sep 2017, at 02:02, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a><br>
&gt;&gt;&gt;&gt;         &lt;mailto:<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt;&gt; wrote:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via<br>
&gt;&gt;&gt;&gt;         swift-evolution&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
&gt;&gt;&gt;&gt;         &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;&gt;wrote:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;             On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution<br>
&gt;&gt;&gt;&gt;&gt;             &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;&gt; wrote:<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;             On 7 Sep 2017, at 22:02, Itai Ferber &lt;<a href="mailto:iferber@apple.com" target="_blank">iferber@apple.com</a><br>
&gt;&gt;&gt;&gt;&gt;&gt;             &lt;mailto:<a href="mailto:iferber@apple.com" target="_blank">iferber@apple.com</a>&gt;&gt; wrote:<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt;             |protocol Fooable : Equatable { // Equatable is just a simple<br>
&gt;&gt;&gt;&gt;&gt;&gt;             example var myFoo: Int { get } } extension Fooable { static func<br>
&gt;&gt;&gt;&gt;&gt;&gt;             ==(_ lhs: Self, _ rhs: Self) -&gt; Bool { return lhs.myFoo ==<br>
&gt;&gt;&gt;&gt;&gt;&gt;             rhs.myFoo } } struct X : Fooable { let myFoo: Int let myName:<br>
&gt;&gt;&gt;&gt;&gt;&gt;             String // Whoops, forgot to give an implementation of == }<br>
&gt;&gt;&gt;&gt;&gt;&gt;             print(X(myFoo: 42, myName: &quot;Alice&quot;) == X(myFoo: 42, myName: &quot;Bob&quot;))<br>
&gt;&gt;&gt;&gt;&gt;&gt;             // true|<br>
&gt;&gt;&gt;&gt;&gt;&gt;             This property is/necessary/, but not/sufficient/to provide a<br>
&gt;&gt;&gt;&gt;&gt;&gt;             correct implementation. A default implementation might be able<br>
&gt;&gt;&gt;&gt;&gt;&gt;             to/assume/ something about the types that it defines, but it does<br>
&gt;&gt;&gt;&gt;&gt;&gt;             not necessarily know enough.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;             Sorry but that&#39;s a bit of a contrived example; in this case the<br>
&gt;&gt;&gt;&gt;&gt;             protocol should*not* implement the equality operator if more<br>
&gt;&gt;&gt;&gt;&gt;             information may be required to define equality. It should only be<br>
&gt;&gt;&gt;&gt;&gt;             implemented if the protocol is absolutely clear that .myFoo is the<br>
&gt;&gt;&gt;&gt;&gt;             only part of a Fooable that can or should be compared as equatable,<br>
&gt;&gt;&gt;&gt;&gt;             e.g- if a Fooable is a database record and .myFoo is a primary key,<br>
&gt;&gt;&gt;&gt;&gt;             the data could differ but it would still be a reference to the same<br>
&gt;&gt;&gt;&gt;&gt;             record.<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;             To be clear, I&#39;m not arguing that someone can&#39;t create a regular<br>
&gt;&gt;&gt;&gt;&gt;             default implementation that also makes flawed assumptions, but that<br>
&gt;&gt;&gt;&gt;&gt;             synthesised/reflective implementations*by their very nature have<br>
&gt;&gt;&gt;&gt;&gt;             to*, as they cannot under every circumstance guarantee correctness<br>
&gt;&gt;&gt;&gt;&gt;             when using parts of a concrete type that they know nothing about.<br>
&gt;&gt;&gt;&gt;             You can’t argue this both ways:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;               * If you’re arguing this on principle, that in order for<br>
&gt;&gt;&gt;&gt;                 synthesized implementations to be correct, they/must/ be able to<br>
&gt;&gt;&gt;&gt;                 —/under every circumstance/ — guarantee correctness, then you<br>
&gt;&gt;&gt;&gt;                 have to apply the same reasoning to default protocol<br>
&gt;&gt;&gt;&gt;                 implementations. Given a default protocol implementation, it is<br>
&gt;&gt;&gt;&gt;                 possible to come up with a (no matter how contrived) case where<br>
&gt;&gt;&gt;&gt;                 the default implementation is wrong. Since you’re arguing this/on<br>
&gt;&gt;&gt;&gt;                 principle/, you cannot reject contrived examples.<br>
&gt;&gt;&gt;&gt;               * If you are arguing this/in practice/, then you’re going to have<br>
&gt;&gt;&gt;&gt;                 to back up your argument with evidence that synthesized examples<br>
&gt;&gt;&gt;&gt;                 are more often wrong than default implementations. You can’t<br>
&gt;&gt;&gt;&gt;                 declare that synthesized implementations are/by nature/incorrect<br>
&gt;&gt;&gt;&gt;                 but allow default implementations to slide because/in practice/,<br>
&gt;&gt;&gt;&gt;                 many implementations are allowable. There’s a reason why<br>
&gt;&gt;&gt;&gt;                 synthesis passed code review and was accepted: in the majority of<br>
&gt;&gt;&gt;&gt;                 cases, synthesis was deemed to be beneficial, and would provide<br>
&gt;&gt;&gt;&gt;                 correct behavior. If you are willing to say that yes, sometimes<br>
&gt;&gt;&gt;&gt;                 default implementations are wrong but overall they’re correct,<br>
&gt;&gt;&gt;&gt;                 you’re going to have to provide hard evidence to back up the<br>
&gt;&gt;&gt;&gt;                 opposite case for synthesized implementations. You stated in a<br>
&gt;&gt;&gt;&gt;                 previous email that &quot;A synthesised/reflective implementation<br>
&gt;&gt;&gt;&gt;                 however may return a result that is simply incorrect, because it<br>
&gt;&gt;&gt;&gt;                 is based on assumptions made by the protocol developer, with no<br>
&gt;&gt;&gt;&gt;                 input from the developer of the concrete type. In this case the<br>
&gt;&gt;&gt;&gt;                 developer must override it in to provide *correct* behaviour.&quot; —<br>
&gt;&gt;&gt;&gt;                 if you can back this up with evidence (say, taking a survey of a<br>
&gt;&gt;&gt;&gt;                 large number of model types and see if in the majority of cases<br>
&gt;&gt;&gt;&gt;                 synthesized implementation would be incorrect) to provide a<br>
&gt;&gt;&gt;&gt;                 compelling argument, then this is something that we should in<br>
&gt;&gt;&gt;&gt;                 that case reconsider.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         Well put, and I agree with this position 100%. However, to play devil&#39;s<br>
&gt;&gt;&gt;&gt;         advocate here, let me summarize what I think Haravikk is saying:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         I think the &quot;synthesized&quot; part of this is a red herring, if I understand<br>
&gt;&gt;&gt;&gt;         Haravikk&#39;s argument correctly. Instead, it is this:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         (1) In principle, it is possible to have a default implementation for a<br>
&gt;&gt;&gt;&gt;         protocol requirement that produces the correct result--though not<br>
&gt;&gt;&gt;&gt;         necessarily in the most performant way--for all possible conforming<br>
&gt;&gt;&gt;&gt;         types, where by conforming we mean that the type respects both the<br>
&gt;&gt;&gt;&gt;         syntactic requirements (enforced by the compiler) and the semantic<br>
&gt;&gt;&gt;&gt;         requirements (which may not necessarily be enforceable by the compiler)<br>
&gt;&gt;&gt;&gt;         of the protocol in question.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         (2) However, there exist *some* requirements that, by their very nature,<br>
&gt;&gt;&gt;&gt;         cannot have default implementations which are guaranteed to produce the<br>
&gt;&gt;&gt;&gt;         correct result for all conforming types. In Haravikk&#39;s view, no default<br>
&gt;&gt;&gt;&gt;         implementations should be provided in these cases. (I don&#39;t necessarily<br>
&gt;&gt;&gt;&gt;         subscribe to this view in absolute terms, but for the sake of argument<br>
&gt;&gt;&gt;&gt;         let&#39;s grant this premise.)<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         (3) Equatable, Hashable, and Codable requirements are, by their very<br>
&gt;&gt;&gt;&gt;         nature, such requirements that cannot have default implementations<br>
&gt;&gt;&gt;&gt;         guaranteed to be correct for all conforming types. Therefore, they should<br>
&gt;&gt;&gt;&gt;         not have a default implementation. It just so happens that a default<br>
&gt;&gt;&gt;&gt;         implementation cannot currently be written in Swift itself and must be<br>
&gt;&gt;&gt;&gt;         synthesized, but Haravikk&#39;s point is that even if they could be written<br>
&gt;&gt;&gt;&gt;         in native Swift through a hypothetical reflection facility, they should<br>
&gt;&gt;&gt;&gt;         not be, just as many other protocol requirements currently could have<br>
&gt;&gt;&gt;&gt;         default implementations written in Swift but should not have them because<br>
&gt;&gt;&gt;&gt;         they cannot be guaranteed to produce the correct result.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         My response to this line of argumentation is as follows:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;         For any open protocol (i.e., a protocol for which the universe of<br>
&gt;&gt;&gt;&gt;         possible conforming types cannot be enumerated a priori by the protocol<br>
&gt;&gt;&gt;&gt;         designer) worthy of being a protocol by the Swift standard (&quot;what useful<br>
&gt;&gt;&gt;&gt;         thing can you do with such a protocol that you could not without?&quot;), any<br>
&gt;&gt;&gt;&gt;         sufficiently interesting requirement (i.e., one for which user ergonomics<br>
&gt;&gt;&gt;&gt;         would measurably benefit from a default implementation) either cannot<br>
&gt;&gt;&gt;&gt;         have a universally guaranteed correct implementation or has an<br>
&gt;&gt;&gt;&gt;         implementation which is also going to be the most performant one (which<br>
&gt;&gt;&gt;&gt;         can therefore be a non-overridable protocol extension method rather than<br>
&gt;&gt;&gt;&gt;         an overridable protocol requirement with a default implementation).<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;         You&#39;re close, but still missing key points:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;          1. I am not arguing that features like these should*not* be provided, but<br>
&gt;&gt;&gt;             that they should*not* be provided implicitly, and that the developer<br>
&gt;&gt;&gt;             should actually be allowed to request them. That is exactly what this<br>
&gt;&gt;&gt;             proposal is about, yet no matter what I say everyone seems to be<br>
&gt;&gt;&gt;             treating me like I&#39;m against these features entirely; *I am not*.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;     You are entirely against Equatable having a default implementation for ==.<br>
&gt;&gt;&gt;     This is unequivocally stated. Others favor such a default implementation and<br>
&gt;&gt;&gt;     feel that in the absence of a way to spell this in Swift itself, it should be<br>
&gt;&gt;&gt;     magic for the time being. For the purposes of this argument it really is not<br>
&gt;&gt;&gt;     pertinent that you are not also against something else; you&#39;re asking us to<br>
&gt;&gt;&gt;     discuss why you are against a particular thing that others are for.<br>
&gt;&gt;<br>
&gt;&gt;     FFS, how much clearer can I make this? *I AM NOT AGAINST THE FEATURE.*<br>
&gt;&gt;     *<br>
&gt;&gt;     *<br>
&gt;&gt;     What I am against is the way in which it is being provided implicitly rather<br>
&gt;&gt;     than explicitly, in particular as a retroactive change to existing protocols in<br>
&gt;&gt;     a way that introduces potential for bugs that are currently impossible, but<br>
&gt;&gt;     also in general.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; You are against a default implementation for ==, i.e. an implementation that is<br>
&gt;&gt; provided for you if you conform a type to the protocol and do nothing else<br>
&gt;&gt; (&quot;implicitly rather than explicitly&quot;), and you are against the default<br>
&gt;&gt; implementation being on the existing protocol Equatable (&quot;retroactive change&quot;). So,<br>
&gt;&gt; to summarize, what you are against is precisely a default implementation for the ==<br>
&gt;&gt; requirement on Equatable.<br>
&gt;&gt;<br>
&gt;&gt; This is the topic of discussion here; I am attempting to convince you that you<br>
&gt;&gt; should be for rather than against these things.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;&gt;     As repeatedly answered by others, nothing here is specific to synthesized<br>
&gt;&gt;&gt;     default implementations, as more powerful reflection will gradually allow them<br>
&gt;&gt;&gt;     to be non-synthesised.<br>
&gt;&gt;<br>
&gt;&gt;     And as repeatedly stated by me; I am not treating synthesised vs. run-time<br>
&gt;&gt;     reflection any differently, I specifically included both in the original proposal.<br>
&gt;&gt;<br>
&gt;&gt;&gt;     As pointed out very cogently by Itai, you assert but offer no evidence, either<br>
&gt;&gt;&gt;     in principle or empirically, that going too far by reflection is worse than<br>
&gt;&gt;&gt;     going not far enough without reflection in terms of likelihood of a default<br>
&gt;&gt;&gt;     implementation being inappropriate for conforming types.<br>
&gt;&gt;<br>
&gt;&gt;     As I have also repeatedly pointed out it is not an issue of &quot;not going far<br>
&gt;&gt;     enough&quot; vs. &quot;going too far&quot;; if a default implementation lacks information then<br>
&gt;&gt;     it should not be provided, doing so regardless is a flaw in the protocol design<br>
&gt;&gt;     and not something that this proposal attempts to address (as such a thing is<br>
&gt;&gt;     likely impossible).<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Right, one must consider the semantics of the specific protocol requirement and ask<br>
&gt;&gt; whether a reasonable default can be provided for it.<br>
&gt;&gt;<br>
&gt;&gt;     Reflective implementations *necessarily* go too far, because they literally<br>
&gt;&gt;     know *nothing* about the concrete type with any certainty, except for the<br>
&gt;&gt;     properties that are defined in the protocol (which do not require reflection or<br>
&gt;&gt;     synthesis in the first place).<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; I am confused why you are trying to argue in general terms about the universe of<br>
&gt;&gt; all possible default implementations that use reflection. This is necessarily a<br>
&gt;&gt; more difficult argument to make, and if it is to be convincing for all default<br>
&gt;&gt; implementations it must also be convincing for the two specific protocol<br>
&gt;&gt; requirements we are talking about here. Start small:<br>
&gt;&gt;<br>
&gt;&gt; We have agreed, as a community, that there is a reasonable default implementation<br>
&gt;&gt; for Equatable.== when certain conditions are met (for value types only at the<br>
&gt;&gt; moment, I believe). Namely, given two values of a type that has only Equatable<br>
&gt;&gt; stored properties, those values are equal if their stored properties are all equal.<br>
&gt;&gt; The author of a new value type who wishes to make her type Equatable but chooses<br>
&gt;&gt; not to implement a custom == then benefits from this default when all stored<br>
&gt;&gt; properties are Equatable.<br>
&gt;&gt;<br>
&gt;&gt;     And precisely what kind of &quot;evidence&quot; am I expected to give? This is a set of<br>
&gt;&gt;     features that *do not exist yet*, I am trying to argue in favour of an explicit<br>
&gt;&gt;     end-developer centric opt-in rather than an implicit protocol designer centric<br>
&gt;&gt;     one. Yet no-one seems interested in the merits of allowing developers to choose<br>
&gt;&gt;     what they want, rather than having implicit behaviours appear potentially<br>
&gt;&gt;     unexpectedly.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Both options were examined for Codable and for Equatable/Hashable. The community<br>
&gt;&gt; and core team decided to prefer the current design. At this point, new insights<br>
&gt;&gt; that arise which could not be anticipated at the time of review could prompt<br>
&gt;&gt; revision. However, so far, you have presented arguments already considered during<br>
&gt;&gt; review.<br>
&gt;&gt;<br>
&gt;&gt;&gt;     Therefore, your argument reduces to one about which default implementations<br>
&gt;&gt;&gt;     generally ought or ought not to be provided--that is, that they ought to be<br>
&gt;&gt;&gt;     provided only when their correctness can be guaranteed for all (rather than<br>
&gt;&gt;&gt;     almost all) possible conforming types. To which point I sketched a rebuttal above.<br>
&gt;&gt;<br>
&gt;&gt;     If a protocol defines something, and creates a default implementation based<br>
&gt;&gt;     only upon those definitions then it must by its very nature be correct. A<br>
&gt;&gt;     concrete type may later decided to go further, but that is a feature of the<br>
&gt;&gt;     concrete type, not a failure of the protocol itself which can function<br>
&gt;&gt;     correctly within the context it created. You want to talk evidence, yet there<br>
&gt;&gt;     has been no example given that proves otherwise; thus far only Itai has<br>
&gt;&gt;     attempted to do so, but I have already pointed out the flaws with that example.<br>
&gt;&gt;<br>
&gt;&gt;     The simple fact is that a default implementation may either be flawed or not<br>
&gt;&gt;     within the context of the protocol itself; but a reflective or synthetic<br>
&gt;&gt;     implementation by its very nature goes beyond what the protocol defines and so<br>
&gt;&gt;     is automatically flawed because as it does not rely on the end-developer to<br>
&gt;&gt;     confirm correctness, not when provided implicitly at least.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Again, if it applies generally, it must apply specifically. What is &quot;automatically<br>
&gt;&gt; flawed&quot; about the very reasonable synthesized default implementation of ==?<br>
&gt;&gt;<br>
&gt;&gt;&gt;         And all of this continues to be a side-issue to the fact that in the<br>
&gt;&gt;&gt;         specific case of Equatable/Hashable, which thus far has gone ignored, is<br>
&gt;&gt;&gt;         that bolting this on retroactively to an existing protocol*hides bugs*.<br>
&gt;&gt;&gt;         The issue of reflective default implementations is less of a concern on<br>
&gt;&gt;&gt;         very clearly and well defined*new* protocols, though I still prefer more,<br>
&gt;&gt;&gt;         rather than less, control, but in the specific case of*existing* protocols<br>
&gt;&gt;&gt;         this fucking about with behaviours is reckless and foolish in the extreme,<br>
&gt;&gt;&gt;         yet no-one on the core teams seems willing or able to justify it, which<br>
&gt;&gt;&gt;         only opens much wider concerns (how am I to have any faith in Swift&#39;s<br>
&gt;&gt;&gt;         development if the core team can&#39;t or won&#39;t justify the creation of new<br>
&gt;&gt;&gt;         bugs?).<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;     This has emphatically not gone ignored, as I have myself responded to this<br>
&gt;&gt;&gt;     point in an earlier thread in which you commented, as well as many others.<br>
&gt;&gt;&gt;     Crucially, no existing conforming type changes its behavior, as they have all<br>
&gt;&gt;&gt;     had to implement these requirements themselves. And as I said to you already,<br>
&gt;&gt;&gt;     the addition of a synthesized default implementation no more &quot;hides bugs&quot;<br>
&gt;&gt;&gt;     going forward than the addition of a non-synthesized default implementation to<br>
&gt;&gt;&gt;     an existing protocol, and we do that with some frequency without even Swift<br>
&gt;&gt;&gt;     Evolution review.<br>
&gt;&gt;<br>
&gt;&gt;     Feel free to a supply a non-synthesised default implementation for Equatable<br>
&gt;&gt;     without the use of reflection. Go-on, I&#39;ll wait.<br>
&gt;&gt;     You insist on suggesting these are the same thing, yet if you can&#39;t provide one<br>
&gt;&gt;     then clearly they are not.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; That is not the argument. The argument is that they are indistinguishable in the<br>
&gt;&gt; sense that the author of a type who intends to supply a custom implementation but<br>
&gt;&gt; neglects to do so will have a default implementation supplied for them. It is<br>
&gt;&gt; plainly true that this is no more or less likely to happen simply because the<br>
&gt;&gt; default implementation is synthesized.<br>
&gt;&gt;<br>
&gt;&gt;&gt;     Put another way, what the proposal about synthesizing implementations for<br>
&gt;&gt;&gt;     Equatable and Hashable was about can be thought of in two parts: (a) should<br>
&gt;&gt;&gt;     there be default implementations; and (b) given that it is impossible to write<br>
&gt;&gt;&gt;     these in Swift, should we use magic? Now, as I said above, adding default<br>
&gt;&gt;&gt;     implementations isn&#39;t (afaik) even considered an API change that requires<br>
&gt;&gt;&gt;     review on this list. Really, what people were debating was (b), whether it is<br>
&gt;&gt;&gt;     worth it to implement compiler-supported magic to make these possible. Your<br>
&gt;&gt;&gt;     disagreement has to do with (a) and not (b).<br>
&gt;&gt;<br>
&gt;&gt;     Wrong. The use of magic in this case produces something else entirely; that&#39;s<br>
&gt;&gt;     the whole point. It is *not the same*, otherwise it wouldn&#39;t be needed at all.<br>
&gt;&gt;     It doesn&#39;t matter if it&#39;s compiler magic, some external script or a native<br>
&gt;&gt;     macro, ultimately they are all doing something with a concrete type that is<br>
&gt;&gt;     currently not possible.<br>
&gt;&gt;<br>
&gt;&gt;     And once again; *I am not arguing against a default implementation that cuts<br>
&gt;&gt;     boilerplate*, I am arguing against it being implicit. What I want is to be the<br>
&gt;&gt;     one asking for it, because it is not reasonable to assume that just throwing it<br>
&gt;&gt;     in there is always going to be fine, because it quite simply is not.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; If you have to ask for it, then it&#39;s not a default. You *are* against a default<br>
&gt;&gt; implementation.<br>
&gt;&gt;<br>
&gt;&gt;     _______________________________________________<br>
&gt;&gt;     swift-evolution mailing list<br>
&gt;&gt;     <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;<br>
&gt;&gt;     <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;&gt;<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; swift-evolution mailing list<br>
&gt;&gt; <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;<br>
&gt;&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; swift-evolution mailing list<br>
&gt; <a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
&gt;<br>
_______________________________________________<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>