Sent from my iPad

> On Sep 7, 2017, at 7:45 AM, Tony Allevato <tony.allev...@gmail.com> wrote:
> 
> 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.
> 
> 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).

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.

> 
> 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.
>> On Thu, Sep 7, 2017 at 5:37 AM Matthew Johnson via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>> 
>> Sent from my iPad
>> 
>>> On Sep 7, 2017, at 7:07 AM, Gwendal Roué via swift-evolution 
>>> <swift-evolution@swift.org> wrote:
>>> 
>>> Hello,
>>> 
>>> I'm interested in this debate because I've been bitten by automatic 
>>> synthesis recently.
>>> 
>>> 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).
>>> 
>>> 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:
>>> 
>>>     // SELECT * FROM players WHERE bestScore = 1000
>>>     Player.filter(bestScore == 1000)
>>> 
>>> 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:
>>> 
>>>     // SELECT * FROM players WHERE lastScore = bestScore
>>>     Player.filter(lastScore == bestScore)
>>> 
>>> However, as soon as the type is (also) Equatable, an ambiguity occurs, and 
>>> the DSL is basically broken:
>>> 
>>>     Player.filter(lastScore == bestScore) // which == please?
>>> 
>>> 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.
>>> 
>>> 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.
>> 
>> 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.
>> 
>> 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). 
>>  
>> 
>>> 
>>> Thanks for reading,
>>> Gwendal Roué
>>> [1] http://github.com/groue/GRDB.swift
>>> 
>>>>> Le 7 sept. 2017 à 12:20, Haravikk via swift-evolution 
>>>>> <swift-evolution@swift.org> a écrit :
>>>>> 
>>>>> 
>>>>>> On 7 Sep 2017, at 00:11, Brent Royal-Gordon <br...@architechies.com> 
>>>>>> wrote:
>>>>>> 
>>>>>> On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
>>>>>> <swift-evolution@swift.org> wrote:
>>>>>> 
>>>>>> 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).
>>>>> 
>>>>> 
>>>>> "Use of the reflection API against `self`"? `String(describing:)` and 
>>>>> `String(reflecting:)` sometimes do that.
>>>>> 
>>>>> 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.
>>>> 
>>>> Actually they don't; the problem here is that through reflection you are 
>>>> accessing and manipulating concrete types. A non-reflective default 
>>>> implementation only 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.
>>>> 
>>>>>> On 6 Sep 2017, at 23:43, Nevin Brackett-Rozinsky 
>>>>>> <nevin.brackettrozin...@gmail.com> wrote:
>>>>>>> On Wed, Sep 6, 2017 at 5:42 PM, Haravikk via swift-evolution 
>>>>>>> <swift-evolution@swift.org> wrote:
>>>>>>> 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.
>>>>> 
>>>>> 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.
>>>> 
>>>> 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.
>>>> 
>>>> 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.
>>>> 
>>>> 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 can make a difference, as it can drastically 
>>>> affect behaviour when those assumptions fail.
>>>> 
>>>>> On 7 Sep 2017, at 05:00, Andrew Thompson <mrwerdo...@me.com> wrote:
>>>>> 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 )
>>>> 
>>>> 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 do 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.
>>>> 
>>>> 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.
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution@swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to