Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-10-02 Thread David Hart via swift-evolution

> On 2 Oct 2017, at 06:39, Ted Kremenek via swift-evolution 
>  wrote:
> 
> 
>> On Oct 1, 2017, at 4:00 AM, Haravikk via swift-evolution 
>> > wrote:
>> 
>>> 
>>> On 14 Sep 2017, at 20:10, Ben Rimmington >> > wrote:
>>> 
>>> 
 On 14 Sep 2017, at 15:31, Haravikk wrote:
 
> On 14 Sep 2017, at 02:12, Xiaodi Wu wrote:
> 
>> On Wed, Sep 13, 2017 at 09:13 Haravikk wrote:
>> 
>> I mean because not once have you summarised what these alleged 
>> "considerations" were; if they exist then you should be able do so, yet 
>> all I am hearing is "it was considered", which frankly is not an 
>> argument at all as it is entirely without substance.
> 
> Of course it is not an argument at all. It is a factual statement. The 
> objections which you mentioned were also mentioned prior to a decision 
> about SE-0185. The community and the core team had an opportunity to view 
> those objections. After that time, a decision was made, having considered 
> all the stated pros and cons which included the ones that you are now 
> repeating. What "considerations" are you looking for?
 
 Ones with proof that they were ever made! Once again you are stating that 
 these issues were "considered", yet you show not a single shred of proof 
 that that was the case. You're asking me to take you at your word but I 
 have no reason to trust that the problem has been as carefully considered 
 as you claim.
 I was involved in one such discussion and the response from the core team 
 was frankly pitiful; they did not provide any justification whatsoever.
>>> 
>>> Chris Lattner already said that the core team discussed your concerns:
>>> 
>>> >>  
>>> >
>>> 
>>> >>  
>>> >
>>> 
>>> The original idea was for most types to be *implicitly* equatable and 
>>> hashable:
>>> 
>>> >>  
>>> >
>>> 
>>> The accepted proposal, with *explicit* declaration of conformance, is a 
>>> good compromise.
>>> 
>>> Instead of discussing hypothetical issues with SE-0185, we can wait for 
>>> Swift 4.1 beta.
>> 
>> And as I pointed out this "consideration" was pathetic; he interjected once 
>> with a flawed argument and was never seen again. The core team has utterly 
>> failed to justify their decision. It does not prove "consideration"; there 
>> are no reasoned points, alternatives are never discussed, it is a dictate 
>> not a discussion.
>> 
>> But fuck it, I no longer care; it is clear to me now that Swift Evolution 
>> serves no purpose if the core team cannot or will not listen, and on that 
>> basis if I cannot trust the core team I cannot trust Swift as a language, 
>> and will not be using it going forward, as the direction it is taking 
>> frankly undermines any optimism I once had for it.
> 
> I’m sad to see the thread go this way.  Myself and others who want to make 
> swift-evolution feel like a place where ideas are heard certainly are 
> sensitive to individuals getting frustrated.  That said, closing out the 
> thread in a way that clearly violates the code of conduct (and thus the core 
> sense of courtesy and professionalism we want to maintain on the list) isn’t 
> effective either.  I think the thread should stop here, and remedial actions 
> will be taken to stem this negative dialogue from continuing.

Thanks for stepping in Ted. I’m very happy with how Swift Evolution has been 
going and I’m happy to see that when the Code of Conduct is violated, it is 
recognised and dealt with swiftly (no pun intended).

> ___
> 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


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-10-01 Thread Ted Kremenek via swift-evolution

> On Oct 1, 2017, at 4:00 AM, Haravikk via swift-evolution 
>  wrote:
> 
>> 
>> On 14 Sep 2017, at 20:10, Ben Rimmington  wrote:
>> 
>> 
>>> On 14 Sep 2017, at 15:31, Haravikk wrote:
>>> 
 On 14 Sep 2017, at 02:12, Xiaodi Wu wrote:
 
> On Wed, Sep 13, 2017 at 09:13 Haravikk wrote:
> 
> I mean because not once have you summarised what these alleged 
> "considerations" were; if they exist then you should be able do so, yet 
> all I am hearing is "it was considered", which frankly is not an argument 
> at all as it is entirely without substance.
 
 Of course it is not an argument at all. It is a factual statement. The 
 objections which you mentioned were also mentioned prior to a decision 
 about SE-0185. The community and the core team had an opportunity to view 
 those objections. After that time, a decision was made, having considered 
 all the stated pros and cons which included the ones that you are now 
 repeating. What "considerations" are you looking for?
>>> 
>>> Ones with proof that they were ever made! Once again you are stating that 
>>> these issues were "considered", yet you show not a single shred of proof 
>>> that that was the case. You're asking me to take you at your word but I 
>>> have no reason to trust that the problem has been as carefully considered 
>>> as you claim.
>>> I was involved in one such discussion and the response from the core team 
>>> was frankly pitiful; they did not provide any justification whatsoever.
>> 
>> Chris Lattner already said that the core team discussed your concerns:
>> 
>> 
>> 
>> 
>> 
>> The original idea was for most types to be *implicitly* equatable and 
>> hashable:
>> 
>> 
>> 
>> The accepted proposal, with *explicit* declaration of conformance, is a good 
>> compromise.
>> 
>> Instead of discussing hypothetical issues with SE-0185, we can wait for 
>> Swift 4.1 beta.
> 
> And as I pointed out this "consideration" was pathetic; he interjected once 
> with a flawed argument and was never seen again. The core team has utterly 
> failed to justify their decision. It does not prove "consideration"; there 
> are no reasoned points, alternatives are never discussed, it is a dictate not 
> a discussion.
> 
> But fuck it, I no longer care; it is clear to me now that Swift Evolution 
> serves no purpose if the core team cannot or will not listen, and on that 
> basis if I cannot trust the core team I cannot trust Swift as a language, and 
> will not be using it going forward, as the direction it is taking frankly 
> undermines any optimism I once had for it.

I’m sad to see the thread go this way.  Myself and others who want to make 
swift-evolution feel like a place where ideas are heard certainly are sensitive 
to individuals getting frustrated.  That said, closing out the thread in a way 
that clearly violates the code of conduct (and thus the core sense of courtesy 
and professionalism we want to maintain on the list) isn’t effective either.  I 
think the thread should stop here, and remedial actions will be taken to stem 
this negative dialogue from continuing.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-10-01 Thread Haravikk via swift-evolution

> On 14 Sep 2017, at 20:10, Ben Rimmington  wrote:
> 
> 
>> On 14 Sep 2017, at 15:31, Haravikk wrote:
>> 
>>> On 14 Sep 2017, at 02:12, Xiaodi Wu wrote:
>>> 
 On Wed, Sep 13, 2017 at 09:13 Haravikk wrote:
 
 I mean because not once have you summarised what these alleged 
 "considerations" were; if they exist then you should be able do so, yet 
 all I am hearing is "it was considered", which frankly is not an argument 
 at all as it is entirely without substance.
>>> 
>>> Of course it is not an argument at all. It is a factual statement. The 
>>> objections which you mentioned were also mentioned prior to a decision 
>>> about SE-0185. The community and the core team had an opportunity to view 
>>> those objections. After that time, a decision was made, having considered 
>>> all the stated pros and cons which included the ones that you are now 
>>> repeating. What "considerations" are you looking for?
>> 
>> Ones with proof that they were ever made! Once again you are stating that 
>> these issues were "considered", yet you show not a single shred of proof 
>> that that was the case. You're asking me to take you at your word but I have 
>> no reason to trust that the problem has been as carefully considered as you 
>> claim.
>> I was involved in one such discussion and the response from the core team 
>> was frankly pitiful; they did not provide any justification whatsoever.
> 
> Chris Lattner already said that the core team discussed your concerns:
> 
> 
> 
> 
> 
> The original idea was for most types to be *implicitly* equatable and 
> hashable:
> 
> 
> 
> The accepted proposal, with *explicit* declaration of conformance, is a good 
> compromise.
> 
> Instead of discussing hypothetical issues with SE-0185, we can wait for Swift 
> 4.1 beta.

And as I pointed out this "consideration" was pathetic; he interjected once 
with a flawed argument and was never seen again. The core team has utterly 
failed to justify their decision. It does not prove "consideration"; there are 
no reasoned points, alternatives are never discussed, it is a dictate not a 
discussion.

But fuck it, I no longer care; it is clear to me now that Swift Evolution 
serves no purpose if the core team cannot or will not listen, and on that basis 
if I cannot trust the core team I cannot trust Swift as a language, and will 
not be using it going forward, as the direction it is taking frankly undermines 
any optimism I once had for it.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-14 Thread Ben Rimmington via swift-evolution

> On 14 Sep 2017, at 15:31, Haravikk wrote:
> 
>> On 14 Sep 2017, at 02:12, Xiaodi Wu wrote:
>> 
>>> On Wed, Sep 13, 2017 at 09:13 Haravikk wrote:
>>> 
>>> I mean because not once have you summarised what these alleged 
>>> "considerations" were; if they exist then you should be able do so, yet all 
>>> I am hearing is "it was considered", which frankly is not an argument at 
>>> all as it is entirely without substance.
>> 
>> Of course it is not an argument at all. It is a factual statement. The 
>> objections which you mentioned were also mentioned prior to a decision about 
>> SE-0185. The community and the core team had an opportunity to view those 
>> objections. After that time, a decision was made, having considered all the 
>> stated pros and cons which included the ones that you are now repeating. 
>> What "considerations" are you looking for?
> 
> Ones with proof that they were ever made! Once again you are stating that 
> these issues were "considered", yet you show not a single shred of proof that 
> that was the case. You're asking me to take you at your word but I have no 
> reason to trust that the problem has been as carefully considered as you 
> claim.
> I was involved in one such discussion and the response from the core team was 
> frankly pitiful; they did not provide any justification whatsoever.

Chris Lattner already said that the core team discussed your concerns:





The original idea was for most types to be *implicitly* equatable and hashable:



The accepted proposal, with *explicit* declaration of conformance, is a good 
compromise.

Instead of discussing hypothetical issues with SE-0185, we can wait for Swift 
4.1 beta.

-- Ben

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-14 Thread Haravikk via swift-evolution

> On 14 Sep 2017, at 02:12, Xiaodi Wu  wrote:
>> On Wed, Sep 13, 2017 at 09:13 Haravikk via swift-evolution 
>> > wrote:
>> I mean because not once have you summarised what these alleged 
>> "considerations" were; if they exist then you should be able do so, yet all 
>> I am hearing is "it was considered", which frankly is not an argument at all 
>> as it is entirely without substance.
> 
> Of course it is not an argument at all. It is a factual statement. The 
> objections which you mentioned were also mentioned prior to a decision about 
> SE-0185. The community and the core team had an opportunity to view those 
> objections. After that time, a decision was made, having considered all the 
> stated pros and cons which included the ones that you are now repeating. What 
> "considerations" are you looking for?

Ones with proof that they were ever made! Once again you are stating that these 
issues were "considered", yet you show not a single shred of proof that that 
was the case. You're asking me to take you at your word but I have no reason to 
trust that the problem has been as carefully considered as you claim.
I was involved in one such discussion and the response from the core team was 
frankly pitiful; they did not provide any justification whatsoever.


But since it's clear that you have no intention of ever responding 
substantively I will not dignify your messages with any further responses as it 
is nothing more than a waste of my time; you hypocritically accuse me of 
repetition, while you also ignore direct questions and any point that doesn't 
fit your "shut up about this" viewpoint. If that is all you have to say then 
you've said it a dozen times over, so kindly stop doing so.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Xiaodi Wu via swift-evolution
On Wed, Sep 13, 2017 at 09:13 Haravikk via swift-evolution <
swift-evolution@swift.org> wrote:

> On 13 Sep 2017, at 03:26, Xiaodi Wu  wrote:
>
> On Tue, Sep 12, 2017 at 11:43 AM, Haravikk via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> On 12 Sep 2017, at 12:08, Xiaodi Wu  wrote:
>>
>> On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> See, this is another flawed assumption; you are assuming that omitting a
>>> custom implementation of == is always intentional rather than an oversight,
>>> which is not guaranteed. This is one of my gripes with the retroactive
>>> change to Equatable, as it is currently *impossible* to omit an
>>> implementation.
>>>
>>
>> Again, this applies equally to the addition of _any_ default
>> implementation. And again, such changes don’t even require Swift Evolution
>> approval.
>>
>>
>> So what? Because the Swift Evolution process is currently deficient we
>> should just give up on discussing problems with features and the language
>> altogether?
>>
>
> I don't claim that it's a deficiency; I claim it's reflective of Swift's
> opinionated take on default implementations. Are you, after all, saying
> that you have a problem with the addition of _any_ default implementation
> to an existing protocol? If so, this conversation isn't about
> synthesis/reflection at all.
>
>
> No, and you should know that by now. I suggest actually reading some of
> what I have written as I am sick of repeating myself.
>
> And precisely what kind of "evidence" am I expected to give? This is a set
>>> of features that *do not exist yet*, I am trying to argue in favour of
>>> an explicit end-developer centric opt-in rather than an implicit protocol
>>> designer centric one. Yet no-one seems interested in the merits of allowing
>>> developers to choose what they want, rather than having implicit behaviours
>>> appear potentially unexpectedly.
>>>
>>>
>>> Both options were examined for Codable and for Equatable/Hashable. The
>>> community and core team decided to prefer the current design. At this
>>> point, new insights that arise which could not be anticipated at the time
>>> of review could prompt revision. However, so far, you have presented
>>> arguments already considered during review.
>>>
>>>
>>> And so far all I have heard about this is how it was "decided"; no-one
>>> seems interested in showing how any of these concerns were addressed (if at
>>> all), so as far as I can tell they were not, or they were wilfully ignored.
>>>
>>
>> They were addressed by being considered.
>>
>>
>> And yet no-one can apparently summarise what those "considerations" might
>> be, suggesting that they were either *not* considered at all, or that
>> the "consideration" was so weak that no-one is willing to step forward to
>> defend it. Either way it is not sufficient by any reasonable measure.
>>
>> If I were to run over your foot in my car, would you be happy to accept
>> that I "considered" it first?
>>
>
> How do you mean? People wrote in with their opinions. Then, taking into
> account the community's response, the proposal was approved.
>
>
> I mean because not once have you summarised what these alleged
> "considerations" were; if they exist then you should be able do so, yet all
> I am hearing is "it was considered", which frankly is not an argument at
> all as it is entirely without substance.
>

Of course it is not an argument at all. It is a factual statement. The
objections which you mentioned were also mentioned prior to a decision
about SE-0185. The community and the core team had an opportunity to view
those objections. After that time, a decision was made, having considered
all the stated pros and cons which included the ones that you are now
repeating. What "considerations" are you looking for?

If it was genuinely considered then someone should be able to say what
> points were considered and what conclusions were reached and why. And even
> if there *was* an earlier decision, that doesn't necessarily make it
> right.
>

No, but it does mean that discussion of this topic has concluded on Swift
Evolution.

We are discussing it now, and it is clear that any decision that has been
> made has been made poorly at best.
>
> And if you're talking about the discussion on Equatable/Hashable
> specifically, I'm afraid your memory of the "considerations" is radically
> different to mine; as the concerns I raised were essentially ignored, as
> not a single person gave a justification more substantial than "but, but
> Codable!" which frankly isn't a justification at all.
>
> Therefore, your argument reduces to one about which default
 implementations generally ought or ought not to be provided--that is, that
 they ought to be provided only when their correctness can be guaranteed for
 all (rather than almost all) possible conforming types. To which point I
 sketched a rebuttal above.

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Xiaodi Wu via swift-evolution
On Wed, Sep 13, 2017 at 06:20 Gwendal Roué  wrote:

> >> If I take on my free time exposing issues, it's because I hope that
> maybe some reader will consider them with proper attention, then maybe
> agree that there is an issue worth investigating, and then many conclude
> that a made decision has to be reverted. That's a multi-step process. And
> that process starts with a proper read of the issues that have been exposed.
> >
> > Keep in mind that by posting to this list, you are also demanding other
> people spend their free time on the issue. And again, these issues have
> already been discussed. If a point is made once but doesn't carry the day,
> repeating it again and again doesn't make it more convincing.
>
> The fact that you fail at evaluating the relevance of an issue, as
> exemplified by the fact that you never answer directly to the described
> problems, does not make that issue moot.


As I have already replied, you have provided examples, but I fail to see
any unanticipated problem that is illustrated by them. It appears that the
proposed implementation for SE-0185 causes each of your examples to behave
exactly as the proposal authors would intend them to. You may disagree that
SE-0185 is desirable, but that is quite distinct from bringing up a new
insight about something unanticipated.

Instead, it may well end in the ears of people who have been more engaged
> in the subject: Tony Allevato as the author of SE-0185, and Chris Lattner
> the review manager.
>

Yes, it is clear that you and others are trying to re-open a debate about
SE-0185. And I am writing to ask you not to do that, as it is contrary to
the standard procedure by which this list evaluates proposals. There is
deliberately a preset period of time for consideration. It serves the
purpose of promoting timely feedback, since community memebers are
incentivized to put forward the most fully developed thoughts while the
idea has the attention of the greatest possible proportion of those who are
engaged in the community, and before the core team makes a decision; it
also preserves forward momentum by causing the community to move on to
other issues once a decision is taken. I'm sure all who participate on this
list feel strongly that one or another decision is wrongly taken. However,
it is extremely disrespectful to others involved in this process to insist
that the decisions with which you happen to disagree are the ones which,
right now, need to be reconsidered because you have decided that it is a
convenient time for you to re-state your thoughts again.

Their feedback would be especially appreciated, considering that the
> SE-0185 acceptance rationale (
> https://lists.swift.org/pipermail/swift-evolution-announce/2017-August/000400.html)
> doesn't address the issues I'm please to repeat for the interested readers:
>
> > For reference, here are some issues with implicit synthesis:
> >
> > -
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039704.html
> > -
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039710.html
>
> Gwendal
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread David Sweeris via swift-evolution

> On Sep 12, 2017, at 8:07 PM, Tony Allevato via swift-evolution 
>  wrote:
> 
> But all that stuff about custom attributes and metaprogramming introspection 
> is a big topic of it's own that isn't going to be solved in Swift 5, so this 
> is a bit of a digression. :)

Is it really a digression, though? Seems like with source-compatibility being 
essentially required going forward, it's important to nail this stuff down 
sooner rather than later if we want a nice, consistent language for The Future™.

I mean, the idea of writing "@adjective var noun: Type" to indicate that a 
certain variable shouldn't take place in code synthesis seems fairly safe to 
me, but proving $Idea1 is generalizable without stepping on $Idea2 is outside 
my area of expertise.



> On Sep 12, 2017, at 8:07 PM, Tony Allevato via swift-evolution 
>  wrote:
> On Tue, Sep 12, 2017 at 7:10 PM Xiaodi Wu  > wrote:
> On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via swift-evolution 
> > wrote:
> Good arguments, Tony, you have convinced me on all points. Transient is the 
> way to go. Thank you for your patience!
> 
> On many points, I agree with Tony, but I disagree that "transient" addresses 
> the issue at hand. The challenge being made is that, as Gwendal puts it, it's 
> _unwise_ to have a default implementation, because people might forget that 
> there is a default implementation. "Transient" only works if you remember 
> that there is a default implementation, and in that case, we already have a 
> clear syntax for overriding the default.
> 
> Right—I hope it hasn't sounded like I'm conflating the two concepts 
> completely. The reason I brought up "transient" is because nearly all of the 
> "risky" examples being cited so far have been of the variety "I have a type 
> where some properties happen to be Equatable but shouldn't be involved in 
> equality", so my intention has been to show that if we have a better solution 
> to that specific problem (which is, related to but not the same as the 
> question at hand), then there aren't enough risky cases left to warrant 
> adding this level of complexity to the protocol system.
>  
> 
> As others point out, there's a temptation here to write things like 
> "transient(Equatable)" so as to control the synthesis of implementations on a 
> per-protocol basis. By that point, you've invented a whole new syntax for 
> implementing protocol requirements. (Ah, you might say, but it's hard to 
> write a good hashValue implementation: sure, but that's adequately solved by 
> a library-supplied combineHashes() function.)
> 
> I totally agree with this. A design that would try to annotate "transient" 
> with a protocol or list of protocols is missing the point of the semantics 
> that "transient" is supposed to provide. It's not a series of switches to 
> that can be flipped on and off for arbitrary protocols—it's a semantic tag 
> that assigns additional meaning to properties and certain protocols (such as 
> Equatable, Hashable, and Codable, but possibly others that haven't been 
> designed yet) would have protocol-specific behavior for those properties.
> 
> To better explain what I've been poking at, I'm kind of extrapolating this 
> out to a possible future where it may be possible to more generally (1) 
> define custom @attributes in Swift, like Java annotations, and then (2) use 
> some metaprogramming constructs to generate introspective default 
> implementations for a protocol at compile-time just as the compiler does 
> "magically" now, and the generator would be able to query attributes that are 
> defined by the same library author as the protocol and handle them 
> accordingly.
> 
> In a world where that's possible, I think it's less helpful to think in terms 
> of "I need to distinguish between conforming to X and getting a synthesized 
> implementation and conforming to X and avoiding the synthesized 
> implementation because the default might be risky", but instead to think in 
> terms of "How can I provide enough semantic information about my types to 
> remove the risk?"
> 
> In other words, the switches we offer developers to flip shouldn't be about 
> turning on/off entire features, but about giving the compiler enough 
> information to make it smart enough that we never need to turn it off in the 
> first place. As I alluded to before, if I have 10 properties in a type and 
> only 1 of those needs to be ignored in ==/hashValue/whatever, writing 
> "Equatable" instead of "derives Equatable" isn't all that helpful. Yes, it 
> spits out an error message where there wouldn't have been one, but it doesn't 
> reduce any of the burden of having to provide the appropriate manual 
> implementation.

Speaking of which, what do you suppose the hit/miss ratio would be WRT 
synthesized `Equatable`, etc, if we introduced 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Tony Allevato via swift-evolution
On Wed, Sep 13, 2017 at 11:47 AM Vladimir.S  wrote:

> On 13.09.2017 20:48, Tony Allevato wrote:
> > On Wed, Sep 13, 2017 at 10:21 AM Vladimir.S via swift-evolution
> > > wrote:
> >
> > On 13.09.2017 19:08, Ondrej Barina via swift-evolution wrote:
> >  > Maybe something like this as middle ground.
> >  >
> >  > protocol Equatable {
> >  >  @syntetic static func ==(_ lhs: Self, _ rhs: Self) -> Bool
> >  > }
> >  >
> >  > protocol itself contains default implementation, but without real
> body.
> > Instead the
> >  > function is marked that the real body is generated by compiler.
> >  > There is explicit mentions of default impl (by compiler magic),
> but it does not
> >  > affects users as they would still use protocol in normal way:
> >  >
> >  > struct Foo: Equatable {  }
> >
> > Yes, I also thought about this. And personally for me it is also
> good solution, while
> > `struct S: Equatable {/*nothing*/}` will *still* lead to compiler's
> error or at least
> > warning about not implemented requirements.
> > So, I'll be explicit regarding my intention: do I want requirements
> to be
> > auto-generated or I want to do this manually.
> >
> > But still. If you see
> >
> > struct S: Equatable, Codable {
> > // a lot of lines
> > }
> >
> > you can't say right now if requirements for Equatable and/or Codable
> was implemented
> > manually or will be auto-generated without checking all the code of
> a type. This
> > knowledge can help to faster solve issues related to
> comparison/archiving.
> > So for me the best solution is still 'deriving'-like keyword, which
> adds clarity and
> > show intention without any boilerplate code:
> >
> >
> > The sentences above apply equally to non-synthesized default protocol
> implementations:
> >
> > struct S: Foo {
> >// a lot of lines
> > }
> >
> > I can't say if the requirements for Foo were implemented manually by S
> or by a
> > default implementation in Foo (which could be in a different module that
> I don't have
> > source access to) without checking all the code for S. So this can't be
> used as a
> > basis to rationalize special-casing synthesized implementations.
>
> As was noted in this thread, some people believe that protocol
> synthesizing its
> requirements by accessing type's fields is of a different kind than
> 'usual' protocol
> with default implementation.
> I belong to that camp. So, from my point of view, it is important to have
> 'deriving'-like marker for 'auto-senthesizeable' protocols as described
> above.
>

Yes, I understand that's your (and others') argument. But that argument
didn't apply to the example you gave, which was "I don't know if S
implements a requirement without looking at all of its code."  You can't
draw the line from that to "therefore S must say it explicitly derives it"
as a special case for Equatable because the same premise also applies to
non-synthesized default methods.

Unfortunately I think this thread has reached a bit of a stalemate, so I'm
not sure what else I can add. I believe that creating an entirely new axis
of protocol conformance is a very weak solution to the "risky defaults"
problem, because it's still all-or-nothing; it doesn't move users any
closer to the goal of eliminating boilerplate by leveraging synthesis. The
risk space isn't unknown—it can be fully described today because the number
of protocols that support synthesis are few and finite. The risky
situations presented so far have been of the form "I have a type where some
property shouldn't be compared, but the compiler does by default anyway",
then it's *very* hard for me to support solutions that say "just disable
synthesis, but you still have to implement ==/hashValue/etc. by hand" when
I can envision solutions that instead say "just tag the single property
with appropriate semantics and the compiler can now do what I wanted it to."

Make the compiler work for you—don't make you work for the compiler.



>
> Also, some 'usual' protocol Foo can have no default implementations at the
> moment of
> *writing* the code, but can have them at the moment of *compilation* via
> protocol
> extension in separate file in project. So it is not possible to require
> similar
> marker for such protocol.
> But Equatable/Hashable/Codable protocols has auto-generation feature
> already at the
> moment of writing the code and we can request that marker.
>
> Vladimir.
>
> >
> >
> > struct S: Equatable, deriving Codable {
> > // all clear:
> > // manually implemented Equatable
> > // auto-generated Codable
> >
> > // a lot of lines
> > }
> >
> > Vladimir.
> >
> >  >
> >  > Ondrej B.
> >  >
> >  > On Wed, Sep 13, 2017 at 4:14 PM, Haravikk via swift-evolution
> >  > 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Nevin Brackett-Rozinsky via swift-evolution
On Wed, Sep 13, 2017 at 2:47 PM, Vladimir.S via swift-evolution <
swift-evolution@swift.org> wrote:
>
>
> As was noted in this thread, some people believe that protocol
> synthesizing its requirements by accessing type's fields is of a different
> kind than 'usual' protocol with default implementation.
> I belong to that camp. So, from my point of view, it is important to have
> 'deriving'-like marker for 'auto-senthesizeable' protocols as described
> above.


This is a distinction without a difference
.
Witness:

To the *author* of a type, there is no difference between a default
implementation provided by a protocol extension, and one provided by
compiler magic. In both cases the author simply conforms to the protocol
and their type obtains the default method implementation which they may
choose to override.

To the *maintainer* of a type, there is no difference between the two
possible sources of a default implementation. They see that the type
conforms, and that it does not implement the requirement, so they surmise a
default implementation is in play, which they may choose to override.

To the *user* of a type, there is no difference either. They simply make
use of the existing conformance, which means they can call the methods
defined by the protocol.

The only interested party for whom the distinction is material, is the
author of the protocol itself. And even there, the only difference is that
with compiler magic the default implementation does not need to be written
in a protocol extension.

***

Personally, I am *delighted* at where SE-0185 ended up. It makes simple
cases simple, without changing what needs to be done for complex cases.

If we had been required to write an extra word like “deriving” or “auto”,
that would make declarations for simple types more verbose and ugly, with
no change to the complex case. It would be all cost and no benefit.

The way it is, though, we get both elegance and ease of use. And when we
eventually add the “@transient” attribute, many of the currently-complex
cases will become much simpler. We are in a good place, on the road to a
better place, and the proposed modification in this thread would dig a hole
in the pavement.

Nevin
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Vladimir.S via swift-evolution

On 13.09.2017 20:48, Tony Allevato wrote:
On Wed, Sep 13, 2017 at 10:21 AM Vladimir.S via swift-evolution 
> wrote:


On 13.09.2017 19:08, Ondrej Barina via swift-evolution wrote:
 > Maybe something like this as middle ground.
 >
 > protocol Equatable {
 >  @syntetic static func ==(_ lhs: Self, _ rhs: Self) -> Bool
 > }
 >
 > protocol itself contains default implementation, but without real body.
Instead the
 > function is marked that the real body is generated by compiler.
 > There is explicit mentions of default impl (by compiler magic), but it 
does not
 > affects users as they would still use protocol in normal way:
 >
 > struct Foo: Equatable {  }

Yes, I also thought about this. And personally for me it is also good 
solution, while
`struct S: Equatable {/*nothing*/}` will *still* lead to compiler's error 
or at least
warning about not implemented requirements.
So, I'll be explicit regarding my intention: do I want requirements to be
auto-generated or I want to do this manually.

But still. If you see

struct S: Equatable, Codable {
// a lot of lines
}

you can't say right now if requirements for Equatable and/or Codable was 
implemented
manually or will be auto-generated without checking all the code of a type. 
This
knowledge can help to faster solve issues related to comparison/archiving.
So for me the best solution is still 'deriving'-like keyword, which adds 
clarity and
show intention without any boilerplate code:


The sentences above apply equally to non-synthesized default protocol 
implementations:

struct S: Foo {
   // a lot of lines
}

I can't say if the requirements for Foo were implemented manually by S or by a 
default implementation in Foo (which could be in a different module that I don't have 
source access to) without checking all the code for S. So this can't be used as a 
basis to rationalize special-casing synthesized implementations.


As was noted in this thread, some people believe that protocol synthesizing its 
requirements by accessing type's fields is of a different kind than 'usual' protocol 
with default implementation.
I belong to that camp. So, from my point of view, it is important to have 
'deriving'-like marker for 'auto-senthesizeable' protocols as described above.


Also, some 'usual' protocol Foo can have no default implementations at the moment of 
*writing* the code, but can have them at the moment of *compilation* via protocol 
extension in separate file in project. So it is not possible to require similar 
marker for such protocol.
But Equatable/Hashable/Codable protocols has auto-generation feature already at the 
moment of writing the code and we can request that marker.


Vladimir.




struct S: Equatable, deriving Codable {
// all clear:
// manually implemented Equatable
// auto-generated Codable

// a lot of lines
}

Vladimir.

 >
 > Ondrej B.
 >
 > On Wed, Sep 13, 2017 at 4:14 PM, Haravikk via swift-evolution
 > 
>> 
wrote:
 >
 >
 >> On 13 Sep 2017, at 03:26, Xiaodi Wu 
 >> >> wrote:
 >>
 >> On Tue, Sep 12, 2017 at 11:43 AM, Haravikk via
 >> swift-evolution >>wrote:
 >>
 >>
 >>> On 12 Sep 2017, at 12:08, Xiaodi Wu 
 >>> >> 
wrote:
 >>>
  On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution
  
>> 
wrote:
 
  See, this is another flawed assumption; you are assuming 
that
  omitting a custom implementation of == is always 
intentional rather
  than an oversight, which is not guaranteed. This is one 
of my
gripes
  with the retroactive change to Equatable, as it is
  currently*impossible* to omit an implementation.
 >>>
 >>>
 >>> Again, this applies equally to the addition of _any_ default
 >>> implementation. And again, such changes don’t even require 
Swift
Evolution
 >>> approval.
 >>
 >> So what? Because the Swift Evolution process is currently 
deficient we
 >> should just give up on discussing 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Tony Allevato via swift-evolution
On Wed, Sep 13, 2017 at 10:21 AM Vladimir.S via swift-evolution <
swift-evolution@swift.org> wrote:

> On 13.09.2017 19:08, Ondrej Barina via swift-evolution wrote:
> > Maybe something like this as middle ground.
> >
> > protocol Equatable {
> >  @syntetic static func ==(_ lhs: Self, _ rhs: Self) -> Bool
> > }
> >
> > protocol itself contains default implementation, but without real body.
> Instead the
> > function is marked that the real body is generated by compiler.
> > There is explicit mentions of default impl (by compiler magic), but it
> does not
> > affects users as they would still use protocol in normal way:
> >
> > struct Foo: Equatable {  }
>
> Yes, I also thought about this. And personally for me it is also good
> solution, while
> `struct S: Equatable {/*nothing*/}` will *still* lead to compiler's error
> or at least
> warning about not implemented requirements.
> So, I'll be explicit regarding my intention: do I want requirements to be
> auto-generated or I want to do this manually.
>
> But still. If you see
>
> struct S: Equatable, Codable {
>// a lot of lines
> }
>
> you can't say right now if requirements for Equatable and/or Codable was
> implemented
> manually or will be auto-generated without checking all the code of a
> type. This
> knowledge can help to faster solve issues related to comparison/archiving.
> So for me the best solution is still 'deriving'-like keyword, which adds
> clarity and
> show intention without any boilerplate code:
>

The sentences above apply equally to non-synthesized default protocol
implementations:

struct S: Foo {
  // a lot of lines
}

I can't say if the requirements for Foo were implemented manually by S or
by a default implementation in Foo (which could be in a different module
that I don't have source access to) without checking all the code for S. So
this can't be used as a basis to rationalize special-casing synthesized
implementations.



>
> struct S: Equatable, deriving Codable {
>// all clear:
>// manually implemented Equatable
>// auto-generated Codable
>
>// a lot of lines
> }
>
> Vladimir.
>
> >
> > Ondrej B.
> >
> > On Wed, Sep 13, 2017 at 4:14 PM, Haravikk via swift-evolution
> > > wrote:
> >
> >
> >> On 13 Sep 2017, at 03:26, Xiaodi Wu  >> > wrote:
> >>
> >> On Tue, Sep 12, 2017 at 11:43 AM, Haravikk via
> >> swift-evolution>wrote:
> >>
> >>
> >>> On 12 Sep 2017, at 12:08, Xiaodi Wu  >>> > wrote:
> >>>
>  On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution
>  >
> wrote:
> 
>  See, this is another flawed assumption; you are assuming
> that
>  omitting a custom implementation of == is always
> intentional rather
>  than an oversight, which is not guaranteed. This is one
> of my gripes
>  with the retroactive change to Equatable, as it is
>  currently*impossible* to omit an implementation.
> >>>
> >>>
> >>> Again, this applies equally to the addition of _any_ default
> >>> implementation. And again, such changes don’t even require
> Swift Evolution
> >>> approval.
> >>
> >> So what? Because the Swift Evolution process is currently
> deficient we
> >> should just give up on discussing problems with features and
> the language
> >> altogether?
> >>
> >>
> >> I don't claim that it's a deficiency; I claim it's reflective of
> Swift's
> >> opinionated take on default implementations. Are you, after all,
> saying that
> >> you have a problem with the addition of _any_ default
> implementation to an
> >> existing protocol? If so, this conversation isn't about
> synthesis/reflection at
> >> all.
> >
> > No, and you should know that by now. I suggest actually reading some
> of what I
> > have written as I am sick of repeating myself.
> >
> >> And precisely what kind of "evidence" am I expected to
> give? This
> >> is a set of features that*do not exist yet*, I am
> trying to argue
> >> in favour of an explicit end-developer centric opt-in
> rather than
> >> an implicit protocol designer centric one. Yet no-one
> seems
> >> interested in the merits of allowing developers to
> choose what they
> >> want, rather than having implicit behaviours appear
> potentially
> >> unexpectedly.
> >
> > Both options were examined for Codable and for
> Equatable/Hashable.
> > The community and core team decided to prefer the
> current design. At
> > this point, new insights that arise 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Tony Allevato via swift-evolution
On Wed, Sep 13, 2017 at 10:03 AM Vladimir.S  wrote:

> On 13.09.2017 19:03, Tony Allevato wrote:
> >
> >
> > On Wed, Sep 13, 2017 at 8:41 AM Vladimir.S via swift-evolution
> > > wrote:
> >
> > On 13.09.2017 7:14, Xiaodi Wu via swift-evolution wrote:
> >  >
> >  > On Tue, Sep 12, 2017 at 22:07 Tony Allevato <
> tony.allev...@gmail.com
> > 
> >  > >>
> wrote:
> >  >
> >  > On Tue, Sep 12, 2017 at 7:10 PM Xiaodi Wu <
> xiaodi...@gmail.com
> > 
> >  > >>
> wrote:
> >  >
> >  > On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via
> swift-evolution
> >  > 
> > >>
> wrote:
> >  >
> >  > Good arguments, Tony, you have convinced me on all
> points.
> > Transient is
> >  > the way to go. Thank you for your patience!
> >  >
> >  >
> >  > On many points, I agree with Tony, but I disagree that
> "transient"
> > addresses
> >  > the issue at hand. The challenge being made is that, as
> Gwendal puts
> > it, it's
> >  > _unwise_ to have a default implementation, because people
> might forget
> > that
> >  > there is a default implementation. "Transient" only works
> if you remember
> >  > that there is a default implementation, and in that case,
> we already
> > have a
> >  > clear syntax for overriding the default.
> >  >
> >  >
> >  > RightБ─■I hope it hasn't sounded like I'm conflating the two
> concepts
> > completely.
> >  > The reason I brought up "transient" is because nearly all of
> the "risky"
> > examples
> >  > being cited so far have been of the variety "I have a type
> where some
> > properties
> >  > happen to be Equatable but shouldn't be involved in
> equality", so my intention
> >  > has been to show that if we have a better solution to that
> specific problem
> >  > (which is, related to but not the same as the question at
> hand), then there
> >  > aren't enough risky cases left to warrant adding this level
> of complexity
> > to the
> >  > protocol system.
> >  >
> >  >
> >  > As others point out, there's a temptation here to write
> things like
> >  > "transient(Equatable)" so as to control the synthesis of
> > implementations on a
> >  > per-protocol basis. By that point, you've invented a
> whole new syntax for
> >  > implementing protocol requirements. (Ah, you might say,
> but it's hard to
> >  > write a good hashValue implementation: sure, but that's
> adequately
> > solved by
> >  > a library-supplied combineHashes() function.)
> >  >
> >  >
> >  > I totally agree with this. A design that would try to
> annotate "transient"
> > with a
> >  > protocol or list of protocols is missing the point of the
> semantics that
> >  > "transient" is supposed to provide. It's not a series of
> switches to that
> > can be
> >  > flipped on and off for arbitrary protocolsБ─■it's a semantic
> tag that assigns
> >  > additional meaning to properties and certain protocols (such
> as Equatable,
> >  > Hashable, and Codable, but possibly others that haven't been
> designed yet)
> > would
> >  > have protocol-specific behavior for those properties.
> >  >
> >  > To better explain what I've been poking at, I'm kind of
> extrapolating this
> > out to
> >  > a possible future where it may be possible to more generally
> (1) define custom
> >  > @attributes in Swift, like Java annotations, and then (2) use
> some
> >  > metaprogramming constructs to generate introspective default
> > implementations for
> >  > a protocol at compile-time just as the compiler does
> "magically" now, and the
> >  > generator would be able to query attributes that are defined
> by the same
> > library
> >  > author as the protocol and handle them accordingly.
> >  >
> >  > In a world where that's possible, I think it's less helpful
> to think in
> > terms of
> >  > "I need to distinguish between conforming to X and getting a
> synthesized
> >  > implementation and conforming to X and avoiding the
> synthesized implementation
> >  > because the default might be risky", but instead to think in
> terms of "How
> > can I
> >  > provide enough semantic information about my types to remove
> the 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Vladimir.S via swift-evolution

On 13.09.2017 15:34, Brent Royal-Gordon via swift-evolution wrote:
On Sep 13, 2017, at 4:21 AM, Gwendal Roué via swift-evolution 
> wrote:


If I take on my free time exposing issues, it's because I hope that maybe some 
reader will consider them with proper attention, then maybe agree that there is 
an issue worth investigating, and then many conclude that a made decision has to 
be reverted. That's a multi-step process. And that process starts with a proper 
read of the issues that have been exposed.


Keep in mind that by posting to this list, you are also demanding other people 
spend their free time on the issue. And again, these issues have already been 
discussed. If a point is made once but doesn't carry the day, repeating it again 
and again doesn't make it more convincing.


The fact that you fail at evaluating the relevance of an issue, as exemplified by 
the fact that you never answer directly to the described problems, does not make 
that issue moot. Instead, it may well end in the ears of people who have been more 
engaged in the subject: Tony Allevato as the author of SE-0185, and Chris Lattner 
the review manager.


The posts in this thread have grown a bit nasty and personal. Before we reach the 
level of CoC violations over a single keyword, can we all take a deep breath and try 
to approach this more cordially?


("Gentlemen, you can't fight in here! This is the War Room!")



Agree.

Btw, I believe this thread could be closed by core team with just one message like 
"We are not going to allow Codable have a special 'deriving'-like keyword at the 
moment of conformance to produce auto-synthesized requirement, and so 
Equatable/Hashable will not have such. This decision was made and will not be changed."
Right now it seems like core team is reading different opinions regarding this 
subject and so probably(I hope) this discussion has a sense.


Vladimir.


--
Brent Royal-Gordon
Architechies



___
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


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Vladimir.S via swift-evolution

On 13.09.2017 19:08, Ondrej Barina via swift-evolution wrote:

Maybe something like this as middle ground.

protocol Equatable {
 @syntetic static func ==(_ lhs: Self, _ rhs: Self) -> Bool
}

protocol itself contains default implementation, but without real body. Instead the 
function is marked that the real body is generated by compiler.
There is explicit mentions of default impl (by compiler magic), but it does not 
affects users as they would still use protocol in normal way:


struct Foo: Equatable {  }


Yes, I also thought about this. And personally for me it is also good solution, while 
`struct S: Equatable {/*nothing*/}` will *still* lead to compiler's error or at least 
warning about not implemented requirements.
So, I'll be explicit regarding my intention: do I want requirements to be 
auto-generated or I want to do this manually.


But still. If you see

struct S: Equatable, Codable {
  // a lot of lines
}

you can't say right now if requirements for Equatable and/or Codable was implemented 
manually or will be auto-generated without checking all the code of a type. This 
knowledge can help to faster solve issues related to comparison/archiving.
So for me the best solution is still 'deriving'-like keyword, which adds clarity and 
show intention without any boilerplate code:


struct S: Equatable, deriving Codable {
  // all clear:
  // manually implemented Equatable
  // auto-generated Codable

  // a lot of lines
}

Vladimir.



Ondrej B.

On Wed, Sep 13, 2017 at 4:14 PM, Haravikk via swift-evolution 
> wrote:




On 13 Sep 2017, at 03:26, Xiaodi Wu > wrote:

On Tue, Sep 12, 2017 at 11:43 AM, Haravikk via
swift-evolution>wrote:



On 12 Sep 2017, at 12:08, Xiaodi Wu > wrote:


On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution
> wrote:

See, this is another flawed assumption; you are assuming that
omitting a custom implementation of == is always intentional rather
than an oversight, which is not guaranteed. This is one of my gripes
with the retroactive change to Equatable, as it is
currently*impossible* to omit an implementation.



Again, this applies equally to the addition of _any_ default
implementation. And again, such changes don’t even require Swift 
Evolution
approval.


So what? Because the Swift Evolution process is currently deficient we
should just give up on discussing problems with features and the 
language
altogether?


I don't claim that it's a deficiency; I claim it's reflective of Swift's
opinionated take on default implementations. Are you, after all, saying that
you have a problem with the addition of _any_ default implementation to an
existing protocol? If so, this conversation isn't about 
synthesis/reflection at
all.


No, and you should know that by now. I suggest actually reading some of 
what I
have written as I am sick of repeating myself.


And precisely what kind of "evidence" am I expected to give? This
is a set of features that*do not exist yet*, I am trying to argue
in favour of an explicit end-developer centric opt-in rather than
an implicit protocol designer centric one. Yet no-one seems
interested in the merits of allowing developers to choose what they
want, rather than having implicit behaviours appear potentially
unexpectedly.


Both options were examined for Codable and for Equatable/Hashable.
The community and core team decided to prefer the current design. At
this point, new insights that arise which could not be anticipated
at the time of review could prompt revision. However, so far, you
have presented arguments already considered during review.


And so far all I have heard about this is how it was "decided";
no-one seems interested in showing how any of these concerns were
addressed (if at all), so as far as I can tell they were not, or 
they
were wilfully ignored.



They were addressed by being considered.


And yet no-one can apparently summarise what those "considerations" 
might
be, suggesting that they were either *not* considered at all, or that 
the
"consideration" was so weak that no-one is willing to step forward to
defend it. Either way it is not sufficient by any reasonable measure.

If I were to run over your foot in my car, would you be happy to accept
that I "considered" it first?


How do you mean? People wrote 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Vladimir.S via swift-evolution

On 13.09.2017 19:03, Tony Allevato wrote:



On Wed, Sep 13, 2017 at 8:41 AM Vladimir.S via swift-evolution 
> wrote:


On 13.09.2017 7:14, Xiaodi Wu via swift-evolution wrote:
 >
 > On Tue, Sep 12, 2017 at 22:07 Tony Allevato 
 > >> wrote:
 >
 > On Tue, Sep 12, 2017 at 7:10 PM Xiaodi Wu 
 > >> wrote:
 >
 > On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via 
swift-evolution
 > 
>> 
wrote:
 >
 > Good arguments, Tony, you have convinced me on all points.
Transient is
 > the way to go. Thank you for your patience!
 >
 >
 > On many points, I agree with Tony, but I disagree that 
"transient"
addresses
 > the issue at hand. The challenge being made is that, as Gwendal 
puts
it, it's
 > _unwise_ to have a default implementation, because people might 
forget
that
 > there is a default implementation. "Transient" only works if you 
remember
 > that there is a default implementation, and in that case, we 
already
have a
 > clear syntax for overriding the default.
 >
 >
 > RightБ─■I hope it hasn't sounded like I'm conflating the two concepts
completely.
 > The reason I brought up "transient" is because nearly all of the 
"risky"
examples
 > being cited so far have been of the variety "I have a type where some
properties
 > happen to be Equatable but shouldn't be involved in equality", so my 
intention
 > has been to show that if we have a better solution to that specific 
problem
 > (which is, related to but not the same as the question at hand), 
then there
 > aren't enough risky cases left to warrant adding this level of 
complexity
to the
 > protocol system.
 >
 >
 > As others point out, there's a temptation here to write things 
like
 > "transient(Equatable)" so as to control the synthesis of
implementations on a
 > per-protocol basis. By that point, you've invented a whole new 
syntax for
 > implementing protocol requirements. (Ah, you might say, but it's 
hard to
 > write a good hashValue implementation: sure, but that's 
adequately
solved by
 > a library-supplied combineHashes() function.)
 >
 >
 > I totally agree with this. A design that would try to annotate 
"transient"
with a
 > protocol or list of protocols is missing the point of the semantics 
that
 > "transient" is supposed to provide. It's not a series of switches to 
that
can be
 > flipped on and off for arbitrary protocolsБ─■it's a semantic tag 
that assigns
 > additional meaning to properties and certain protocols (such as 
Equatable,
 > Hashable, and Codable, but possibly others that haven't been 
designed yet)
would
 > have protocol-specific behavior for those properties.
 >
 > To better explain what I've been poking at, I'm kind of 
extrapolating this
out to
 > a possible future where it may be possible to more generally (1) 
define custom
 > @attributes in Swift, like Java annotations, and then (2) use some
 > metaprogramming constructs to generate introspective default
implementations for
 > a protocol at compile-time just as the compiler does "magically" 
now, and the
 > generator would be able to query attributes that are defined by the 
same
library
 > author as the protocol and handle them accordingly.
 >
 > In a world where that's possible, I think it's less helpful to think 
in
terms of
 > "I need to distinguish between conforming to X and getting a 
synthesized
 > implementation and conforming to X and avoiding the synthesized 
implementation
 > because the default might be risky", but instead to think in terms of 
"How
can I
 > provide enough semantic information about my types to remove the 
risk?"
 >
 > In other words, the switches we offer developers to flip shouldn't 
be about
 > turning on/off entire features, but about giving the compiler enough
information
 > to make it smart enough that we never need to turn it off in the 
first
place. As
 > I alluded to before, if I have 10 properties in a type and only 1 of 
those
needs
 > to be ignored in ==/hashValue/whatever, writing "Equatable" 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Vladimir.S via swift-evolution


On 13.09.2017 17:13, Haravikk via swift-evolution wrote:


Well, certainly, synthesized default implementations differ from non-synthesized 
ones in key respects. However, they do not differ in terms of the user experience 
of conforming to the protocol and having to override the default.


Except that that's not true at all, is it?

Synthesised default implementations go much further in how they attempt (and 
potentially fail) to implement those defaults, and in the specific case of 
Equatable/Hashable they are fully implementing a protocol without a single property 
of method being raised as a requirement; they are utterly different at a fundamental 
level, no amount of mental contortion changes that fact.


FWIW Fully agree with Haravikk. Just want to add my 2 cents. We hear an opinion that 
protocol with auto-synthesization of requirements should be treated as a normal 
protocol with deault implenentation. So, this is just a variant of default 
implementation.


Actually I can agree with this. *BUT.* Such a *well-declared* protocol, which uses 
macros/reflection/other to access *type's fields* to implement the default methods 
IMO should also be explicitly conformed with 'deriving'-like keyword to be able to 
synthesize methods. For example, as first thoughts, such protocol should be marked 
with some kind of @synthesizable directive and probably have some helpers in this 
case from compiler to implement synthesizable defaults. Yes, one probably can 
implement protocol which uses macros/reflection without @synthesizable directive for 
protocol, but this should be considered as not-well-formed protocol.


Vladimir.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Ondrej Barina via swift-evolution
Maybe something like this as middle ground.

protocol Equatable {
@syntetic static func ==(_ lhs: Self, _ rhs: Self) -> Bool
}

protocol itself contains default implementation, but without real body.
Instead the function is marked that the real body is generated by compiler.
There is explicit mentions of default impl (by compiler magic), but it does
not affects users as they would still use protocol in normal way:

struct Foo: Equatable {  }

Ondrej B.

On Wed, Sep 13, 2017 at 4:14 PM, Haravikk via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On 13 Sep 2017, at 03:26, Xiaodi Wu  wrote:
>
> On Tue, Sep 12, 2017 at 11:43 AM, Haravikk via swift-evolution  evolut...@swift.org> wrote:
>
>>
>> On 12 Sep 2017, at 12:08, Xiaodi Wu  wrote:
>>
>> On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> See, this is another flawed assumption; you are assuming that omitting a
>>> custom implementation of == is always intentional rather than an oversight,
>>> which is not guaranteed. This is one of my gripes with the retroactive
>>> change to Equatable, as it is currently *impossible* to omit an
>>> implementation.
>>>
>>
>> Again, this applies equally to the addition of _any_ default
>> implementation. And again, such changes don’t even require Swift Evolution
>> approval.
>>
>>
>> So what? Because the Swift Evolution process is currently deficient we
>> should just give up on discussing problems with features and the language
>> altogether?
>>
>
> I don't claim that it's a deficiency; I claim it's reflective of Swift's
> opinionated take on default implementations. Are you, after all, saying
> that you have a problem with the addition of _any_ default implementation
> to an existing protocol? If so, this conversation isn't about
> synthesis/reflection at all.
>
>
> No, and you should know that by now. I suggest actually reading some of
> what I have written as I am sick of repeating myself.
>
> And precisely what kind of "evidence" am I expected to give? This is a set
>>> of features that *do not exist yet*, I am trying to argue in favour of
>>> an explicit end-developer centric opt-in rather than an implicit protocol
>>> designer centric one. Yet no-one seems interested in the merits of allowing
>>> developers to choose what they want, rather than having implicit behaviours
>>> appear potentially unexpectedly.
>>>
>>>
>>> Both options were examined for Codable and for Equatable/Hashable. The
>>> community and core team decided to prefer the current design. At this
>>> point, new insights that arise which could not be anticipated at the time
>>> of review could prompt revision. However, so far, you have presented
>>> arguments already considered during review.
>>>
>>>
>>> And so far all I have heard about this is how it was "decided"; no-one
>>> seems interested in showing how any of these concerns were addressed (if at
>>> all), so as far as I can tell they were not, or they were wilfully ignored.
>>>
>>
>> They were addressed by being considered.
>>
>>
>> And yet no-one can apparently summarise what those "considerations" might
>> be, suggesting that they were either *not* considered at all, or that
>> the "consideration" was so weak that no-one is willing to step forward to
>> defend it. Either way it is not sufficient by any reasonable measure.
>>
>> If I were to run over your foot in my car, would you be happy to accept
>> that I "considered" it first?
>>
>
> How do you mean? People wrote in with their opinions. Then, taking into
> account the community's response, the proposal was approved.
>
>
> I mean because not once have you summarised what these alleged
> "considerations" were; if they exist then you should be able do so, yet all
> I am hearing is "it was considered", which frankly is not an argument at
> all as it is entirely without substance.
>
> If it was genuinely considered then someone should be able to say what
> points were considered and what conclusions were reached and why. And even
> if there *was* an earlier decision, that doesn't necessarily make it
> right. We are discussing it now, and it is clear that any decision that has
> been made has been made poorly at best.
>
> And if you're talking about the discussion on Equatable/Hashable
> specifically, I'm afraid your memory of the "considerations" is radically
> different to mine; as the concerns I raised were essentially ignored, as
> not a single person gave a justification more substantial than "but, but
> Codable!" which frankly isn't a justification at all.
>
> Therefore, your argument reduces to one about which default
 implementations generally ought or ought not to be provided--that is, that
 they ought to be provided only when their correctness can be guaranteed for
 all (rather than almost all) possible conforming types. To which point I
 sketched a rebuttal above.


 If a protocol defines 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Tony Allevato via swift-evolution
On Wed, Sep 13, 2017 at 8:41 AM Vladimir.S via swift-evolution <
swift-evolution@swift.org> wrote:

> On 13.09.2017 7:14, Xiaodi Wu via swift-evolution wrote:
> >
> > On Tue, Sep 12, 2017 at 22:07 Tony Allevato  > > wrote:
> >
> > On Tue, Sep 12, 2017 at 7:10 PM Xiaodi Wu  > > wrote:
> >
> > On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via
> swift-evolution
> > >
> wrote:
> >
> > Good arguments, Tony, you have convinced me on all points.
> Transient is
> > the way to go. Thank you for your patience!
> >
> >
> > On many points, I agree with Tony, but I disagree that
> "transient" addresses
> > the issue at hand. The challenge being made is that, as Gwendal
> puts it, it's
> > _unwise_ to have a default implementation, because people might
> forget that
> > there is a default implementation. "Transient" only works if you
> remember
> > that there is a default implementation, and in that case, we
> already have a
> > clear syntax for overriding the default.
> >
> >
> > RightБ─■I hope it hasn't sounded like I'm conflating the two
> concepts completely.
> > The reason I brought up "transient" is because nearly all of the
> "risky" examples
> > being cited so far have been of the variety "I have a type where
> some properties
> > happen to be Equatable but shouldn't be involved in equality", so my
> intention
> > has been to show that if we have a better solution to that specific
> problem
> > (which is, related to but not the same as the question at hand),
> then there
> > aren't enough risky cases left to warrant adding this level of
> complexity to the
> > protocol system.
> >
> >
> > As others point out, there's a temptation here to write things
> like
> > "transient(Equatable)" so as to control the synthesis of
> implementations on a
> > per-protocol basis. By that point, you've invented a whole new
> syntax for
> > implementing protocol requirements. (Ah, you might say, but it's
> hard to
> > write a good hashValue implementation: sure, but that's
> adequately solved by
> > a library-supplied combineHashes() function.)
> >
> >
> > I totally agree with this. A design that would try to annotate
> "transient" with a
> > protocol or list of protocols is missing the point of the semantics
> that
> > "transient" is supposed to provide. It's not a series of switches to
> that can be
> > flipped on and off for arbitrary protocolsБ─■it's a semantic tag
> that assigns
> > additional meaning to properties and certain protocols (such as
> Equatable,
> > Hashable, and Codable, but possibly others that haven't been
> designed yet) would
> > have protocol-specific behavior for those properties.
> >
> > To better explain what I've been poking at, I'm kind of
> extrapolating this out to
> > a possible future where it may be possible to more generally (1)
> define custom
> > @attributes in Swift, like Java annotations, and then (2) use some
> > metaprogramming constructs to generate introspective default
> implementations for
> > a protocol at compile-time just as the compiler does "magically"
> now, and the
> > generator would be able to query attributes that are defined by the
> same library
> > author as the protocol and handle them accordingly.
> >
> > In a world where that's possible, I think it's less helpful to think
> in terms of
> > "I need to distinguish between conforming to X and getting a
> synthesized
> > implementation and conforming to X and avoiding the synthesized
> implementation
> > because the default might be risky", but instead to think in terms
> of "How can I
> > provide enough semantic information about my types to remove the
> risk?"
> >
> > In other words, the switches we offer developers to flip shouldn't
> be about
> > turning on/off entire features, but about giving the compiler enough
> information
> > to make it smart enough that we never need to turn it off in the
> first place. As
> > I alluded to before, if I have 10 properties in a type and only 1 of
> those needs
> > to be ignored in ==/hashValue/whatever, writing "Equatable" instead
> of "derives
> > Equatable" isn't all that helpful. Yes, it spits out an error
> message where there
> > wouldn't have been one, but it doesn't reduce any of the burden of
> having to
> > provide the appropriate manual implementation.
> >
> > But all that stuff about custom attributes and metaprogramming
> introspection is a
> > big topic of it's own that isn't going to be solved in Swift 5, so
> this is a bit
> > of a digression. :)
> >
> >
> > That said, we could have enums EquatingKeys and 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Vladimir.S via swift-evolution

On 13.09.2017 7:14, Xiaodi Wu via swift-evolution wrote:


On Tue, Sep 12, 2017 at 22:07 Tony Allevato > wrote:


On Tue, Sep 12, 2017 at 7:10 PM Xiaodi Wu > wrote:

On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via swift-evolution
> wrote:

Good arguments, Tony, you have convinced me on all points. 
Transient is
the way to go. Thank you for your patience!


On many points, I agree with Tony, but I disagree that "transient" 
addresses
the issue at hand. The challenge being made is that, as Gwendal puts 
it, it's
_unwise_ to have a default implementation, because people might forget 
that
there is a default implementation. "Transient" only works if you 
remember
that there is a default implementation, and in that case, we already 
have a
clear syntax for overriding the default.


RightБ─■I hope it hasn't sounded like I'm conflating the two concepts 
completely.
The reason I brought up "transient" is because nearly all of the "risky" 
examples
being cited so far have been of the variety "I have a type where some 
properties
happen to be Equatable but shouldn't be involved in equality", so my 
intention
has been to show that if we have a better solution to that specific problem
(which is, related to but not the same as the question at hand), then there
aren't enough risky cases left to warrant adding this level of complexity 
to the
protocol system.


As others point out, there's a temptation here to write things like
"transient(Equatable)" so as to control the synthesis of 
implementations on a
per-protocol basis. By that point, you've invented a whole new syntax 
for
implementing protocol requirements. (Ah, you might say, but it's hard to
write a good hashValue implementation: sure, but that's adequately 
solved by
a library-supplied combineHashes() function.)


I totally agree with this. A design that would try to annotate "transient" 
with a
protocol or list of protocols is missing the point of the semantics that
"transient" is supposed to provide. It's not a series of switches to that 
can be
flipped on and off for arbitrary protocolsБ─■it's a semantic tag that 
assigns
additional meaning to properties and certain protocols (such as Equatable,
Hashable, and Codable, but possibly others that haven't been designed yet) 
would
have protocol-specific behavior for those properties.

To better explain what I've been poking at, I'm kind of extrapolating this 
out to
a possible future where it may be possible to more generally (1) define 
custom
@attributes in Swift, like Java annotations, and then (2) use some
metaprogramming constructs to generate introspective default 
implementations for
a protocol at compile-time just as the compiler does "magically" now, and 
the
generator would be able to query attributes that are defined by the same 
library
author as the protocol and handle them accordingly.

In a world where that's possible, I think it's less helpful to think in 
terms of
"I need to distinguish between conforming to X and getting a synthesized
implementation and conforming to X and avoiding the synthesized 
implementation
because the default might be risky", but instead to think in terms of "How 
can I
provide enough semantic information about my types to remove the risk?"

In other words, the switches we offer developers to flip shouldn't be about
turning on/off entire features, but about giving the compiler enough 
information
to make it smart enough that we never need to turn it off in the first 
place. As
I alluded to before, if I have 10 properties in a type and only 1 of those 
needs
to be ignored in ==/hashValue/whatever, writing "Equatable" instead of 
"derives
Equatable" isn't all that helpful. Yes, it spits out an error message where 
there
wouldn't have been one, but it doesn't reduce any of the burden of having to
provide the appropriate manual implementation.

But all that stuff about custom attributes and metaprogramming 
introspection is a
big topic of it's own that isn't going to be solved in Swift 5, so this is 
a bit
of a digression. :)


That said, we could have enums EquatingKeys and HashingKeys, a la CodingKeys... That 
may not be a huge leap to propose and implement.


Actually, not taking into account a question of explicit marker for auto-generated 
methods, this is IMO a great point.


Codable, which can auto-generate methods, *had* these CodingKeys from the moment of 
birth. Currently, we have a proposal for auto-generating of methods for 
Equatable/Hashable. Why we don't have a EquatingKeys/HashingKeys option for 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Haravikk via swift-evolution

> On 13 Sep 2017, at 03:26, Xiaodi Wu  wrote:
> 
> On Tue, Sep 12, 2017 at 11:43 AM, Haravikk via swift-evolution 
> > wrote:
> 
>> On 12 Sep 2017, at 12:08, Xiaodi Wu > > wrote:
>> 
>>> On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution 
>>> > wrote:
>>> See, this is another flawed assumption; you are assuming that omitting a 
>>> custom implementation of == is always intentional rather than an oversight, 
>>> which is not guaranteed. This is one of my gripes with the retroactive 
>>> change to Equatable, as it is currently impossible to omit an 
>>> implementation.
>> 
>> Again, this applies equally to the addition of _any_ default implementation. 
>> And again, such changes don’t even require Swift Evolution approval.
> 
> So what? Because the Swift Evolution process is currently deficient we should 
> just give up on discussing problems with features and the language altogether?
> 
> I don't claim that it's a deficiency; I claim it's reflective of Swift's 
> opinionated take on default implementations. Are you, after all, saying that 
> you have a problem with the addition of _any_ default implementation to an 
> existing protocol? If so, this conversation isn't about synthesis/reflection 
> at all.

No, and you should know that by now. I suggest actually reading some of what I 
have written as I am sick of repeating myself.

> And precisely what kind of "evidence" am I expected to give? This is a 
> set of features that do not exist yet, I am trying to argue in favour of 
> an explicit end-developer centric opt-in rather than an implicit protocol 
> designer centric one. Yet no-one seems interested in the merits of 
> allowing developers to choose what they want, rather than having implicit 
> behaviours appear potentially unexpectedly.
 
 Both options were examined for Codable and for Equatable/Hashable. The 
 community and core team decided to prefer the current design. At this 
 point, new insights that arise which could not be anticipated at the time 
 of review could prompt revision. However, so far, you have presented 
 arguments already considered during review.
>>> 
>>> And so far all I have heard about this is how it was "decided"; no-one 
>>> seems interested in showing how any of these concerns were addressed (if at 
>>> all), so as far as I can tell they were not, or they were wilfully ignored.
>> 
>> They were addressed by being considered.
> 
> And yet no-one can apparently summarise what those "considerations" might be, 
> suggesting that they were either not considered at all, or that the 
> "consideration" was so weak that no-one is willing to step forward to defend 
> it. Either way it is not sufficient by any reasonable measure.
> 
> If I were to run over your foot in my car, would you be happy to accept that 
> I "considered" it first?
> 
> How do you mean? People wrote in with their opinions. Then, taking into 
> account the community's response, the proposal was approved.

I mean because not once have you summarised what these alleged "considerations" 
were; if they exist then you should be able do so, yet all I am hearing is "it 
was considered", which frankly is not an argument at all as it is entirely 
without substance.

If it was genuinely considered then someone should be able to say what points 
were considered and what conclusions were reached and why. And even if there 
was an earlier decision, that doesn't necessarily make it right. We are 
discussing it now, and it is clear that any decision that has been made has 
been made poorly at best.

And if you're talking about the discussion on Equatable/Hashable specifically, 
I'm afraid your memory of the "considerations" is radically different to mine; 
as the concerns I raised were essentially ignored, as not a single person gave 
a justification more substantial than "but, but Codable!" which frankly isn't a 
justification at all.

> Therefore, your argument reduces to one about which default 
> implementations generally ought or ought not to be provided--that is, 
> that they ought to be provided only when their correctness can be 
> guaranteed for all (rather than almost all) possible conforming types. To 
> which point I sketched a rebuttal above.
 
 If a protocol defines something, and creates a default implementation 
 based only upon those definitions then it must by its very nature be 
 correct. A concrete type may later decided to go further, but that is a 
 feature of the concrete type, not a failure of the protocol itself which 
 can function correctly within the context it created. You want to talk 
 evidence, yet there has been no example given that proves otherwise; thus 
 far only Itai has attempted to do so, 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Brent Royal-Gordon via swift-evolution
> On Sep 13, 2017, at 4:21 AM, Gwendal Roué via swift-evolution 
>  wrote:
> 
>>> If I take on my free time exposing issues, it's because I hope that maybe 
>>> some reader will consider them with proper attention, then maybe agree that 
>>> there is an issue worth investigating, and then many conclude that a made 
>>> decision has to be reverted. That's a multi-step process. And that process 
>>> starts with a proper read of the issues that have been exposed.
>> 
>> Keep in mind that by posting to this list, you are also demanding other 
>> people spend their free time on the issue. And again, these issues have 
>> already been discussed. If a point is made once but doesn't carry the day, 
>> repeating it again and again doesn't make it more convincing.
> 
> The fact that you fail at evaluating the relevance of an issue, as 
> exemplified by the fact that you never answer directly to the described 
> problems, does not make that issue moot. Instead, it may well end in the ears 
> of people who have been more engaged in the subject: Tony Allevato as the 
> author of SE-0185, and Chris Lattner the review manager.


The posts in this thread have grown a bit nasty and personal. Before we reach 
the level of CoC violations over a single keyword, can we all take a deep 
breath and try to approach this more cordially?

("Gentlemen, you can't fight in here! This is the War Room!")

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Gwendal Roué via swift-evolution
>> If I take on my free time exposing issues, it's because I hope that maybe 
>> some reader will consider them with proper attention, then maybe agree that 
>> there is an issue worth investigating, and then many conclude that a made 
>> decision has to be reverted. That's a multi-step process. And that process 
>> starts with a proper read of the issues that have been exposed.
> 
> Keep in mind that by posting to this list, you are also demanding other 
> people spend their free time on the issue. And again, these issues have 
> already been discussed. If a point is made once but doesn't carry the day, 
> repeating it again and again doesn't make it more convincing.

The fact that you fail at evaluating the relevance of an issue, as exemplified 
by the fact that you never answer directly to the described problems, does not 
make that issue moot. Instead, it may well end in the ears of people who have 
been more engaged in the subject: Tony Allevato as the author of SE-0185, and 
Chris Lattner the review manager.

Their feedback would be especially appreciated, considering that the SE-0185 
acceptance rationale 
(https://lists.swift.org/pipermail/swift-evolution-announce/2017-August/000400.html)
 doesn't address the issues I'm please to repeat for the interested readers:

> For reference, here are some issues with implicit synthesis:
> 
> - 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039704.html
> - 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039710.html

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-13 Thread Xiaodi Wu via swift-evolution
On Wed, Sep 13, 2017 at 01:23 Gwendal Roué  wrote:

>
> Le 13 sept. 2017 à 07:35, Xiaodi Wu  a écrit :
>
>
> On Wed, Sep 13, 2017 at 00:26 Gwendal Roué  wrote:
>
>>
>> Le 13 sept. 2017 à 06:28, Xiaodi Wu  a écrit :
>>
>>
>> On Tue, Sep 12, 2017 at 23:26 Gwendal Roué 
>> wrote:
>>
>>>
>>> > Le 13 sept. 2017 à 04:05, Xiaodi Wu  a écrit :
>>> >
>>> > On Tue, Sep 12, 2017 at 2:30 PM, Gwendal Roué 
>>> wrote:
>>> > >> In none of those cases, the compiler emits any warning. It's thus
>>> easy to forget or miss the problem, and uneasy to fix it (you'll need a
>>> runtime failure to spot it, or a thorough code review).
>>> > >>
>>> > >> I hope you agree with this last sentence. This unbalance between
>>> the easiness of the mistake and the easiness of the fix should ring a bell
>>> to language designers.
>>> > >
>>> > > Suppose instead this were about a protocol named Fooable and a
>>> requirement called foo() that has a default implementation. Everything you
>>> just talked about would apply equally. Am I to understand that you are
>>> opposed to default implementations in general? If so, then that’s got
>>> nothing to do with synthesized Equatable conformance. If not, then you’ll
>>> have to justify why.
>>> >
>>> > Sounds like a good argument, until one realises that if a protocol
>>> does not provide a default implementations for a method, it may be because
>>> a default implementations is impossible to provide (the most usual case),
>>> or because it would be unwise to do so.
>>> >
>>> > And indeed, the topic currently discussed is not if we should remove
>>> or not default implementations. Instead, the question is: is it wise or not
>>> to provide an *implicit* default Equatable/Hashable/XXX implementation?
>>> >
>>> > Right, _that_ is the question. It was asked during review for the
>>> proposal, and the agreed upon answer is _yes_.
>>>
>>> Wrong. This whole thread is about *explicit* synthetic behavior;. If an
>>> agreed proposal has to be invalidated in the way, _so be it_.
>>>
>>> Gwendal
>>
>>
>> Explicit (e.g., "AutoEquatable") and implicit synthetic behavior were
>> both considered during the proposal which approved the implicit behavior.
>> This question has been asked and answered.
>>
>>
>> We're in a new thread now, which may drive the core team into
>> reconsidering a previous decision.
>>
>> It happens. You may remember a funny debate about SE-0110. In the end a
>> question that had been asked and answered got a whole new answer.
>>
>> We're all here to improve the language. That's why I sometimes
>> participate in this mailing list.
>>
>
> After implementation, sometimes new insights arise from user experience
> that weren't originally anticipated. This can prompt reconsideration.
> Again, this is not the case here; decisions made are made.
>
>
> If I take on my free time exposing issues, it's because I hope that maybe
> some reader will consider them with proper attention, then maybe agree that
> there is an issue worth investigating, and then many conclude that a made
> decision has to be reverted. That's a multi-step process. And that process
> starts with a proper read of the issues that have been exposed.
>

Keep in mind that by posting to this list, you are also demanding other
people spend their free time on the issue. And again, these issues have
already been discussed. If a point is made once but doesn't carry the day,
repeating it again and again doesn't make it more convincing.


> For reference, here are some issues with implicit synthesis:
>
> -
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039704.html
> -
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039710.html
>
> Gwendal
>

>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Wed, Sep 13, 2017 at 00:26 Gwendal Roué  wrote:

>
> Le 13 sept. 2017 à 06:28, Xiaodi Wu  a écrit :
>
>
> On Tue, Sep 12, 2017 at 23:26 Gwendal Roué  wrote:
>
>>
>> > Le 13 sept. 2017 à 04:05, Xiaodi Wu  a écrit :
>> >
>> > On Tue, Sep 12, 2017 at 2:30 PM, Gwendal Roué 
>> wrote:
>> > >> In none of those cases, the compiler emits any warning. It's thus
>> easy to forget or miss the problem, and uneasy to fix it (you'll need a
>> runtime failure to spot it, or a thorough code review).
>> > >>
>> > >> I hope you agree with this last sentence. This unbalance between the
>> easiness of the mistake and the easiness of the fix should ring a bell to
>> language designers.
>> > >
>> > > Suppose instead this were about a protocol named Fooable and a
>> requirement called foo() that has a default implementation. Everything you
>> just talked about would apply equally. Am I to understand that you are
>> opposed to default implementations in general? If so, then that’s got
>> nothing to do with synthesized Equatable conformance. If not, then you’ll
>> have to justify why.
>> >
>> > Sounds like a good argument, until one realises that if a protocol does
>> not provide a default implementations for a method, it may be because a
>> default implementations is impossible to provide (the most usual case), or
>> because it would be unwise to do so.
>> >
>> > And indeed, the topic currently discussed is not if we should remove or
>> not default implementations. Instead, the question is: is it wise or not to
>> provide an *implicit* default Equatable/Hashable/XXX implementation?
>> >
>> > Right, _that_ is the question. It was asked during review for the
>> proposal, and the agreed upon answer is _yes_.
>>
>> Wrong. This whole thread is about *explicit* synthetic behavior;. If an
>> agreed proposal has to be invalidated in the way, _so be it_.
>>
>> Gwendal
>
>
> Explicit (e.g., "AutoEquatable") and implicit synthetic behavior were both
> considered during the proposal which approved the implicit behavior. This
> question has been asked and answered.
>
>
> We're in a new thread now, which may drive the core team into
> reconsidering a previous decision.
>
> It happens. You may remember a funny debate about SE-0110. In the end a
> question that had been asked and answered got a whole new answer.
>
> We're all here to improve the language. That's why I sometimes participate
> in this mailing list.
>

After implementation, sometimes new insights arise from user experience
that weren't originally anticipated. This can prompt reconsideration.
Again, this is not the case here; decisions made are made.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Gwendal Roué via swift-evolution

> Le 13 sept. 2017 à 06:28, Xiaodi Wu  a écrit :
> 
> 
> On Tue, Sep 12, 2017 at 23:26 Gwendal Roué  > wrote:
> 
> > Le 13 sept. 2017 à 04:05, Xiaodi Wu  > > a écrit :
> >
> > On Tue, Sep 12, 2017 at 2:30 PM, Gwendal Roué  > > wrote:
> > >> In none of those cases, the compiler emits any warning. It's thus easy 
> > >> to forget or miss the problem, and uneasy to fix it (you'll need a 
> > >> runtime failure to spot it, or a thorough code review).
> > >>
> > >> I hope you agree with this last sentence. This unbalance between the 
> > >> easiness of the mistake and the easiness of the fix should ring a bell 
> > >> to language designers.
> > >
> > > Suppose instead this were about a protocol named Fooable and a 
> > > requirement called foo() that has a default implementation. Everything 
> > > you just talked about would apply equally. Am I to understand that you 
> > > are opposed to default implementations in general? If so, then that’s got 
> > > nothing to do with synthesized Equatable conformance. If not, then you’ll 
> > > have to justify why.
> >
> > Sounds like a good argument, until one realises that if a protocol does not 
> > provide a default implementations for a method, it may be because a default 
> > implementations is impossible to provide (the most usual case), or because 
> > it would be unwise to do so.
> >
> > And indeed, the topic currently discussed is not if we should remove or not 
> > default implementations. Instead, the question is: is it wise or not to 
> > provide an *implicit* default Equatable/Hashable/XXX implementation?
> >
> > Right, _that_ is the question. It was asked during review for the proposal, 
> > and the agreed upon answer is _yes_.
> 
> Wrong. This whole thread is about *explicit* synthetic behavior;. If an 
> agreed proposal has to be invalidated in the way, _so be it_.
> 
> Gwendal
> 
> Explicit (e.g., "AutoEquatable") and implicit synthetic behavior were both 
> considered during the proposal which approved the implicit behavior. This 
> question has been asked and answered.

We're in a new thread now, which may drive the core team into reconsidering a 
previous decision.

It happens. You may remember a funny debate about SE-0110. In the end a 
question that had been asked and answered got a whole new answer.

We're all here to improve the language. That's why I sometimes participate in 
this mailing list.

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Tue, Sep 12, 2017 at 23:26 Gwendal Roué  wrote:

>
> > Le 13 sept. 2017 à 04:05, Xiaodi Wu  a écrit :
> >
> > On Tue, Sep 12, 2017 at 2:30 PM, Gwendal Roué 
> wrote:
> > >> In none of those cases, the compiler emits any warning. It's thus
> easy to forget or miss the problem, and uneasy to fix it (you'll need a
> runtime failure to spot it, or a thorough code review).
> > >>
> > >> I hope you agree with this last sentence. This unbalance between the
> easiness of the mistake and the easiness of the fix should ring a bell to
> language designers.
> > >
> > > Suppose instead this were about a protocol named Fooable and a
> requirement called foo() that has a default implementation. Everything you
> just talked about would apply equally. Am I to understand that you are
> opposed to default implementations in general? If so, then that’s got
> nothing to do with synthesized Equatable conformance. If not, then you’ll
> have to justify why.
> >
> > Sounds like a good argument, until one realises that if a protocol does
> not provide a default implementations for a method, it may be because a
> default implementations is impossible to provide (the most usual case), or
> because it would be unwise to do so.
> >
> > And indeed, the topic currently discussed is not if we should remove or
> not default implementations. Instead, the question is: is it wise or not to
> provide an *implicit* default Equatable/Hashable/XXX implementation?
> >
> > Right, _that_ is the question. It was asked during review for the
> proposal, and the agreed upon answer is _yes_.
>
> Wrong. This whole thread is about *explicit* synthetic behavior;. If an
> agreed proposal has to be invalidated in the way, _so be it_.
>
> Gwendal


Explicit (e.g., "AutoEquatable") and implicit synthetic behavior were both
considered during the proposal which approved the implicit behavior. This
question has been asked and answered.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Gwendal Roué via swift-evolution

> Le 13 sept. 2017 à 04:05, Xiaodi Wu  a écrit :
> 
> On Tue, Sep 12, 2017 at 2:30 PM, Gwendal Roué  wrote:
> >> In none of those cases, the compiler emits any warning. It's thus easy to 
> >> forget or miss the problem, and uneasy to fix it (you'll need a runtime 
> >> failure to spot it, or a thorough code review).
> >>
> >> I hope you agree with this last sentence. This unbalance between the 
> >> easiness of the mistake and the easiness of the fix should ring a bell to 
> >> language designers.
> >
> > Suppose instead this were about a protocol named Fooable and a requirement 
> > called foo() that has a default implementation. Everything you just talked 
> > about would apply equally. Am I to understand that you are opposed to 
> > default implementations in general? If so, then that’s got nothing to do 
> > with synthesized Equatable conformance. If not, then you’ll have to justify 
> > why.
> 
> Sounds like a good argument, until one realises that if a protocol does not 
> provide a default implementations for a method, it may be because a default 
> implementations is impossible to provide (the most usual case), or because it 
> would be unwise to do so.
> 
> And indeed, the topic currently discussed is not if we should remove or not 
> default implementations. Instead, the question is: is it wise or not to 
> provide an *implicit* default Equatable/Hashable/XXX implementation?
> 
> Right, _that_ is the question. It was asked during review for the proposal, 
> and the agreed upon answer is _yes_.

Wrong. This whole thread is about *explicit* synthetic behavior;. If an agreed 
proposal has to be invalidated in the way, _so be it_.

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Tue, Sep 12, 2017 at 22:07 Tony Allevato  wrote:

> On Tue, Sep 12, 2017 at 7:10 PM Xiaodi Wu  wrote:
>
>> On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> Good arguments, Tony, you have convinced me on all points. Transient is
>>> the way to go. Thank you for your patience!
>>>
>>
>> On many points, I agree with Tony, but I disagree that "transient"
>> addresses the issue at hand. The challenge being made is that, as Gwendal
>> puts it, it's _unwise_ to have a default implementation, because people
>> might forget that there is a default implementation. "Transient" only works
>> if you remember that there is a default implementation, and in that case,
>> we already have a clear syntax for overriding the default.
>>
>
> Right—I hope it hasn't sounded like I'm conflating the two concepts
> completely. The reason I brought up "transient" is because nearly all of
> the "risky" examples being cited so far have been of the variety "I have a
> type where some properties happen to be Equatable but shouldn't be involved
> in equality", so my intention has been to show that if we have a better
> solution to that specific problem (which is, related to but not the same as
> the question at hand), then there aren't enough risky cases left to warrant
> adding this level of complexity to the protocol system.
>
>
>>
>> As others point out, there's a temptation here to write things like
>> "transient(Equatable)" so as to control the synthesis of implementations on
>> a per-protocol basis. By that point, you've invented a whole new syntax for
>> implementing protocol requirements. (Ah, you might say, but it's hard to
>> write a good hashValue implementation: sure, but that's adequately solved
>> by a library-supplied combineHashes() function.)
>>
>
> I totally agree with this. A design that would try to annotate "transient"
> with a protocol or list of protocols is missing the point of the semantics
> that "transient" is supposed to provide. It's not a series of switches to
> that can be flipped on and off for arbitrary protocols—it's a semantic tag
> that assigns additional meaning to properties and certain protocols (such
> as Equatable, Hashable, and Codable, but possibly others that haven't been
> designed yet) would have protocol-specific behavior for those properties.
>
> To better explain what I've been poking at, I'm kind of extrapolating this
> out to a possible future where it may be possible to more generally (1)
> define custom @attributes in Swift, like Java annotations, and then (2) use
> some metaprogramming constructs to generate introspective default
> implementations for a protocol at compile-time just as the compiler does
> "magically" now, and the generator would be able to query attributes that
> are defined by the same library author as the protocol and handle them
> accordingly.
>
> In a world where that's possible, I think it's less helpful to think in
> terms of "I need to distinguish between conforming to X and getting a
> synthesized implementation and conforming to X and avoiding the synthesized
> implementation because the default might be risky", but instead to think in
> terms of "How can I provide enough semantic information about my types to
> remove the risk?"
>
> In other words, the switches we offer developers to flip shouldn't be
> about turning on/off entire features, but about giving the compiler enough
> information to make it smart enough that we never need to turn it off in
> the first place. As I alluded to before, if I have 10 properties in a type
> and only 1 of those needs to be ignored in ==/hashValue/whatever, writing
> "Equatable" instead of "derives Equatable" isn't all that helpful. Yes, it
> spits out an error message where there wouldn't have been one, but it
> doesn't reduce any of the burden of having to provide the appropriate
> manual implementation.
>
> But all that stuff about custom attributes and metaprogramming
> introspection is a big topic of it's own that isn't going to be solved in
> Swift 5, so this is a bit of a digression. :)
>

That said, we could have enums EquatingKeys and HashingKeys, a la
CodingKeys... That may not be a huge leap to propose and implement.


>
>>
>>
>>> -Thorsten
>>>
>>> Am 12.09.2017 um 16:38 schrieb Tony Allevato via swift-evolution <
>>> swift-evolution@swift.org>:
>>>
>>>
>>>
>>> On Mon, Sep 11, 2017 at 10:05 PM Gwendal Roué 
>>> wrote:
>>>

> This doesn'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 "what generic algorithms would be written using this protocol?"
> AutoSynthesize doesn't satisfy that—there are no generic algorithms that
> you would write with AutoEquatable that differ from what you would write
> with Equatable.
>
>
> And so everybody has 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Tony Allevato via swift-evolution
On Tue, Sep 12, 2017 at 7:10 PM Xiaodi Wu  wrote:

> On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Good arguments, Tony, you have convinced me on all points. Transient is
>> the way to go. Thank you for your patience!
>>
>
> On many points, I agree with Tony, but I disagree that "transient"
> addresses the issue at hand. The challenge being made is that, as Gwendal
> puts it, it's _unwise_ to have a default implementation, because people
> might forget that there is a default implementation. "Transient" only works
> if you remember that there is a default implementation, and in that case,
> we already have a clear syntax for overriding the default.
>

Right—I hope it hasn't sounded like I'm conflating the two concepts
completely. The reason I brought up "transient" is because nearly all of
the "risky" examples being cited so far have been of the variety "I have a
type where some properties happen to be Equatable but shouldn't be involved
in equality", so my intention has been to show that if we have a better
solution to that specific problem (which is, related to but not the same as
the question at hand), then there aren't enough risky cases left to warrant
adding this level of complexity to the protocol system.


>
> As others point out, there's a temptation here to write things like
> "transient(Equatable)" so as to control the synthesis of implementations on
> a per-protocol basis. By that point, you've invented a whole new syntax for
> implementing protocol requirements. (Ah, you might say, but it's hard to
> write a good hashValue implementation: sure, but that's adequately solved
> by a library-supplied combineHashes() function.)
>

I totally agree with this. A design that would try to annotate "transient"
with a protocol or list of protocols is missing the point of the semantics
that "transient" is supposed to provide. It's not a series of switches to
that can be flipped on and off for arbitrary protocols—it's a semantic tag
that assigns additional meaning to properties and certain protocols (such
as Equatable, Hashable, and Codable, but possibly others that haven't been
designed yet) would have protocol-specific behavior for those properties.

To better explain what I've been poking at, I'm kind of extrapolating this
out to a possible future where it may be possible to more generally (1)
define custom @attributes in Swift, like Java annotations, and then (2) use
some metaprogramming constructs to generate introspective default
implementations for a protocol at compile-time just as the compiler does
"magically" now, and the generator would be able to query attributes that
are defined by the same library author as the protocol and handle them
accordingly.

In a world where that's possible, I think it's less helpful to think in
terms of "I need to distinguish between conforming to X and getting a
synthesized implementation and conforming to X and avoiding the synthesized
implementation because the default might be risky", but instead to think in
terms of "How can I provide enough semantic information about my types to
remove the risk?"

In other words, the switches we offer developers to flip shouldn't be about
turning on/off entire features, but about giving the compiler enough
information to make it smart enough that we never need to turn it off in
the first place. As I alluded to before, if I have 10 properties in a type
and only 1 of those needs to be ignored in ==/hashValue/whatever, writing
"Equatable" instead of "derives Equatable" isn't all that helpful. Yes, it
spits out an error message where there wouldn't have been one, but it
doesn't reduce any of the burden of having to provide the appropriate
manual implementation.

But all that stuff about custom attributes and metaprogramming
introspection is a big topic of it's own that isn't going to be solved in
Swift 5, so this is a bit of a digression. :)



>
>
>> -Thorsten
>>
>> Am 12.09.2017 um 16:38 schrieb Tony Allevato via swift-evolution <
>> swift-evolution@swift.org>:
>>
>>
>>
>> On Mon, Sep 11, 2017 at 10:05 PM Gwendal Roué 
>> wrote:
>>
>>>
 This doesn'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 "what generic algorithms would be written using this protocol?"
 AutoSynthesize doesn't satisfy that—there are no generic algorithms that
 you would write with AutoEquatable that differ from what you would write
 with Equatable.


 And so everybody has to swallow implicit and non-avoidable code
 synthesis and shut up?

>>>
>>> That's not what I said. I simply pointed out one of the barriers to
>>> getting a new protocol added to the language.
>>>
>>> Code synthesis is explicitly opt-in and quite avoidable—you either don't
>>> conform to the protocol, or you conform to the protocol and provide your

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Tue, Sep 12, 2017 at 11:43 AM, Haravikk via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On 12 Sep 2017, at 12:08, Xiaodi Wu  wrote:
>
> On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> See, this is another flawed assumption; you are assuming that omitting a
>> custom implementation of == is always intentional rather than an oversight,
>> which is not guaranteed. This is one of my gripes with the retroactive
>> change to Equatable, as it is currently *impossible* to omit an
>> implementation.
>>
>
> Again, this applies equally to the addition of _any_ default
> implementation. And again, such changes don’t even require Swift Evolution
> approval.
>
>
> So what? Because the Swift Evolution process is currently deficient we
> should just give up on discussing problems with features and the language
> altogether?
>

I don't claim that it's a deficiency; I claim it's reflective of Swift's
opinionated take on default implementations. Are you, after all, saying
that you have a problem with the addition of _any_ default implementation
to an existing protocol? If so, this conversation isn't about
synthesis/reflection at all.

And precisely what kind of "evidence" am I expected to give? This is a set
>> of features that *do not exist yet*, I am trying to argue in favour of
>> an explicit end-developer centric opt-in rather than an implicit protocol
>> designer centric one. Yet no-one seems interested in the merits of allowing
>> developers to choose what they want, rather than having implicit behaviours
>> appear potentially unexpectedly.
>>
>>
>> Both options were examined for Codable and for Equatable/Hashable. The
>> community and core team decided to prefer the current design. At this
>> point, new insights that arise which could not be anticipated at the time
>> of review could prompt revision. However, so far, you have presented
>> arguments already considered during review.
>>
>>
>> And so far all I have heard about this is how it was "decided"; no-one
>> seems interested in showing how any of these concerns were addressed (if at
>> all), so as far as I can tell they were not, or they were wilfully ignored.
>>
>
> They were addressed by being considered.
>
>
> And yet no-one can apparently summarise what those "considerations" might
> be, suggesting that they were either *not* considered at all, or that the
> "consideration" was so weak that no-one is willing to step forward to
> defend it. Either way it is not sufficient by any reasonable measure.
>
> If I were to run over your foot in my car, would you be happy to accept
> that I "considered" it first?
>

How do you mean? People wrote in with their opinions. Then, taking into
account the community's response, the proposal was approved.

Therefore, your argument reduces to one about which default implementations
>>> generally ought or ought not to be provided--that is, that they ought to be
>>> provided only when their correctness can be guaranteed for all (rather than
>>> almost all) possible conforming types. To which point I sketched a rebuttal
>>> above.
>>>
>>>
>>> If a protocol defines something, and creates a default implementation
>>> based only upon those definitions then it must by its very nature be
>>> correct. A concrete type may later decided to go further, but that is a
>>> feature of the concrete type, not a failure of the protocol itself which
>>> can function correctly within the context it created. You want to talk
>>> evidence, yet there has been no example given that proves otherwise; thus
>>> far only Itai has attempted to do so, but I have already pointed out the
>>> flaws with that example.
>>>
>>> The simple fact is that a default implementation may either be flawed or
>>> not within the context of the protocol itself; but a reflective or
>>> synthetic implementation by its very nature goes beyond what the protocol
>>> defines and so is automatically flawed because as it does not rely on the
>>> end-developer to confirm correctness, not when provided implicitly at least.
>>>
>>
>> Again, if it applies generally, it must apply specifically. What is
>> "automatically flawed" about the very reasonable synthesized default
>> implementation of ==?
>>
>>
>> It makes the assumption that every equatable property of a type is
>> necessarily relevant to its equality.
>>
>
> No necessarily, only provisionally and rebuttably. If it’s not the case,
> override the default.
>
>
> So… entirely unlike standard default implementations which *cannot* 
> "provisionally"
> assume something is relevant at all,
>

Why not?


> thereby making them entirely different from synthesised/reflective
> implementations!
>
> I'm sorry, but you keep trying to argue that they're the same, but then
> admitting that they're not. You can't have it both ways.
>

Well, certainly, synthesized default implementations differ from
non-synthesized ones in key respects. However, they do 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Tue, Sep 12, 2017 at 9:58 AM, Thorsten Seitz via swift-evolution <
swift-evolution@swift.org> wrote:

> Good arguments, Tony, you have convinced me on all points. Transient is
> the way to go. Thank you for your patience!
>

On many points, I agree with Tony, but I disagree that "transient"
addresses the issue at hand. The challenge being made is that, as Gwendal
puts it, it's _unwise_ to have a default implementation, because people
might forget that there is a default implementation. "Transient" only works
if you remember that there is a default implementation, and in that case,
we already have a clear syntax for overriding the default.

As others point out, there's a temptation here to write things like
"transient(Equatable)" so as to control the synthesis of implementations on
a per-protocol basis. By that point, you've invented a whole new syntax for
implementing protocol requirements. (Ah, you might say, but it's hard to
write a good hashValue implementation: sure, but that's adequately solved
by a library-supplied combineHashes() function.)


> -Thorsten
>
> Am 12.09.2017 um 16:38 schrieb Tony Allevato via swift-evolution <
> swift-evolution@swift.org>:
>
>
>
> On Mon, Sep 11, 2017 at 10:05 PM Gwendal Roué 
> wrote:
>
>>
>>> This doesn'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 "what generic algorithms would be written using this protocol?"
>>> AutoSynthesize doesn't satisfy that—there are no generic algorithms that
>>> you would write with AutoEquatable that differ from what you would write
>>> with Equatable.
>>>
>>>
>>> And so everybody has to swallow implicit and non-avoidable code
>>> synthesis and shut up?
>>>
>>
>> That's not what I said. I simply pointed out one of the barriers to
>> getting a new protocol added to the language.
>>
>> Code synthesis is explicitly opt-in and quite avoidable—you either don't
>> conform to the protocol, or you conform to the protocol and provide your
>> own implementation. What folks are differing on is whether there should
>> have to be *two* explicit switches that you flip instead of one.
>>
>>
>> No. One does not add a protocol conformance by whim. One adds a protocol
>> conformance by need. So the conformance to the protocol is a *given* in our
>> analysis of the consequence of code synthesis. You can not say "just don't
>> adopt it".
>>
>> As soon as I type the protocol name, I get synthesis. That's the reason
>> why the synthesized code is implicit. The synthesis is explicitly written
>> in the protocol documentation, if you want. But not in the programmer's
>> code.
>>
>> I did use "non-avoidable" badly, you're right: one can avoid it, by
>> providing its custom implementation.
>>
>> So the code synthesis out of a mere protocol adoption *is* implicit.
>>
>> Let's imagine a pie. The whole pie is the set of all Swift types. Some
>> slice of that pie is the subset of those types that satisfy the conditions
>> that allow one of our protocols to be synthesized. Now that slice of pie
>> can be sliced again, into the subset of types where (1) the synthesized
>> implementation is correct both in terms of strict value and of business
>> logic, and (2) the subset where it is correct in terms of strict value but
>> is not the right business logic because of something like transient data.
>>
>>
>> Yes.
>>
>> What we have to consider is, how large is slice (2) relative to the whole
>> pie, *and* what is the likelihood that developers are going to mistakenly
>> conform to the protocol without providing their own implementation, *and*
>> is the added complexity worth protecting against this case?
>>
>>
>> That's quite a difficult job: do you think you can evaluate this
>> likelihood?
>>
>> Explicit synthesis has big advantage: it avoids this question entirely.
>>
>> Remember that the main problem with slide (2) is that developers can not
>> *learn* to avoid it.
>>
>> For each type is slide (2) there is a probability that it comes into
>> existence with a forgotten explicit protocol adoption. And this probability
>> will not go down as people learn Swift and discover the existence of slide
>> (2). Why? because this probability is driven by unavoidable human behaviors:
>> - developer doesn't see the problem (a programmer mistake)
>> - the developper plans to add explicit conformance later and happens to
>> forget (carelessness)
>> - a developper extends an existing type with a transient property, and
>> doesn't add the explicit protocol conformance that has become required.
>>
>> Case 2 and 3 bite even experienced developers. And they can't be improved
>> by learning.
>>
>> Looks like the problem is better defined as an ergonomics issue, now.
>>
>> If someone can show me something that points to accidental synthesized
>> implementations being a significant barrier to smooth development in Swift,
>> I'm more than happy to consider that 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Tue, Sep 12, 2017 at 2:30 PM, Gwendal Roué 
wrote:

> >> In none of those cases, the compiler emits any warning. It's thus easy
> to forget or miss the problem, and uneasy to fix it (you'll need a runtime
> failure to spot it, or a thorough code review).
> >>
> >> I hope you agree with this last sentence. This unbalance between the
> easiness of the mistake and the easiness of the fix should ring a bell to
> language designers.
> >
> > Suppose instead this were about a protocol named Fooable and a
> requirement called foo() that has a default implementation. Everything you
> just talked about would apply equally. Am I to understand that you are
> opposed to default implementations in general? If so, then that’s got
> nothing to do with synthesized Equatable conformance. If not, then you’ll
> have to justify why.
>
> Sounds like a good argument, until one realises that if a protocol does
> not provide a default implementations for a method, it may be because a
> default implementations is impossible to provide (the most usual case), or
> because it would be unwise to do so.
>
> And indeed, the topic currently discussed is not if we should remove or
> not default implementations. Instead, the question is: is it wise or not to
> provide an *implicit* default Equatable/Hashable/XXX implementation?
>

Right, _that_ is the question. It was asked during review for the proposal,
and the agreed upon answer is _yes_.

The tenant of explicit synthesis attempt to say that it would be unwise to
> do so. Please don't have us repeat again, that would be disrespectful.
>
> BTW, Happy Keynote to everybody!
> Gwendal
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread David Waite via swift-evolution

> On Sep 12, 2017, at 11:00 AM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Suppose instead this were about a protocol named Fooable and a requirement 
> called foo() that has a default implementation. Everything you just talked 
> about would apply equally. Am I to understand that you are opposed to default 
> implementations in general? If so, then that’s got nothing to do with 
> synthesized Equatable conformance. If not, then you’ll have to justify why.

First - I can go either way on this issue, since proper traits/mixins and 
hygienic macros both appear to be strong influencers which will drive evolution 
in ways we cannot evaluate yet.

In my opinion, the difference between most protocol default implementations and 
Equatable/Hashable is that most protocol default implementations are based on 
the contract of the protocol itself. I can understand that Sequence#contains 
works by default because a Sequence implementation has a required 
makeIterator() function that meet the Sequence contract (and returns an 
Iterator that meets the iterator contract).

There is nothing in the Equatable contract saying "two instances of a type are 
considered Equatable for value types when all the properties on the type are 
Equatable and compare as being equal." That is a behavioral assumption made by 
the default implementation.

The current usage of traits in swift (in my experience) can be a bit deficient 
in that there is an assumption of a single behavior. For example - I might be 
able to default quite a bit of a view's delegate if I was willing to make 
assumptions, such as each row being a fixed size with a fixed (set of) views. 
But this is inappropriate as a default behavior for all table view delegates.

We also have the disadvantage that we haven't solved the problem of indicating 
a method is meant to implement a protocol, so typos and incorrect function 
signatures can result in the wrong behavior at runtime.

-DW___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Gwendal Roué via swift-evolution
>> In none of those cases, the compiler emits any warning. It's thus easy to 
>> forget or miss the problem, and uneasy to fix it (you'll need a runtime 
>> failure to spot it, or a thorough code review).
>> 
>> I hope you agree with this last sentence. This unbalance between the 
>> easiness of the mistake and the easiness of the fix should ring a bell to 
>> language designers.
> 
> Suppose instead this were about a protocol named Fooable and a requirement 
> called foo() that has a default implementation. Everything you just talked 
> about would apply equally. Am I to understand that you are opposed to default 
> implementations in general? If so, then that’s got nothing to do with 
> synthesized Equatable conformance. If not, then you’ll have to justify why.

Sounds like a good argument, until one realises that if a protocol does not 
provide a default implementations for a method, it may be because a default 
implementations is impossible to provide (the most usual case), or because it 
would be unwise to do so.

And indeed, the topic currently discussed is not if we should remove or not 
default implementations. Instead, the question is: is it wise or not to provide 
an *implicit* default Equatable/Hashable/XXX implementation?

The tenant of explicit synthesis attempt to say that it would be unwise to do 
so. Please don't have us repeat again, that would be disrespectful.

BTW, Happy Keynote to everybody!
Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Vladimir.S via swift-evolution

On 12.09.2017 18:09, Tony Allevato wrote:



On Tue, Sep 12, 2017 at 3:32 AM Vladimir.S > wrote:


On 12.09.2017 0:35, Tony Allevato wrote:
 >
 >
 > On Mon, Sep 11, 2017 at 2:05 PM Vladimir.S via swift-evolution
 > 
>> 
wrote:
 >
 > On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:
 >  > I think I do understand Haravikk's argument (actually it seems 
quite
 > straightforward
 >  > to me).
 >  >
 >  > An example should be:
 >  >
 >  > struct Foo : Equatable {
 >  >  var x: Int
 >  >  var cachedLabel: String? = nil
 >  >
 >  >  init(x: Int) {
 >  >  self.x = x
 >  >  }
 >  >
 >  >  mutating func label() {
 >  >  if let label = cachedLabel {
 >  >  return label
 >  >  }
 >  >  let label = calculateLabel()
 >  >  cachedLabel = label
 >  >  return cachedLabel
 >  >  }
 >  > }
 >  >
 >  > var foo1 = Foo(x: 1)
 >  > var foo2 = Foo(x: 1)
 >  > foo1 == foo2 // true
 >  > var label = foo1.label()
 >  > foo1 == foo2 // now false, due to cachedString being falsely 
included
in the
 > comparison
 >  >
 >  > The problem is that the developer was not required to implement 
the
protocol
 > and so
 >  > might forget it.
 >  > The difference to other default implementations is that those use 
the
protocol
 > itself
 >  > as building blocks and so are correct with regards to the 
protocol's
semantics,
 >  > whereas the synthesized equality reaches deeply into the private
innards of a
 > struct
 >  > and therefore is much more likely to be wrong as in the example 
above.
 >  >
 >  > Why not just write
 >  >
 >  > *struct* Foo : *deriving* Equatable {...}
 >  >
 >  > to request the synthesized implementation?
 >
 > FWIW, +100. The same should be required for Codable. I support the 
opinion
that
 > 'synthesized' methods differs from protocol-default-implementation 
in what
'kind' of
 > data they use: defined by protocol itself or internals of the 
conformed
type. And
 > this can lead to more un-expected problems.
 >
 > If protocol is able to synthesize its requirements, it should 
require a
 > 'deriving'-like marker when type conforms to it to make it absolutely
clear what
 > happens here. It would be not a confusion point, but clarify the 
intention
to better
 > understand the code.
 >
 > Thinking about *future* custom protocols that could implement 
requirements
in default
 > implementation by using macros/reflection, for me it seems like such
protocol should
 > *also* somehow explicitly state that some requirements are
auto-synthesized, probably
 > by conforming(derive) to some compiler-magic protocol 
'AutoSynthesize'.
 > (i.e. 'protocol MySynthesizeable: AutoSynthesize {...}')
 >
 > So each built-in protocol like Equatable/Hashable/Codable will 
conform to
it, and
 > also, each custom "auto-synthesizeable" protocol - also should 
explicitly
conform to
 > AutoSynthesize. So, when type conforms to it - such type should use
'deriving'-like
 > marker if auto-generation of methods is expected.
 >
 >
 > This doesn'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 
"what generic
 > algorithms would be written using this protocol?" AutoSynthesize doesn't 
satisfy
 > that—there are no generic algorithms that you would write with 
AutoEquatable that
 > differ from what you would write with Equatable.
 >

OK, got it, it was general thoughts, not exact proposal regarding the 
AutoSynthesize
protocol. Probably it should be @autosynthesize directive for protocol when 
you
define it or other 'marker', so when you conform to this protocol, you *can*
explicitely use 'derived'-like keyword to make requirements 
auto-synthesized,
otherwise you'll be asked by compiler for manual implementation.


 > I also have a question regarding future direction of 'exclusion' of 
fields
from being
 > included into auto-generated implementation of
Equatable/Hashable/Codable/other.
 >
 > If we'll have this 'deriving'-like marker, it seems naturally if we 
mark
some member
 > with some kind of 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Tue, Sep 12, 2017 at 09:53 Gwendal Roué  wrote:

>
> > Le 12 sept. 2017 à 12:01, Xiaodi Wu  a écrit :
> >
> >> There is this sample code by Thorsten Seitz with a cached property
> which is quite simple and clear :
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
> >>
> >> This is the sample code that had me enter the "worried" camp.
> >
> > Sorry, I fail to see what the problem is in that example. A method was
> invoked that changed a stored property of one instance. Therefore, it’s no
> longer equal to the other instance. If you want a custom notion of
> equality, you should implement it yourself. In the absence of such, the
> _default_ notion of equality is pretty clear.
>
> Yes, I agree with you. As long as you reason in this way, there is no
> problem at all, just a programmer error.
>
> I'll try to show that you need to play some moves further before problems
> appear. Don't look at the code as a static thing, but as a living thing.
>
> Please follow me: will you play a little programmer game? Here is a
> snippet of code. It is embedded in this Xcode project which, as you can
> see, contains hundreds of files. Your mission is to add an extra property
> which should not be considered for Equatable adoption. How do you do that?
>
> struct S : Equatable {
> var x: Int
> }
>
> The answer is:
>
> 1. Find if there is an extension somewhere that implements Equatable
> conformance.
> 2. If you are eventually sure that there is no explicit conformance yet,
> write the correct one.
>
> You may know that proving that something does not exist is harder than the
> opposite, and the step 1 above seems dubious to you. You are right. You
> thus use this smarter technique:
>
> 1. Write a dummy explicit conformance to Equatable, compile.
> 2. If compiler does not complain about duplicate implementation, conclude
> that there is no explicit conformance yet, and write the correct one.
>
> Problem solved. And nice display of smartness and funny little compiler
> tricks. 
>
> 
>
> No. Please look at the topic from above, and look at how developers are
> working. Troubles in synthesized conformance can happen for several reasons:
>
> 1. Lack of knowledge. As you tend to day, nobody is supposed to ignore the
> law, and the bug is the fault of the programmer.
> 2. The developper creates the type, plans to add specific implementation,
> and forgets.
> 3. The developper eventually adds a property and misses the fact that a
> synthesized conformance exists (and is now incorrect).
> 4. The developper eventually adds a property and misses the fact that the
> synthesized conformance is now incorrect.
> 5. The developper eventually adds a property, plans to fix the synthesized
> conformance, and forgets.
>
> Cases 2, 3 and 5 are examples of good faith mistakes.
>
> In none of those cases, the compiler emits any warning. It's thus easy to
> forget or miss the problem, and uneasy to fix it (you'll need a runtime
> failure to spot it, or a thorough code review).
>
> I hope you agree with this last sentence. This unbalance between the
> easiness of the mistake and the easiness of the fix should ring a bell to
> language designers.
>

Suppose instead this were about a protocol named Fooable and a requirement
called foo() that has a default implementation. Everything you just talked
about would apply equally. Am I to understand that you are opposed to
default implementations in general? If so, then that’s got nothing to do
with synthesized Equatable conformance. If not, then you’ll have to justify
why.


Beyond that, it's very hard to improve one's skills in face of those
> programmer errors. They have not much value beyond blind punishment. You
> can't learn from them. I'm the last one who wishes to see a weird cultural
> paranoia against Equatable: look at how "smart" and versed in Swift
> subtleties you need to be to just add a simple property to an innocuous
> struct!
>
> Gwendal
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Haravikk via swift-evolution

> On 12 Sep 2017, at 16:29, Tony Allevato via swift-evolution 
>  wrote:
> 
> Since your game involves the specific question of a property that should not 
> be considered for Equatable synthesis, and since SE-0185 explicitly calls out 
> the notion of transient properties as a future direction to solve that 
> specific problem, then my solution is "I declare the property as transient."
> 
> Surely this is an acceptable solution? It achieves the goal you set, and more 
> concisely/quickly than the ways you proposed in that post. It doesn't require 
> me to go fishing through code; the act of adding the property and making it 
> transient is completely localized to one place (it's one line!). If there's a 
> synthesized implementation of Equatable, then the property gets ignored as 
> desired. If there's a handwritten implementation, then the new property is 
> already ignored because it wasn't there to begin with, but the transient 
> declaration still provides valuable information to the reader of the code 
> about the intention.
> 
> If the rebuttal to that is going to be "a developer may not know about 
> transient", then where do we draw the line at expecting users to know how to 
> use the features their language? It's a significant leap to go from 
> "developers might do the wrong thing" to "so this specific approach is the 
> only right way to fix it."

I think that it's reasonable to assume that the protocol would inform 
developers of the use of transient, but this comes back to the original topic 
of this thread; if the developer didn't ask for the synthesised behaviour then 
is it reasonable to assume they'll have properly marked their properties as 
transient?

My argument would (perhaps unsurprisingly) be no; a default implementation that 
can make use of attributes is IMO something that a developer should opt into 
explicitly as a convenient alternative to providing a full implementation 
themselves.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Haravikk via swift-evolution

> On 12 Sep 2017, at 12:08, Xiaodi Wu  > wrote:
> 
>> On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution 
>> > wrote:
>> See, this is another flawed assumption; you are assuming that omitting a 
>> custom implementation of == is always intentional rather than an oversight, 
>> which is not guaranteed. This is one of my gripes with the retroactive 
>> change to Equatable, as it is currently impossible to omit an implementation.
> 
> Again, this applies equally to the addition of _any_ default implementation. 
> And again, such changes don’t even require Swift Evolution approval.

So what? Because the Swift Evolution process is currently deficient we should 
just give up on discussing problems with features and the language altogether?

 And precisely what kind of "evidence" am I expected to give? This is a set 
 of features that do not exist yet, I am trying to argue in favour of an 
 explicit end-developer centric opt-in rather than an implicit protocol 
 designer centric one. Yet no-one seems interested in the merits of 
 allowing developers to choose what they want, rather than having implicit 
 behaviours appear potentially unexpectedly.
>>> 
>>> Both options were examined for Codable and for Equatable/Hashable. The 
>>> community and core team decided to prefer the current design. At this 
>>> point, new insights that arise which could not be anticipated at the time 
>>> of review could prompt revision. However, so far, you have presented 
>>> arguments already considered during review.
>> 
>> And so far all I have heard about this is how it was "decided"; no-one seems 
>> interested in showing how any of these concerns were addressed (if at all), 
>> so as far as I can tell they were not, or they were wilfully ignored.
> 
> They were addressed by being considered.

And yet no-one can apparently summarise what those "considerations" might be, 
suggesting that they were either not considered at all, or that the 
"consideration" was so weak that no-one is willing to step forward to defend 
it. Either way it is not sufficient by any reasonable measure.

If I were to run over your foot in my car, would you be happy to accept that I 
"considered" it first?

 Therefore, your argument reduces to one about which default 
 implementations generally ought or ought not to be provided--that is, that 
 they ought to be provided only when their correctness can be guaranteed 
 for all (rather than almost all) possible conforming types. To which point 
 I sketched a rebuttal above.
>>> 
>>> If a protocol defines something, and creates a default implementation based 
>>> only upon those definitions then it must by its very nature be correct. A 
>>> concrete type may later decided to go further, but that is a feature of the 
>>> concrete type, not a failure of the protocol itself which can function 
>>> correctly within the context it created. You want to talk evidence, yet 
>>> there has been no example given that proves otherwise; thus far only Itai 
>>> has attempted to do so, but I have already pointed out the flaws with that 
>>> example.
>>> 
>>> The simple fact is that a default implementation may either be flawed or 
>>> not within the context of the protocol itself; but a reflective or 
>>> synthetic implementation by its very nature goes beyond what the protocol 
>>> defines and so is automatically flawed because as it does not rely on the 
>>> end-developer to confirm correctness, not when provided implicitly at least.
>>> 
>>> Again, if it applies generally, it must apply specifically. What is 
>>> "automatically flawed" about the very reasonable synthesized default 
>>> implementation of ==?
>> 
>> It makes the assumption that every equatable property of a type is 
>> necessarily relevant to its equality.
> 
> No necessarily, only provisionally and rebuttably. If it’s not the case, 
> override the default.

So… entirely unlike standard default implementations which cannot 
"provisionally" assume something is relevant at all, thereby making them 
entirely different from synthesised/reflective implementations!

I'm sorry, but you keep trying to argue that they're the same, but then 
admitting that they're not. You can't have it both ways.

>> Consider for example if a type stores a collection index for performance 
>> reasons; this isn't an intrinsic part of the type, nor relevant to testing 
>> equality, yet this default implementation will treat it as such because it 
>> knows nothing about the concrete type's properties. If a protocol does not 
>> define a property then any action taken upon such a property is necessarily 
>> based upon an assumption; just because it might be fine some of the time, 
>> does not make it any less flawed.
>> 
>> The big difference here between explicit and implicit synthetic 
>> implementations is where this 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Vladimir.S via swift-evolution

On 12.09.2017 17:38, Tony Allevato wrote:



On Mon, Sep 11, 2017 at 10:05 PM Gwendal Roué > wrote:





This doesn'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
"what generic algorithms would be written using this protocol?"
AutoSynthesize doesn't satisfy that—there are no generic algorithms that
you would write with AutoEquatable that differ from what you would write
with Equatable.


And so everybody has to swallow implicit and non-avoidable code 
synthesis
and shut up?


That's not what I said. I simply pointed out one of the barriers to getting 
a
new protocol added to the language.

Code synthesis is explicitly opt-in and quite avoidable—you either don't
conform to the protocol, or you conform to the protocol and provide your own
implementation. What folks are differing on is whether there should have to 
be
*two* explicit switches that you flip instead of one.


No. One does not add a protocol conformance by whim. One adds a protocol
conformance by need. So the conformance to the protocol is a *given* in our
analysis of the consequence of code synthesis. You can not say "just don't adopt 
it".

As soon as I type the protocol name, I get synthesis. That's the reason why 
the
synthesized code is implicit. The synthesis is explicitly written in the 
protocol
documentation, if you want. But not in the programmer's code.

I did use "non-avoidable" badly, you're right: one can avoid it, by 
providing its
custom implementation.

So the code synthesis out of a mere protocol adoption *is* implicit.


Let's imagine a pie. The whole pie is the set of all Swift types. Some 
slice of
that pie is the subset of those types that satisfy the conditions that allow
one of our protocols to be synthesized. Now that slice of pie can be sliced
again, into the subset of types where (1) the synthesized implementation is
correct both in terms of strict value and of business logic, and (2) the 
subset
where it is correct in terms of strict value but is not the right business
logic because of something like transient data.


Yes.


What we have to consider is, how large is slice (2) relative to the whole 
pie,
*and* what is the likelihood that developers are going to mistakenly 
conform to
the protocol without providing their own implementation, *and* is the added
complexity worth protecting against this case?


That's quite a difficult job: do you think you can evaluate this likelihood?

Explicit synthesis has big advantage: it avoids this question entirely.

Remember that the main problem with slide (2) is that developers can not 
*learn*
to avoid it.

For each type is slide (2) there is a probability that it comes into 
existence
with a forgotten explicit protocol adoption. And this probability will not 
go
down as people learn Swift and discover the existence of slide (2). Why? 
because
this probability is driven by unavoidable human behaviors:
- developer doesn't see the problem (a programmer mistake)
- the developper plans to add explicit conformance later and happens to 
forget
(carelessness)
- a developper extends an existing type with a transient property, and 
doesn't
add the explicit protocol conformance that has become required.

Case 2 and 3 bite even experienced developers. And they can't be improved by
learning.

Looks like the problem is better defined as an ergonomics issue, now.


If someone can show me something that points to accidental synthesized
implementations being a significant barrier to smooth development in Swift, 
I'm
more than happy to consider that evidence. But right now, this all seems
hypothetical ("I'm worried that...") and what's being proposed is adding
complexity to the language (an entirely new axis of protocol conformance) 
that
would (1) solve a problem that may not exist to any great degree, and (2) 
does
not address the fact that if that problem does indeed exist, then the same
problem just as likely exists with certain non-synthesized default 
implementations.


There is this sample code by Thorsten Seitz with a cached property which is 
quite
simple and clear :

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html

This is the sample code that had me enter the "worried" camp.'


I really like Thorsten's example, because it actually proves that requiring explicit 
derivation is NOT the correct approach here. (Let's set aside the fact that Optionals 
prevent synthesis because we don't have conditional conformances yet, and assume that 
we've gotten that feature as well for the sake of argument.)


Let's look at two scenarios:

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Gwendal Roué via swift-evolution

> Le 12 sept. 2017 à 17:26, Tony Allevato  a écrit :
> 
> Since your game involves the specific question of a property that should not 
> be considered for Equatable synthesis, and since SE-0185 explicitly calls out 
> the notion of transient properties as a future direction to solve that 
> specific problem, then my solution is "I declare the property as transient."
> 
> Surely this is an acceptable solution? It achieves the goal you set, and more 
> concisely/quickly than the ways you proposed in that post. It doesn't require 
> me to go fishing through code; the act of adding the property and making it 
> transient is completely localized to one place (it's one line!). If there's a 
> synthesized implementation of Equatable, then the property gets ignored as 
> desired. If there's a handwritten implementation, then the new property is 
> already ignored because it wasn't there to begin with, but the transient 
> declaration still provides valuable information to the reader of the code 
> about the intention.
> 
> If the rebuttal to that is going to be "a developer may not know about 
> transient", then where do we draw the line at expecting users to know how to 
> use the features their language? It's a significant leap to go from 
> "developers might do the wrong thing" to "so this specific approach is the 
> only right way to fix it."

Your answer is totally valid in a world where properties can be declared 
transient.

So you may now be aware that in a world where there are no transient 
properties, implicit synthesis of Equatable and Hashable conformance has 
problems that explicit synthesis has not. Making more people aware of this is 
my only goal in this thread.

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Tony Allevato via swift-evolution
On Tue, Sep 12, 2017 at 8:10 AM Gwendal Roué  wrote:

> >> There is this sample code by Thorsten Seitz with a cached property
> which is quite simple and clear :
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
> >>
> >> This is the sample code that had me enter the "worried" camp.'
> >>
> > I really like Thorsten's example, because it actually proves that
> requiring explicit derivation is NOT the correct approach here. (Let's set
> aside the fact that Optionals prevent synthesis because we don't have
> conditional conformances yet, and assume that we've gotten that feature as
> well for the sake of argument.)
> >
> > Let's look at two scenarios:
> >
> > 1) Imagine I have a value type with a number of simple Equatable
> properties. In a world where synthesis is explicit, I tell that value type
> to "derive Equatable". Everything is fine. Later, I decide to add some
> cache property like in Thorsten's example, and that property just happens
> to also be Equatable. After doing so, the correct thing to do would be to
> remove the "derive" part and provide my custom implementation. But if I
> forget to do that, the synthesized operator still exists and applies to
> that type. If you're arguing that "derive Equatable" is better because its
> explicitness prevents errors, you must also accept that there are possibly
> just as many cases where that explicitness does *not* prevent errors.
>
> It looks like it is true, but it is not. The implicit world is harder to
> deal with. And this is because in the implicit world, you never know if
> conformance has been synthesized or not. In the explicit world, you know:
> it's plain written down.
>
> To see this point, please play the game I've proposed to Xiaodi at
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039710.html


Since your game involves the specific question of a property that should
not be considered for Equatable synthesis, and since SE-0185 explicitly
calls out the notion of transient properties as a future direction to solve
that specific problem, then my solution is "I declare the property as
transient."

Surely this is an acceptable solution? It achieves the goal you set, and
more concisely/quickly than the ways you proposed in that post. It doesn't
require me to go fishing through code; the act of adding the property and
making it transient is completely localized to one place (it's one line!).
If there's a synthesized implementation of Equatable, then the property
gets ignored as desired. If there's a handwritten implementation, then the
new property is already ignored because it wasn't there to begin with, but
the transient declaration still provides valuable information to the reader
of the code about the intention.

If the rebuttal to that is going to be "a developer may not know about
transient", then where do we draw the line at expecting users to know how
to use the features their language? It's a significant leap to go from
"developers might do the wrong thing" to "so this specific approach is the
only right way to fix it."



> > 2) Imagine I have a value type with 10 Equatable properties and one
> caching property that also happens to be Equatable. The solution being
> proposed here says that I'm better off with explicit synthesis because if I
> conform that type to Equatable without "derive", I get an error, and then I
> can provide my own custom implementation.
>
> Yes.
>
> > But I have to provide that custom implementation *anyway* to ignore the
> caching property even if we don't make synthesis explicit. Making it
> explicit hasn't saved me any work—it's only given me a compiler error for a
> problem that I already knew I needed to resolve.
>
> Oh, so compiler errors and warnings bring no information to you? :-) I'm
> impressed, but I'll keep on focusing on designing a language for average
> developpers, not only geniuses.
>
> Replay your argument and imagine that compiler outputs are useful to you.
> This will change your conclusion.
>
> Gwendal
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Nevin Brackett-Rozinsky via swift-evolution
Tony makes an excellent point, and I agree. At some point in the future we
should consider introducing a “transient” attribute for caches and other
non-essential properties. That will make generated conformances more
powerful while simultaneously reducing boilerplate.

Nevin


On Tue, Sep 12, 2017 at 10:39 AM, Tony Allevato via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Mon, Sep 11, 2017 at 10:05 PM Gwendal Roué 
> wrote:
>
>>
>> There is this sample code by Thorsten Seitz with a cached property which
>> is quite simple and clear : https://lists.swift.org/
>> pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
>>
>> This is the sample code that had me enter the "worried" camp.'
>>
>
> I really like Thorsten's example, because it actually proves that
> requiring explicit derivation is NOT the correct approach here. (Let's set
> aside the fact that Optionals prevent synthesis because we don't have
> conditional conformances yet, and assume that we've gotten that feature as
> well for the sake of argument.)
>
> Let's look at two scenarios:
>
> 1) Imagine I have a value type with a number of simple Equatable
> properties. In a world where synthesis is explicit, I tell that value type
> to "derive Equatable". Everything is fine. Later, I decide to add some
> cache property like in Thorsten's example, and that property just happens
> to also be Equatable. After doing so, the correct thing to do would be to
> remove the "derive" part and provide my custom implementation. But if I
> forget to do that, the synthesized operator still exists and applies to
> that type. If you're arguing that "derive Equatable" is better because its
> explicitness prevents errors, you must also accept that there are possibly
> just as many cases where that explicitness does *not* prevent errors.
>
> 2) Imagine I have a value type with 10 Equatable properties and one
> caching property that also happens to be Equatable. The solution being
> proposed here says that I'm better off with explicit synthesis because if I
> conform that type to Equatable without "derive", I get an error, and then I
> can provide my own custom implementation. But I have to provide that custom
> implementation *anyway* to ignore the caching property even if we don't
> make synthesis explicit. Making it explicit hasn't saved me any work—it's
> only given me a compiler error for a problem that I already knew I needed
> to resolve. If we tack on Hashable and Codable to that type, then I still
> have to write a significant amount of boilerplate for those custom
> operations. Furthermore, if synthesis is explicit, I have *more* work
> because I have to declare it explicitly even for types where the problem
> above does not occur.
>
> So, making derivation explicit is simply a non-useful dodge that doesn't
> solve the underlying problem, which is this: Swift's type system currently
> does not distinguish between Equatable properties that *do* contribute to
> the "value" of their containing instance vs. Equatable properties that *do
> not* contribute to the "value" of their containing instance. It's the
> difference between behavior based on a type and additional business logic
> implemented on top of those types.
>
> So, what I'm trying to encourage people to see is this: saying "there are
> some cases where synthesis is risky because it's incompatible with certain
> semantics, so let's make it explicit everywhere" is trying to fix the wrong
> problem. What we should be looking at is *"how do we give Swift the
> additional semantic information it needs to make the appropriate decision
> about what to synthesize?"*
>
> That's where concepts like "transient" come in. If I have an
> Equatable/Hashable/Codable type with 10 properties and one cache property,
> I *still* want the synthesis for those first 10 properties. I don't want
> the presence of *one* property to force me to write all of that boilerplate
> myself. I just want to tell the compiler which properties to ignore.
>
> Imagine you're a stranger reading the code to such a type for the first
> time. Which would be easier for you to quickly understand? The version with
> custom implementations of ==, hashValue, init(from:), and encode(to:) all
> covering 10 or more properties that you have to read through to figure out
> what's being ignored (and make sure that the author has done so correctly),
> or the version that conforms to those protocols, does not contain a custom
> implementation, and has each transient property clearly marked? The latter
> is more concise and "transient" carries semantic weight that gets buried in
> a handwritten implementation.
>
> Here's a fun exercise—you can actually write something like "transient"
> without any additional language support today: https://gist.github.com/
> allevato/e1aab2b7b2ced72431c3cf4de71d306d. A big drawback to this
> Transient type is that it's not as easy to use as an Optional because of
> the additional 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Gwendal Roué via swift-evolution
>> There is this sample code by Thorsten Seitz with a cached property which is 
>> quite simple and clear : 
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
>> 
>> This is the sample code that had me enter the "worried" camp.'
>> 
> I really like Thorsten's example, because it actually proves that requiring 
> explicit derivation is NOT the correct approach here. (Let's set aside the 
> fact that Optionals prevent synthesis because we don't have conditional 
> conformances yet, and assume that we've gotten that feature as well for the 
> sake of argument.)
> 
> Let's look at two scenarios:
> 
> 1) Imagine I have a value type with a number of simple Equatable properties. 
> In a world where synthesis is explicit, I tell that value type to "derive 
> Equatable". Everything is fine. Later, I decide to add some cache property 
> like in Thorsten's example, and that property just happens to also be 
> Equatable. After doing so, the correct thing to do would be to remove the 
> "derive" part and provide my custom implementation. But if I forget to do 
> that, the synthesized operator still exists and applies to that type. If 
> you're arguing that "derive Equatable" is better because its explicitness 
> prevents errors, you must also accept that there are possibly just as many 
> cases where that explicitness does *not* prevent errors.

It looks like it is true, but it is not. The implicit world is harder to deal 
with. And this is because in the implicit world, you never know if conformance 
has been synthesized or not. In the explicit world, you know: it's plain 
written down.

To see this point, please play the game I've proposed to Xiaodi at 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039710.html

> 2) Imagine I have a value type with 10 Equatable properties and one caching 
> property that also happens to be Equatable. The solution being proposed here 
> says that I'm better off with explicit synthesis because if I conform that 
> type to Equatable without "derive", I get an error, and then I can provide my 
> own custom implementation.

Yes.

> But I have to provide that custom implementation *anyway* to ignore the 
> caching property even if we don't make synthesis explicit. Making it explicit 
> hasn't saved me any work—it's only given me a compiler error for a problem 
> that I already knew I needed to resolve.

Oh, so compiler errors and warnings bring no information to you? :-) I'm 
impressed, but I'll keep on focusing on designing a language for average 
developpers, not only geniuses.

Replay your argument and imagine that compiler outputs are useful to you. This 
will change your conclusion.

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Tony Allevato via swift-evolution
On Tue, Sep 12, 2017 at 3:32 AM Vladimir.S  wrote:

> On 12.09.2017 0:35, Tony Allevato wrote:
> >
> >
> > On Mon, Sep 11, 2017 at 2:05 PM Vladimir.S via swift-evolution
> > > wrote:
> >
> > On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:
> >  > I think I do understand Haravikk's argument (actually it seems
> quite
> > straightforward
> >  > to me).
> >  >
> >  > An example should be:
> >  >
> >  > struct Foo : Equatable {
> >  >  var x: Int
> >  >  var cachedLabel: String? = nil
> >  >
> >  >  init(x: Int) {
> >  >  self.x = x
> >  >  }
> >  >
> >  >  mutating func label() {
> >  >  if let label = cachedLabel {
> >  >  return label
> >  >  }
> >  >  let label = calculateLabel()
> >  >  cachedLabel = label
> >  >  return cachedLabel
> >  >  }
> >  > }
> >  >
> >  > var foo1 = Foo(x: 1)
> >  > var foo2 = Foo(x: 1)
> >  > foo1 == foo2 // true
> >  > var label = foo1.label()
> >  > foo1 == foo2 // now false, due to cachedString being falsely
> included in the
> > comparison
> >  >
> >  > The problem is that the developer was not required to implement
> the protocol
> > and so
> >  > might forget it.
> >  > The difference to other default implementations is that those use
> the protocol
> > itself
> >  > as building blocks and so are correct with regards to the
> protocol's semantics,
> >  > whereas the synthesized equality reaches deeply into the private
> innards of a
> > struct
> >  > and therefore is much more likely to be wrong as in the example
> above.
> >  >
> >  > Why not just write
> >  >
> >  > *struct* Foo : *deriving* Equatable {...}
> >  >
> >  > to request the synthesized implementation?
> >
> > FWIW, +100. The same should be required for Codable. I support the
> opinion that
> > 'synthesized' methods differs from protocol-default-implementation
> in what 'kind' of
> > data they use: defined by protocol itself or internals of the
> conformed type. And
> > this can lead to more un-expected problems.
> >
> > If protocol is able to synthesize its requirements, it should
> require a
> > 'deriving'-like marker when type conforms to it to make it
> absolutely clear what
> > happens here. It would be not a confusion point, but clarify the
> intention to better
> > understand the code.
> >
> > Thinking about *future* custom protocols that could implement
> requirements in default
> > implementation by using macros/reflection, for me it seems like such
> protocol should
> > *also* somehow explicitly state that some requirements are
> auto-synthesized, probably
> > by conforming(derive) to some compiler-magic protocol
> 'AutoSynthesize'.
> > (i.e. 'protocol MySynthesizeable: AutoSynthesize {...}')
> >
> > So each built-in protocol like Equatable/Hashable/Codable will
> conform to it, and
> > also, each custom "auto-synthesizeable" protocol - also should
> explicitly conform to
> > AutoSynthesize. So, when type conforms to it - such type should use
> 'deriving'-like
> > marker if auto-generation of methods is expected.
> >
> >
> > This doesn'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
> "what generic
> > algorithms would be written using this protocol?" AutoSynthesize doesn't
> satisfy
> > that—there are no generic algorithms that you would write with
> AutoEquatable that
> > differ from what you would write with Equatable.
> >
>
> OK, got it, it was general thoughts, not exact proposal regarding the
> AutoSynthesize
> protocol. Probably it should be @autosynthesize directive for protocol
> when you
> define it or other 'marker', so when you conform to this protocol, you
> *can*
> explicitely use 'derived'-like keyword to make requirements
> auto-synthesized,
> otherwise you'll be asked by compiler for manual implementation.
>
>
> > I also have a question regarding future direction of 'exclusion' of
> fields from being
> > included into auto-generated implementation of
> Equatable/Hashable/Codable/other.
> >
> > If we'll have this 'deriving'-like marker, it seems naturally if we
> mark some member
> > with some kind of '@noderiving' marker, like here:
> >
> > struct Foo : deriving Equatable {
> > var x: Int
> > var y: Int
> > var z: Int
> > @noderiving var cachedLabel: String? = nil
> > }
> >
> > this @noderiving directive will work for protocols based on
> AutoSynthesize magic
> > protocol. I.e., if you construct your own protocol with
> auto-synthesizeable methods,
> > to be able to *know* which 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Thorsten Seitz via swift-evolution
Good arguments, Tony, you have convinced me on all points. Transient is the way 
to go. Thank you for your patience!

-Thorsten

> Am 12.09.2017 um 16:38 schrieb Tony Allevato via swift-evolution 
> :
> 
> 
> 
>> On Mon, Sep 11, 2017 at 10:05 PM Gwendal Roué  wrote:
> 
> This doesn'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 "what generic algorithms would be written using this 
> protocol?" AutoSynthesize doesn't satisfy that—there are no generic 
> algorithms that you would write with AutoEquatable that differ from what 
> you would write with Equatable.
 
 And so everybody has to swallow implicit and non-avoidable code synthesis 
 and shut up?
>>> 
>>> That's not what I said. I simply pointed out one of the barriers to getting 
>>> a new protocol added to the language.
>>> 
>>> Code synthesis is explicitly opt-in and quite avoidable—you either don't 
>>> conform to the protocol, or you conform to the protocol and provide your 
>>> own implementation. What folks are differing on is whether there should 
>>> have to be *two* explicit switches that you flip instead of one.
>> 
>> No. One does not add a protocol conformance by whim. One adds a protocol 
>> conformance by need. So the conformance to the protocol is a *given* in our 
>> analysis of the consequence of code synthesis. You can not say "just don't 
>> adopt it".
>> 
>> As soon as I type the protocol name, I get synthesis. That's the reason why 
>> the synthesized code is implicit. The synthesis is explicitly written in the 
>> protocol documentation, if you want. But not in the programmer's code.
>> 
>> I did use "non-avoidable" badly, you're right: one can avoid it, by 
>> providing its custom implementation.
>> 
>> So the code synthesis out of a mere protocol adoption *is* implicit.
>> 
>>> Let's imagine a pie. The whole pie is the set of all Swift types. Some 
>>> slice of that pie is the subset of those types that satisfy the conditions 
>>> that allow one of our protocols to be synthesized. Now that slice of pie 
>>> can be sliced again, into the subset of types where (1) the synthesized 
>>> implementation is correct both in terms of strict value and of business 
>>> logic, and (2) the subset where it is correct in terms of strict value but 
>>> is not the right business logic because of something like transient data.
>> 
>> Yes.
>> 
>>> What we have to consider is, how large is slice (2) relative to the whole 
>>> pie, *and* what is the likelihood that developers are going to mistakenly 
>>> conform to the protocol without providing their own implementation, *and* 
>>> is the added complexity worth protecting against this case?
>> 
>> That's quite a difficult job: do you think you can evaluate this likelihood?
>> 
>> Explicit synthesis has big advantage: it avoids this question entirely.
>> 
>> Remember that the main problem with slide (2) is that developers can not 
>> *learn* to avoid it.
>> 
>> For each type is slide (2) there is a probability that it comes into 
>> existence with a forgotten explicit protocol adoption. And this probability 
>> will not go down as people learn Swift and discover the existence of slide 
>> (2). Why? because this probability is driven by unavoidable human behaviors:
>> - developer doesn't see the problem (a programmer mistake)
>> - the developper plans to add explicit conformance later and happens to 
>> forget (carelessness)
>> - a developper extends an existing type with a transient property, and 
>> doesn't add the explicit protocol conformance that has become required.
>> 
>> Case 2 and 3 bite even experienced developers. And they can't be improved by 
>> learning.
>> 
>> Looks like the problem is better defined as an ergonomics issue, now.
>> 
>>> If someone can show me something that points to accidental synthesized 
>>> implementations being a significant barrier to smooth development in Swift, 
>>> I'm more than happy to consider that evidence. But right now, this all 
>>> seems hypothetical ("I'm worried that...") and what's being proposed is 
>>> adding complexity to the language (an entirely new axis of protocol 
>>> conformance) that would (1) solve a problem that may not exist to any great 
>>> degree, and (2) does not address the fact that if that problem does indeed 
>>> exist, then the same problem just as likely exists with certain 
>>> non-synthesized default implementations.
>> 
>> There is this sample code by Thorsten Seitz with a cached property which is 
>> quite simple and clear : 
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
>> 
>> This is the sample code that had me enter the "worried" camp.'
> 
> I really like Thorsten's example, because it actually proves that requiring 
> explicit derivation is NOT the correct approach here. (Let's set aside the 
> 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Gwendal Roué via swift-evolution

> Le 12 sept. 2017 à 12:01, Xiaodi Wu  a écrit :
> 
>> There is this sample code by Thorsten Seitz with a cached property which is 
>> quite simple and clear : 
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
>> 
>> This is the sample code that had me enter the "worried" camp.
> 
> Sorry, I fail to see what the problem is in that example. A method was 
> invoked that changed a stored property of one instance. Therefore, it’s no 
> longer equal to the other instance. If you want a custom notion of equality, 
> you should implement it yourself. In the absence of such, the _default_ 
> notion of equality is pretty clear.

Yes, I agree with you. As long as you reason in this way, there is no problem 
at all, just a programmer error.

I'll try to show that you need to play some moves further before problems 
appear. Don't look at the code as a static thing, but as a living thing.

Please follow me: will you play a little programmer game? Here is a snippet of 
code. It is embedded in this Xcode project which, as you can see, contains 
hundreds of files. Your mission is to add an extra property which should not be 
considered for Equatable adoption. How do you do that?

struct S : Equatable {
var x: Int
}

The answer is:

1. Find if there is an extension somewhere that implements Equatable 
conformance.
2. If you are eventually sure that there is no explicit conformance yet, write 
the correct one.

You may know that proving that something does not exist is harder than the 
opposite, and the step 1 above seems dubious to you. You are right. You thus 
use this smarter technique:

1. Write a dummy explicit conformance to Equatable, compile.
2. If compiler does not complain about duplicate implementation, conclude that 
there is no explicit conformance yet, and write the correct one.

Problem solved. And nice display of smartness and funny little compiler tricks. 




No. Please look at the topic from above, and look at how developers are 
working. Troubles in synthesized conformance can happen for several reasons:

1. Lack of knowledge. As you tend to day, nobody is supposed to ignore the law, 
and the bug is the fault of the programmer.
2. The developper creates the type, plans to add specific implementation, and 
forgets.
3. The developper eventually adds a property and misses the fact that a 
synthesized conformance exists (and is now incorrect).
4. The developper eventually adds a property and misses the fact that the 
synthesized conformance is now incorrect.
5. The developper eventually adds a property, plans to fix the synthesized 
conformance, and forgets.

Cases 2, 3 and 5 are examples of good faith mistakes.

In none of those cases, the compiler emits any warning. It's thus easy to 
forget or miss the problem, and uneasy to fix it (you'll need a runtime failure 
to spot it, or a thorough code review).

I hope you agree with this last sentence. This unbalance between the easiness 
of the mistake and the easiness of the fix should ring a bell to language 
designers.

Beyond that, it's very hard to improve one's skills in face of those programmer 
errors. They have not much value beyond blind punishment. You can't learn from 
them. I'm the last one who wishes to see a weird cultural paranoia against 
Equatable: look at how "smart" and versed in Swift subtleties you need to be to 
just add a simple property to an innocuous struct!

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Tony Allevato via swift-evolution
On Mon, Sep 11, 2017 at 10:05 PM Gwendal Roué 
wrote:

>
>> This doesn'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 "what generic algorithms would be written using this protocol?"
>> AutoSynthesize doesn't satisfy that—there are no generic algorithms that
>> you would write with AutoEquatable that differ from what you would write
>> with Equatable.
>>
>>
>> And so everybody has to swallow implicit and non-avoidable code synthesis
>> and shut up?
>>
>
> That's not what I said. I simply pointed out one of the barriers to
> getting a new protocol added to the language.
>
> Code synthesis is explicitly opt-in and quite avoidable—you either don't
> conform to the protocol, or you conform to the protocol and provide your
> own implementation. What folks are differing on is whether there should
> have to be *two* explicit switches that you flip instead of one.
>
>
> No. One does not add a protocol conformance by whim. One adds a protocol
> conformance by need. So the conformance to the protocol is a *given* in our
> analysis of the consequence of code synthesis. You can not say "just don't
> adopt it".
>
> As soon as I type the protocol name, I get synthesis. That's the reason
> why the synthesized code is implicit. The synthesis is explicitly written
> in the protocol documentation, if you want. But not in the programmer's
> code.
>
> I did use "non-avoidable" badly, you're right: one can avoid it, by
> providing its custom implementation.
>
> So the code synthesis out of a mere protocol adoption *is* implicit.
>
> Let's imagine a pie. The whole pie is the set of all Swift types. Some
> slice of that pie is the subset of those types that satisfy the conditions
> that allow one of our protocols to be synthesized. Now that slice of pie
> can be sliced again, into the subset of types where (1) the synthesized
> implementation is correct both in terms of strict value and of business
> logic, and (2) the subset where it is correct in terms of strict value but
> is not the right business logic because of something like transient data.
>
>
> Yes.
>
> What we have to consider is, how large is slice (2) relative to the whole
> pie, *and* what is the likelihood that developers are going to mistakenly
> conform to the protocol without providing their own implementation, *and*
> is the added complexity worth protecting against this case?
>
>
> That's quite a difficult job: do you think you can evaluate this
> likelihood?
>
> Explicit synthesis has big advantage: it avoids this question entirely.
>
> Remember that the main problem with slide (2) is that developers can not
> *learn* to avoid it.
>
> For each type is slide (2) there is a probability that it comes into
> existence with a forgotten explicit protocol adoption. And this probability
> will not go down as people learn Swift and discover the existence of slide
> (2). Why? because this probability is driven by unavoidable human behaviors:
> - developer doesn't see the problem (a programmer mistake)
> - the developper plans to add explicit conformance later and happens to
> forget (carelessness)
> - a developper extends an existing type with a transient property, and
> doesn't add the explicit protocol conformance that has become required.
>
> Case 2 and 3 bite even experienced developers. And they can't be improved
> by learning.
>
> Looks like the problem is better defined as an ergonomics issue, now.
>
> If someone can show me something that points to accidental synthesized
> implementations being a significant barrier to smooth development in Swift,
> I'm more than happy to consider that evidence. But right now, this all
> seems hypothetical ("I'm worried that...") and what's being proposed is
> adding complexity to the language (an entirely new axis of protocol
> conformance) that would (1) solve a problem that may not exist to any great
> degree, and (2) does not address the fact that if that problem does indeed
> exist, then the same problem just as likely exists with certain
> non-synthesized default implementations.
>
>
> There is this sample code by Thorsten Seitz with a cached property which
> is quite simple and clear :
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
>
> This is the sample code that had me enter the "worried" camp.'
>

I really like Thorsten's example, because it actually proves that requiring
explicit derivation is NOT the correct approach here. (Let's set aside the
fact that Optionals prevent synthesis because we don't have conditional
conformances yet, and assume that we've gotten that feature as well for the
sake of argument.)

Let's look at two scenarios:

1) Imagine I have a value type with a number of simple Equatable
properties. In a world where synthesis is explicit, I tell that value type
to "derive Equatable". Everything is fine. Later, I decide to add some
cache 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Mon, Sep 11, 2017 at 06:03 Haravikk via swift-evolution <
swift-evolution@swift.org> wrote:

> On 9 Sep 2017, at 18:41, Xiaodi Wu  wrote:
>
>
> On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> On 9 Sep 2017, at 09:33, Xiaodi Wu  wrote:
>>
>>
>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>> On 9 Sep 2017, at 02:02, Xiaodi Wu  wrote:
>>>
>>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>


 On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution <
 swift-evolution@swift.org> wrote:


 On 7 Sep 2017, at 22:02, Itai Ferber  wrote:

 protocol Fooable : Equatable { // Equatable is just a simple example
 var myFoo: Int { get }}
 extension Fooable {
 static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
 return lhs.myFoo == rhs.myFoo
 }}
 struct X : Fooable {
 let myFoo: Int
 let myName: String
 // Whoops, forgot to give an implementation of ==}
 print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // true

 This property is *necessary*, but not *sufficient* to provide a
 correct implementation. A default implementation might be able to
 *assume* something about the types that it defines, but it does not
 necessarily know enough.


 Sorry but that's a bit of a contrived example; in this case the
 protocol should *not* implement the equality operator if more
 information may be required to define equality. It should only be
 implemented if the protocol is absolutely clear that .myFoo is the only
 part of a Fooable that can or should be compared as equatable, e.g- if a
 Fooable is a database record and .myFoo is a primary key, the data could
 differ but it would still be a reference to the same record.

 To be clear, I'm not arguing that someone can't create a regular
 default implementation that also makes flawed assumptions, but that
 synthesised/reflective implementations *by their very nature have to*,
 as they cannot under every circumstance guarantee correctness when using
 parts of a concrete type that they know nothing about.

 You can’t argue this both ways:

- If you’re arguing this on principle, that in order for
synthesized implementations to be correct, they *must* be able to — 
 *under
every circumstance* — guarantee correctness, then you have to apply
the same reasoning to default protocol implementations. Given a default
protocol implementation, it is possible to come up with a (no matter how
contrived) case where the default implementation is wrong. Since you’re
arguing this *on principle*, you cannot reject contrived examples.
- If you are arguing this *in practice*, then you’re going to have
to back up your argument with evidence that synthesized examples are 
 more
often wrong than default implementations. You can’t declare that
synthesized implementations are *by nature* incorrect but allow
default implementations to slide because *in practice*, many
implementations are allowable. There’s a reason why synthesis passed 
 code
review and was accepted: in the majority of cases, synthesis was deemed 
 to
be beneficial, and would provide correct behavior. If you are willing to
say that yes, sometimes default implementations are wrong but overall
they’re correct, you’re going to have to provide hard evidence to back 
 up
the opposite case for synthesized implementations. You stated in a 
 previous
email that "A synthesised/reflective implementation however may
return a result that is simply incorrect, because it is based on
assumptions made by the protocol developer, with no input from the
developer of the concrete type. In this case the developer must 
 override it
in to provide *correct* behaviour." — if you can back this up with
evidence (say, taking a survey of a large number of model types and see 
 if
in the majority of cases synthesized implementation would be incorrect) 
 to
provide a compelling argument, then this is something that we should in
that case reconsider.


>>> Well put, and I agree with this position 100%. However, to play devil's
>>> advocate here, let me summarize what I think Haravikk is saying:
>>>
>>> I think the "synthesized" part of this is a red herring, if I understand
>>> Haravikk's argument correctly. Instead, it is this:
>>>
>>> (1) In principle, it is possible to have a default implementation for a
>>> protocol requirement that produces the 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Vladimir.S via swift-evolution

On 12.09.2017 0:35, Tony Allevato wrote:



On Mon, Sep 11, 2017 at 2:05 PM Vladimir.S via swift-evolution 
> wrote:


On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:
 > I think I do understand Haravikk's argument (actually it seems quite
straightforward
 > to me).
 >
 > An example should be:
 >
 > struct Foo : Equatable {
 >  var x: Int
 >  var cachedLabel: String? = nil
 >
 >  init(x: Int) {
 >  self.x = x
 >  }
 >
 >  mutating func label() {
 >  if let label = cachedLabel {
 >  return label
 >  }
 >  let label = calculateLabel()
 >  cachedLabel = label
 >  return cachedLabel
 >  }
 > }
 >
 > var foo1 = Foo(x: 1)
 > var foo2 = Foo(x: 1)
 > foo1 == foo2 // true
 > var label = foo1.label()
 > foo1 == foo2 // now false, due to cachedString being falsely included in 
the
comparison
 >
 > The problem is that the developer was not required to implement the 
protocol
and so
 > might forget it.
 > The difference to other default implementations is that those use the 
protocol
itself
 > as building blocks and so are correct with regards to the protocol's 
semantics,
 > whereas the synthesized equality reaches deeply into the private innards 
of a
struct
 > and therefore is much more likely to be wrong as in the example above.
 >
 > Why not just write
 >
 > *struct* Foo : *deriving* Equatable {...}
 >
 > to request the synthesized implementation?

FWIW, +100. The same should be required for Codable. I support the opinion 
that
'synthesized' methods differs from protocol-default-implementation in what 
'kind' of
data they use: defined by protocol itself or internals of the conformed 
type. And
this can lead to more un-expected problems.

If protocol is able to synthesize its requirements, it should require a
'deriving'-like marker when type conforms to it to make it absolutely clear 
what
happens here. It would be not a confusion point, but clarify the intention 
to better
understand the code.

Thinking about *future* custom protocols that could implement requirements 
in default
implementation by using macros/reflection, for me it seems like such 
protocol should
*also* somehow explicitly state that some requirements are 
auto-synthesized, probably
by conforming(derive) to some compiler-magic protocol 'AutoSynthesize'.
(i.e. 'protocol MySynthesizeable: AutoSynthesize {...}')

So each built-in protocol like Equatable/Hashable/Codable will conform to 
it, and
also, each custom "auto-synthesizeable" protocol - also should explicitly 
conform to
AutoSynthesize. So, when type conforms to it - such type should use 
'deriving'-like
marker if auto-generation of methods is expected.


This doesn'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 "what generic 
algorithms would be written using this protocol?" AutoSynthesize doesn't satisfy 
that—there are no generic algorithms that you would write with AutoEquatable that 
differ from what you would write with Equatable.




OK, got it, it was general thoughts, not exact proposal regarding the AutoSynthesize 
protocol. Probably it should be @autosynthesize directive for protocol when you 
define it or other 'marker', so when you conform to this protocol, you *can* 
explicitely use 'derived'-like keyword to make requirements auto-synthesized, 
otherwise you'll be asked by compiler for manual implementation.




I also have a question regarding future direction of 'exclusion' of fields 
from being
included into auto-generated implementation of 
Equatable/Hashable/Codable/other.

If we'll have this 'deriving'-like marker, it seems naturally if we mark 
some member
with some kind of '@noderiving' marker, like here:

struct Foo : deriving Equatable {
var x: Int
var y: Int
var z: Int
@noderiving var cachedLabel: String? = nil
}

this @noderiving directive will work for protocols based on AutoSynthesize 
magic
protocol. I.e., if you construct your own protocol with auto-synthesizeable 
methods,
to be able to *know* which members should be 'excluded' for your 
implementation, you
should base your protocol on AutoSynthesize protocol.


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's important.


However, the feature shouldn't be tied *specifically* to derived implementations 
(meaning it shouldn't be named that way). What we're really talking about is 
"transient" data—data that exists for 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-12 Thread Xiaodi Wu via swift-evolution
On Tue, Sep 12, 2017 at 00:06 Gwendal Roué via swift-evolution <
swift-evolution@swift.org> wrote:

>
>> This doesn'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 "what generic algorithms would be written using this protocol?"
>> AutoSynthesize doesn't satisfy that—there are no generic algorithms that
>> you would write with AutoEquatable that differ from what you would write
>> with Equatable.
>>
>>
>> And so everybody has to swallow implicit and non-avoidable code synthesis
>> and shut up?
>>
>
> That's not what I said. I simply pointed out one of the barriers to
> getting a new protocol added to the language.
>
> Code synthesis is explicitly opt-in and quite avoidable—you either don't
> conform to the protocol, or you conform to the protocol and provide your
> own implementation. What folks are differing on is whether there should
> have to be *two* explicit switches that you flip instead of one.
>
>
> No. One does not add a protocol conformance by whim. One adds a protocol
> conformance by need. So the conformance to the protocol is a *given* in our
> analysis of the consequence of code synthesis. You can not say "just don't
> adopt it".
>
> As soon as I type the protocol name, I get synthesis. That's the reason
> why the synthesized code is implicit. The synthesis is explicitly written
> in the protocol documentation, if you want. But not in the programmer's
> code.
>
> I did use "non-avoidable" badly, you're right: one can avoid it, by
> providing its custom implementation.
>
> So the code synthesis out of a mere protocol adoption *is* implicit.
>
> Let's imagine a pie. The whole pie is the set of all Swift types. Some
> slice of that pie is the subset of those types that satisfy the conditions
> that allow one of our protocols to be synthesized. Now that slice of pie
> can be sliced again, into the subset of types where (1) the synthesized
> implementation is correct both in terms of strict value and of business
> logic, and (2) the subset where it is correct in terms of strict value but
> is not the right business logic because of something like transient data.
>
>
> Yes.
>
> What we have to consider is, how large is slice (2) relative to the whole
> pie, *and* what is the likelihood that developers are going to mistakenly
> conform to the protocol without providing their own implementation, *and*
> is the added complexity worth protecting against this case?
>
>
> That's quite a difficult job: do you think you can evaluate this
> likelihood?
>
> Explicit synthesis has big advantage: it avoids this question entirely.
>
> Remember that the main problem with slide (2) is that developers can not
> *learn* to avoid it.
>
> For each type is slide (2) there is a probability that it comes into
> existence with a forgotten explicit protocol adoption. And this probability
> will not go down as people learn Swift and discover the existence of slide
> (2). Why? because this probability is driven by unavoidable human behaviors:
> - developer doesn't see the problem (a programmer mistake)
> - the developper plans to add explicit conformance later and happens to
> forget (carelessness)
> - a developper extends an existing type with a transient property, and
> doesn't add the explicit protocol conformance that has become required.
>
> Case 2 and 3 bite even experienced developers. And they can't be improved
> by learning.
>
> Looks like the problem is better defined as an ergonomics issue, now.
>
> If someone can show me something that points to accidental synthesized
> implementations being a significant barrier to smooth development in Swift,
> I'm more than happy to consider that evidence. But right now, this all
> seems hypothetical ("I'm worried that...") and what's being proposed is
> adding complexity to the language (an entirely new axis of protocol
> conformance) that would (1) solve a problem that may not exist to any great
> degree, and (2) does not address the fact that if that problem does indeed
> exist, then the same problem just as likely exists with certain
> non-synthesized default implementations.
>
>
> There is this sample code by Thorsten Seitz with a cached property which
> is quite simple and clear :
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
>
> This is the sample code that had me enter the "worried" camp.
>

Sorry, I fail to see what the problem is in that example. A method was
invoked that changed a stored property of one instance. Therefore, it’s no
longer equal to the other instance. If you want a custom notion of
equality, you should implement it yourself. In the absence of such, the
_default_ notion of equality is pretty clear.


> Gwendal
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Gwendal Roué via swift-evolution
> 
>> This doesn'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 
>> "what generic algorithms would be written using this protocol?" 
>> AutoSynthesize doesn't satisfy that—there are no generic algorithms that you 
>> would write with AutoEquatable that differ from what you would write with 
>> Equatable.
> 
> And so everybody has to swallow implicit and non-avoidable code synthesis and 
> shut up?
> 
> That's not what I said. I simply pointed out one of the barriers to getting a 
> new protocol added to the language.
> 
> Code synthesis is explicitly opt-in and quite avoidable—you either don't 
> conform to the protocol, or you conform to the protocol and provide your own 
> implementation. What folks are differing on is whether there should have to 
> be *two* explicit switches that you flip instead of one.

No. One does not add a protocol conformance by whim. One adds a protocol 
conformance by need. So the conformance to the protocol is a *given* in our 
analysis of the consequence of code synthesis. You can not say "just don't 
adopt it".

As soon as I type the protocol name, I get synthesis. That's the reason why the 
synthesized code is implicit. The synthesis is explicitly written in the 
protocol documentation, if you want. But not in the programmer's code.

I did use "non-avoidable" badly, you're right: one can avoid it, by providing 
its custom implementation.

So the code synthesis out of a mere protocol adoption *is* implicit.

> Let's imagine a pie. The whole pie is the set of all Swift types. Some slice 
> of that pie is the subset of those types that satisfy the conditions that 
> allow one of our protocols to be synthesized. Now that slice of pie can be 
> sliced again, into the subset of types where (1) the synthesized 
> implementation is correct both in terms of strict value and of business 
> logic, and (2) the subset where it is correct in terms of strict value but is 
> not the right business logic because of something like transient data.

Yes.

> What we have to consider is, how large is slice (2) relative to the whole 
> pie, *and* what is the likelihood that developers are going to mistakenly 
> conform to the protocol without providing their own implementation, *and* is 
> the added complexity worth protecting against this case?

That's quite a difficult job: do you think you can evaluate this likelihood?

Explicit synthesis has big advantage: it avoids this question entirely.

Remember that the main problem with slide (2) is that developers can not 
*learn* to avoid it.

For each type is slide (2) there is a probability that it comes into existence 
with a forgotten explicit protocol adoption. And this probability will not go 
down as people learn Swift and discover the existence of slide (2). Why? 
because this probability is driven by unavoidable human behaviors:
- developer doesn't see the problem (a programmer mistake)
- the developper plans to add explicit conformance later and happens to forget 
(carelessness)
- a developper extends an existing type with a transient property, and doesn't 
add the explicit protocol conformance that has become required.

Case 2 and 3 bite even experienced developers. And they can't be improved by 
learning.

Looks like the problem is better defined as an ergonomics issue, now.

> If someone can show me something that points to accidental synthesized 
> implementations being a significant barrier to smooth development in Swift, 
> I'm more than happy to consider that evidence. But right now, this all seems 
> hypothetical ("I'm worried that...") and what's being proposed is adding 
> complexity to the language (an entirely new axis of protocol conformance) 
> that would (1) solve a problem that may not exist to any great degree, and 
> (2) does not address the fact that if that problem does indeed exist, then 
> the same problem just as likely exists with certain non-synthesized default 
> implementations.

There is this sample code by Thorsten Seitz with a cached property which is 
quite simple and clear : 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170911/039684.html
 


This is the sample code that had me enter the "worried" camp.

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Tony Allevato via swift-evolution
On Mon, Sep 11, 2017 at 2:43 PM Gwendal Roué via swift-evolution <
swift-evolution@swift.org> wrote:

> Doesn't it escalate pretty quickly into complex and ad-hoc language
> constructs?
>
> Like everybody I like code synthesis. Like some, I'm worried that implicit
> synthesis would hide a few bugs that are hard to debunk. I also agree that
> developers who complain about those bugs would rightfully get the "behaves
> as expected" and "RTFM" classical answers. The problem with those deserved
> answers is that there's not much lesson to learn. Being bitten one, two,
> three times does not reduce the probability of being bitten another time.
> Programmer errors due to carelessness are the most difficult errors to
> prevent, don't you all agree?
>
> People who use Sourcery are quite happy with AutoEquatable and
> AutoHashable. I don't know of anybody who complains of those. People are
> happy. Nobody types `AutoEquatable` by mistake: they get synthesis where
> they ask for it, and move on their next task without thinking much more
> about it. Sounds like a developer's dream, isn't it?
>
> This doesn'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
> "what generic algorithms would be written using this protocol?"
> AutoSynthesize doesn't satisfy that—there are no generic algorithms that
> you would write with AutoEquatable that differ from what you would write
> with Equatable.
>
>
> And so everybody has to swallow implicit and non-avoidable code synthesis
> and shut up?
>

That's not what I said. I simply pointed out one of the barriers to getting
a new protocol added to the language.

Code synthesis is explicitly opt-in and quite avoidable—you either don't
conform to the protocol, or you conform to the protocol and provide your
own implementation. What folks are differing on is whether there should
have to be *two* explicit switches that you flip instead of one.

Let's imagine a pie. The whole pie is the set of all Swift types. Some
slice of that pie is the subset of those types that satisfy the conditions
that allow one of our protocols to be synthesized. Now that slice of pie
can be sliced again, into the subset of types where (1) the synthesized
implementation is correct both in terms of strict value and of business
logic, and (2) the subset where it is correct in terms of strict value but
is not the right business logic because of something like transient data.

What we have to consider is, how large is slice (2) relative to the whole
pie, *and* what is the likelihood that developers are going to mistakenly
conform to the protocol without providing their own implementation, *and*
is the added complexity worth protecting against this case?

If someone can show me something that points to accidental synthesized
implementations being a significant barrier to smooth development in Swift,
I'm more than happy to consider that evidence. But right now, this all
seems hypothetical ("I'm worried that...") and what's being proposed is
adding complexity to the language (an entirely new axis of protocol
conformance) that would (1) solve a problem that may not exist to any great
degree, and (2) does not address the fact that if that problem does indeed
exist, then the same problem just as likely exists with certain
non-synthesized default implementations.



>
> Gwendal
>
> Le 11 sept. 2017 à 23:05, Vladimir.S via swift-evolution <
> swift-evolution@swift.org> a écrit :
>
> On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:
>
> I think I do understand Haravikk's argument (actually it seems quite
> straightforward to me).
> An example should be:
> struct Foo : Equatable {
> var x: Int
> var cachedLabel: String? = nil
> init(x: Int) {
> self.x = x
> }
> mutating func label() {
> if let label = cachedLabel {
> return label
> }
> let label = calculateLabel()
> cachedLabel = label
> return cachedLabel
> }
> }
> var foo1 = Foo(x: 1)
> var foo2 = Foo(x: 1)
> foo1 == foo2 // true
> var label = foo1.label()
> foo1 == foo2 // now false, due to cachedString being falsely included in
> the comparison
> The problem is that the developer was not required to implement the
> protocol and so might forget it.
> The difference to other default implementations is that those use the
> protocol itself as building blocks and so are correct with regards to the
> protocol's semantics, whereas the synthesized equality reaches deeply into
> the private innards of a struct and therefore is much more likely to be
> wrong as in the example above.
> Why not just write
> *struct* Foo : *deriving* Equatable {...}
> to request the synthesized implementation?
>
>
> FWIW, +100. The same should be required for Codable. I support the opinion
> that 'synthesized' methods differs from protocol-default-implementation in
> what 'kind' of data they use: defined by protocol 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Gwendal Roué via swift-evolution

> Le 11 sept. 2017 à 23:37, Tony Allevato via swift-evolution 
>  a écrit :
> 
> 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 "transient" attribute for something wholly 
> unrelated to synthesis.

My thoughts exactly. The language is not ready yet for exclusion of some 
members in synthetic code.

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Gwendal Roué via swift-evolution

> Le 11 sept. 2017 à 23:41, Gwendal Roué  a écrit :
> 
> Doesn't it escalate pretty quickly into complex and ad-hoc language 
> constructs?
> 
> Like everybody I like code synthesis. Like some, I'm worried that implicit 
> synthesis would hide a few bugs that are hard to debunk. I also agree that 
> developers who complain about those bugs would rightfully get the "behaves as 
> expected" and "RTFM" classical answers. The problem with those deserved 
> answers is that there's not much lesson to learn. Being bitten one, two, 
> three times does not reduce the probability of being bitten another time. 
> Programmer errors due to carelessness are the most difficult errors to 
> prevent, don't you all agree?
> 
> People who use Sourcery are quite happy with AutoEquatable and AutoHashable. 
> I don't know of anybody who complains of those. People are happy. Nobody 
> types `AutoEquatable` by mistake: they get synthesis where they ask for it, 
> and move on their next task without thinking much more about it. Sounds like 
> a developer's dream, isn't it?
> 
>> This doesn'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 
>> "what generic algorithms would be written using this protocol?" 
>> AutoSynthesize doesn't satisfy that—there are no generic algorithms that you 
>> would write with AutoEquatable that differ from what you would write with 
>> Equatable.
> 
> And so everybody has to swallow implicit and non-avoidable code synthesis and 
> shut up?

Sorry Tony, I didn't quote your sentence properly.

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Gwendal Roué via swift-evolution
Doesn't it escalate pretty quickly into complex and ad-hoc language constructs?

Like everybody I like code synthesis. Like some, I'm worried that implicit 
synthesis would hide a few bugs that are hard to debunk. I also agree that 
developers who complain about those bugs would rightfully get the "behaves as 
expected" and "RTFM" classical answers. The problem with those deserved answers 
is that there's not much lesson to learn. Being bitten one, two, three times 
does not reduce the probability of being bitten another time. Programmer errors 
due to carelessness are the most difficult errors to prevent, don't you all 
agree?

People who use Sourcery are quite happy with AutoEquatable and AutoHashable. I 
don't know of anybody who complains of those. People are happy. Nobody types 
`AutoEquatable` by mistake: they get synthesis where they ask for it, and move 
on their next task without thinking much more about it. Sounds like a 
developer's dream, isn't it?

> This doesn'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 "what 
> generic algorithms would be written using this protocol?" AutoSynthesize 
> doesn't satisfy that—there are no generic algorithms that you would write 
> with AutoEquatable that differ from what you would write with Equatable.

And so everybody has to swallow implicit and non-avoidable code synthesis and 
shut up?

Gwendal

> Le 11 sept. 2017 à 23:05, Vladimir.S via swift-evolution 
>  a écrit :
> 
> On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:
>> I think I do understand Haravikk's argument (actually it seems quite 
>> straightforward to me).
>> An example should be:
>> struct Foo : Equatable {
>> var x: Int
>> var cachedLabel: String? = nil
>> init(x: Int) {
>> self.x = x
>> }
>> mutating func label() {
>> if let label = cachedLabel {
>> return label
>> }
>> let label = calculateLabel()
>> cachedLabel = label
>> return cachedLabel
>> }
>> }
>> var foo1 = Foo(x: 1)
>> var foo2 = Foo(x: 1)
>> foo1 == foo2 // true
>> var label = foo1.label()
>> foo1 == foo2 // now false, due to cachedString being falsely included in the 
>> comparison
>> The problem is that the developer was not required to implement the protocol 
>> and so might forget it.
>> The difference to other default implementations is that those use the 
>> protocol itself as building blocks and so are correct with regards to the 
>> protocol's semantics, whereas the synthesized equality reaches deeply into 
>> the private innards of a struct and therefore is much more likely to be 
>> wrong as in the example above.
>> Why not just write
>> *struct* Foo : *deriving* Equatable {...}
>> to request the synthesized implementation?
> 
> FWIW, +100. The same should be required for Codable. I support the opinion 
> that 'synthesized' methods differs from protocol-default-implementation in 
> what 'kind' of data they use: defined by protocol itself or internals of the 
> conformed type. And this can lead to more un-expected problems.
> 
> If protocol is able to synthesize its requirements, it should require a 
> 'deriving'-like marker when type conforms to it to make it absolutely clear 
> what happens here. It would be not a confusion point, but clarify the 
> intention to better understand the code.
> 
> Thinking about *future* custom protocols that could implement requirements in 
> default implementation by using macros/reflection, for me it seems like such 
> protocol should *also* somehow explicitly state that some requirements are 
> auto-synthesized, probably by conforming(derive) to some compiler-magic 
> protocol 'AutoSynthesize'.
> (i.e. 'protocol MySynthesizeable: AutoSynthesize {...}')
> 
> So each built-in protocol like Equatable/Hashable/Codable will conform to it, 
> and also, each custom "auto-synthesizeable" protocol - also should explicitly 
> conform to AutoSynthesize. So, when type conforms to it - such type should 
> use 'deriving'-like marker if auto-generation of methods is expected.
> 
> I also have a question regarding future direction of 'exclusion' of fields 
> from being included into auto-generated implementation of 
> Equatable/Hashable/Codable/other.
> 
> If we'll have this 'deriving'-like marker, it seems naturally if we mark some 
> member with some kind of '@noderiving' marker, like here:
> 
> struct Foo : deriving Equatable {
>  var x: Int
>  var y: Int
>  var z: Int
>  @noderiving var cachedLabel: String? = nil
> }
> 
> this @noderiving directive will work for protocols based on AutoSynthesize 
> magic protocol. I.e., if you construct your own protocol with 
> auto-synthesizeable methods, to be able to *know* which members should be 
> 'excluded' for your implementation, you should base your protocol on 
> AutoSynthesize protocol.
> 
> I hope this makes any 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Tony Allevato via swift-evolution
On Mon, Sep 11, 2017 at 2:05 PM Vladimir.S via swift-evolution <
swift-evolution@swift.org> wrote:

> On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:
> > I think I do understand Haravikk's argument (actually it seems quite
> straightforward
> > to me).
> >
> > An example should be:
> >
> > struct Foo : Equatable {
> >  var x: Int
> >  var cachedLabel: String? = nil
> >
> >  init(x: Int) {
> >  self.x = x
> >  }
> >
> >  mutating func label() {
> >  if let label = cachedLabel {
> >  return label
> >  }
> >  let label = calculateLabel()
> >  cachedLabel = label
> >  return cachedLabel
> >  }
> > }
> >
> > var foo1 = Foo(x: 1)
> > var foo2 = Foo(x: 1)
> > foo1 == foo2 // true
> > var label = foo1.label()
> > foo1 == foo2 // now false, due to cachedString being falsely included in
> the comparison
> >
> > The problem is that the developer was not required to implement the
> protocol and so
> > might forget it.
> > The difference to other default implementations is that those use the
> protocol itself
> > as building blocks and so are correct with regards to the protocol's
> semantics,
> > whereas the synthesized equality reaches deeply into the private innards
> of a struct
> > and therefore is much more likely to be wrong as in the example above.
> >
> > Why not just write
> >
> > *struct* Foo : *deriving* Equatable {...}
> >
> > to request the synthesized implementation?
>
> FWIW, +100. The same should be required for Codable. I support the opinion
> that
> 'synthesized' methods differs from protocol-default-implementation in what
> 'kind' of
> data they use: defined by protocol itself or internals of the conformed
> type. And
> this can lead to more un-expected problems.
>
> If protocol is able to synthesize its requirements, it should require a
> 'deriving'-like marker when type conforms to it to make it absolutely
> clear what
> happens here. It would be not a confusion point, but clarify the intention
> to better
> understand the code.
>
> Thinking about *future* custom protocols that could implement requirements
> in default
> implementation by using macros/reflection, for me it seems like such
> protocol should
> *also* somehow explicitly state that some requirements are
> auto-synthesized, probably
> by conforming(derive) to some compiler-magic protocol 'AutoSynthesize'.
> (i.e. 'protocol MySynthesizeable: AutoSynthesize {...}')
>
> So each built-in protocol like Equatable/Hashable/Codable will conform to
> it, and
> also, each custom "auto-synthesizeable" protocol - also should explicitly
> conform to
> AutoSynthesize. So, when type conforms to it - such type should use
> 'deriving'-like
> marker if auto-generation of methods is expected.
>

This doesn'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
"what generic algorithms would be written using this protocol?"
AutoSynthesize doesn't satisfy that—there are no generic algorithms that
you would write with AutoEquatable that differ from what you would write
with Equatable.



> I also have a question regarding future direction of 'exclusion' of fields
> from being
> included into auto-generated implementation of
> Equatable/Hashable/Codable/other.
>
> If we'll have this 'deriving'-like marker, it seems naturally if we mark
> some member
> with some kind of '@noderiving' marker, like here:
>
> struct Foo : deriving Equatable {
>var x: Int
>var y: Int
>var z: Int
>@noderiving var cachedLabel: String? = nil
> }
>
> this @noderiving directive will work for protocols based on AutoSynthesize
> magic
> protocol. I.e., if you construct your own protocol with
> auto-synthesizeable methods,
> to be able to *know* which members should be 'excluded' for your
> implementation, you
> should base your protocol on AutoSynthesize protocol.
>

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's important.

However, the feature shouldn't be tied *specifically* to derived
implementations (meaning it shouldn't be named that way). What we're really
talking about is "transient" data—data that exists for the purposes of
caching/performance/etc. but which does not actually contribute to the
thing's "value".

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'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 "exclude this property from synthesized
operations", but it would be fine to say "this property is transient data"
and it just so happens that Equatable, Hashable, and 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Vladimir.S via swift-evolution

On 11.09.2017 21:55, Thorsten Seitz via swift-evolution wrote:
I think I do understand Haravikk's argument (actually it seems quite straightforward 
to me).


An example should be:

struct Foo : Equatable {
 var x: Int
 var cachedLabel: String? = nil

 init(x: Int) {
 self.x = x
 }

 mutating func label() {
 if let label = cachedLabel {
 return label
 }
 let label = calculateLabel()
 cachedLabel = label
 return cachedLabel
 }
}

var foo1 = Foo(x: 1)
var foo2 = Foo(x: 1)
foo1 == foo2 // true
var label = foo1.label()
foo1 == foo2 // now false, due to cachedString being falsely included in the 
comparison

The problem is that the developer was not required to implement the protocol and so 
might forget it.
The difference to other default implementations is that those use the protocol itself 
as building blocks and so are correct with regards to the protocol's semantics, 
whereas the synthesized equality reaches deeply into the private innards of a struct 
and therefore is much more likely to be wrong as in the example above.


Why not just write

*struct* Foo : *deriving* Equatable {...}

to request the synthesized implementation?


FWIW, +100. The same should be required for Codable. I support the opinion that 
'synthesized' methods differs from protocol-default-implementation in what 'kind' of 
data they use: defined by protocol itself or internals of the conformed type. And 
this can lead to more un-expected problems.


If protocol is able to synthesize its requirements, it should require a 
'deriving'-like marker when type conforms to it to make it absolutely clear what 
happens here. It would be not a confusion point, but clarify the intention to better 
understand the code.


Thinking about *future* custom protocols that could implement requirements in default 
implementation by using macros/reflection, for me it seems like such protocol should 
*also* somehow explicitly state that some requirements are auto-synthesized, probably 
by conforming(derive) to some compiler-magic protocol 'AutoSynthesize'.

(i.e. 'protocol MySynthesizeable: AutoSynthesize {...}')

So each built-in protocol like Equatable/Hashable/Codable will conform to it, and 
also, each custom "auto-synthesizeable" protocol - also should explicitly conform to 
AutoSynthesize. So, when type conforms to it - such type should use 'deriving'-like 
marker if auto-generation of methods is expected.


I also have a question regarding future direction of 'exclusion' of fields from being 
included into auto-generated implementation of Equatable/Hashable/Codable/other.


If we'll have this 'deriving'-like marker, it seems naturally if we mark some member 
with some kind of '@noderiving' marker, like here:


struct Foo : deriving Equatable {
  var x: Int
  var y: Int
  var z: Int
  @noderiving var cachedLabel: String? = nil
}

this @noderiving directive will work for protocols based on AutoSynthesize magic 
protocol. I.e., if you construct your own protocol with auto-synthesizeable methods, 
to be able to *know* which members should be 'excluded' for your implementation, you 
should base your protocol on AutoSynthesize protocol.


I hope this makes any sense :-)

Vladimir.



-Thorsten


Am 09.09.2017 um 19:42 schrieb Xiaodi Wu via swift-evolution 
>:




On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution 
> wrote:



On 9 Sep 2017, at 09:33, Xiaodi Wu > wrote:


On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution
> wrote:



On 9 Sep 2017, at 02:02, Xiaodi Wu > wrote:

On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via
swift-evolution>wrote:




On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution
> 
wrote:



On 7 Sep 2017, at 22:02, Itai Ferber > wrote:

|protocol Fooable : Equatable { // Equatable is just a simple
example var myFoo: Int { get } } extension Fooable { static func
==(_ lhs: Self, _ rhs: Self) -> Bool { return lhs.myFoo ==
rhs.myFoo } } struct X : Fooable { let myFoo: Int let myName:
String // Whoops, forgot to give an implementation of == }
print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob"))
// true|
This property is/necessary/, but not/sufficient/to provide a
correct implementation. A default implementation might be able
to/assume/ something 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Tony Allevato via swift-evolution
On Mon, Sep 11, 2017 at 11:56 AM Thorsten Seitz via swift-evolution <
swift-evolution@swift.org> wrote:

> I think I do understand Haravikk's argument (actually it seems quite
> straightforward to me).
>
> An example should be:
>
> struct Foo : Equatable {
> var x: Int
> var cachedLabel: String? = nil
>
> init(x: Int) {
> self.x = x
> }
>
> mutating func label() {
> if let label = cachedLabel {
> return label
> }
> let label = calculateLabel()
> cachedLabel = label
> return cachedLabel
> }
> }
>
> var foo1 = Foo(x: 1)
> var foo2 = Foo(x: 1)
> foo1 == foo2 // true
> var label = foo1.label()
> foo1 == foo2 // now false, due to cachedString being falsely included in
> the comparison
>
> The problem is that the developer was not required to implement the
> protocol and so might forget it.
> The difference to other default implementations is that those use the
> protocol itself as building blocks and so are correct with regards to the
> protocol's semantics, whereas the synthesized equality reaches deeply into
> the private innards of a struct and therefore is much more likely to be
> wrong as in the example above.
>

The example above wouldn't actually get a synthesized ==, because
Optional doesn't conform to Equatable. We can't get that until we get
conditional conformances.

But if we ignore that, we see that the user has opted-in to the synthesized
== by explicitly claiming that their type conforms to a protocol that
contains a default implementation. Their decision—either by intention or
forgetful omission—to not provide a custom implementation means that the
default behavior will be used, as would any default method implementation.

I don't find the argument that "someone might say that their type conforms
to Equatable to shut the compiler up elsewhere and then forget to fill in
the implementation" very compelling—that's clearly programmer error. The
same could be true for any default method. I could say that my type
conforms to protocol X which comes with a default implementation of foo()
that is inappropriate for my type for some reason and then forget to fill
it in later. The argument that Equatable accesses properties that are not
among its requirements doesn't really make a difference—someone could just
as easily design a protocol X with some non-synthesized default method
implementations that are incorrect for some class of types (for example,
maybe there are preconditions on other requirements that can only be
verified at runtime).

If people want to argue that we need to distinguish between synthesized
default implementations and non-synthesized default implementations, it
would be helpful to provide evidence that there is a significantly large
class of bugs that will be difficult to diagnose and resolve because of
synthesized default implementations that warrants the creation of a
*completely new axis of protocol conformance* that will increase the
complexity of the language.



>
> Why not just write
>
>  *struct* Foo : *deriving* Equatable {...}
>
> to request the synthesized implementation?
>
> -Thorsten
>
>
> Am 09.09.2017 um 19:42 schrieb Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org>:
>
>
> On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> On 9 Sep 2017, at 09:33, Xiaodi Wu  wrote:
>>
>>
>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>> On 9 Sep 2017, at 02:02, Xiaodi Wu  wrote:
>>>
>>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>


 On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution <
 swift-evolution@swift.org> wrote:


 On 7 Sep 2017, at 22:02, Itai Ferber  wrote:

 protocol Fooable : Equatable { // Equatable is just a simple example
 var myFoo: Int { get }}
 extension Fooable {
 static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
 return lhs.myFoo == rhs.myFoo
 }}
 struct X : Fooable {
 let myFoo: Int
 let myName: String
 // Whoops, forgot to give an implementation of ==}
 print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // true

 This property is *necessary*, but not *sufficient* to provide a
 correct implementation. A default implementation might be able to
 *assume* something about the types that it defines, but it does not
 necessarily know enough.


 Sorry but that's a bit of a contrived example; in this case the
 protocol should *not* implement the equality operator if more
 information may be required to define equality. It should only be
 implemented if the protocol is absolutely clear that .myFoo is the only
 part of a Fooable that can or should be compared as 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Jon Shier via swift-evolution
Mainly because we want synthesis without having to debate keyword 
naming and killing the proposal, which is what happened every other time before 
the latest proposal that was actually implemented. I’ll take the tiny danger 
for the feature in the 99% of other cases which I want it.




Jon 


> On Sep 11, 2017, at 2:54 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> I think I do understand Haravikk's argument (actually it seems quite 
> straightforward to me).
> 
> An example should be:
> 
> struct Foo : Equatable {
> var x: Int
> var cachedLabel: String? = nil
> 
> init(x: Int) {
> self.x = x
> }
> 
> mutating func label() {
> if let label = cachedLabel {
> return label
> }
> let label = calculateLabel()
> cachedLabel = label
> return cachedLabel
> }
> }
> 
> var foo1 = Foo(x: 1)
> var foo2 = Foo(x: 1)
> foo1 == foo2 // true
> var label = foo1.label()
> foo1 == foo2 // now false, due to cachedString being falsely included in the 
> comparison 
> 
> The problem is that the developer was not required to implement the protocol 
> and so might forget it.
> The difference to other default implementations is that those use the 
> protocol itself as building blocks and so are correct with regards to the 
> protocol's semantics, whereas the synthesized equality reaches deeply into 
> the private innards of a struct and therefore is much more likely to be wrong 
> as in the example above.
> 
> Why not just write
> 
>  struct Foo : deriving Equatable {...}
> 
> to request the synthesized implementation?
> 
> -Thorsten
> 
> 
> Am 09.09.2017 um 19:42 schrieb Xiaodi Wu via swift-evolution 
> >:
> 
>> 
>> On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution 
>> > wrote:
>>> On 9 Sep 2017, at 09:33, Xiaodi Wu >> > wrote:
>>> 
>>> 
>>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution 
>>> > wrote:
>>> 
 On 9 Sep 2017, at 02:02, Xiaodi Wu > wrote:
 
 On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution 
 > wrote:
 
 
> On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution 
> > wrote:
> 
> 
>> On 7 Sep 2017, at 22:02, Itai Ferber > > wrote:
>> 
>> protocol Fooable : Equatable { // Equatable is just a simple example
>> var myFoo: Int { get }
>> }
>> 
>> extension Fooable {
>> static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
>> return lhs.myFoo == rhs.myFoo
>> }
>> }
>> 
>> struct X : Fooable {
>> let myFoo: Int
>> let myName: String
>> // Whoops, forgot to give an implementation of ==
>> }
>> 
>> print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // 
>> true
>> This property is necessary, but not sufficient to provide a correct 
>> implementation. A default implementation might be able to assume 
>> something about the types that it defines, but it does not necessarily 
>> know enough.
> 
> Sorry but that's a bit of a contrived example; in this case the protocol 
> should not implement the equality operator if more information may be 
> required to define equality. It should only be implemented if the 
> protocol is absolutely clear that .myFoo is the only part of a Fooable 
> that can or should be compared as equatable, e.g- if a Fooable is a 
> database record and .myFoo is a primary key, the data could differ but it 
> would still be a reference to the same record.
> 
> To be clear, I'm not arguing that someone can't create a regular default 
> implementation that also makes flawed assumptions, but that 
> synthesised/reflective implementations by their very nature have to, as 
> they cannot under every circumstance guarantee correctness when using 
> parts of a concrete type that they know nothing about.
 
 You can’t argue this both ways:
 If you’re arguing this on principle, that in order for synthesized 
 implementations to be correct, they must be able to — under every 
 circumstance — guarantee correctness, then you have to apply the same 
 reasoning to default protocol implementations. Given a default protocol 
 implementation, it is possible to come up with a (no matter how contrived) 
 case where the default implementation is wrong. Since you’re arguing this 
 on principle, you cannot reject contrived examples.
 If you are 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Thorsten Seitz via swift-evolution
I think I do understand Haravikk's argument (actually it seems quite 
straightforward to me).

An example should be:

struct Foo : Equatable {
var x: Int
var cachedLabel: String? = nil

init(x: Int) {
self.x = x
}

mutating func label() {
if let label = cachedLabel {
return label
}
let label = calculateLabel()
cachedLabel = label
return cachedLabel
}
}

var foo1 = Foo(x: 1)
var foo2 = Foo(x: 1)
foo1 == foo2 // true
var label = foo1.label()
foo1 == foo2 // now false, due to cachedString being falsely included in the 
comparison 

The problem is that the developer was not required to implement the protocol 
and so might forget it.
The difference to other default implementations is that those use the protocol 
itself as building blocks and so are correct with regards to the protocol's 
semantics, whereas the synthesized equality reaches deeply into the private 
innards of a struct and therefore is much more likely to be wrong as in the 
example above.

Why not just write

 struct Foo : deriving Equatable {...}

to request the synthesized implementation?

-Thorsten


> Am 09.09.2017 um 19:42 schrieb Xiaodi Wu via swift-evolution 
> :
> 
> 
> On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution 
>  wrote:
>>> On 9 Sep 2017, at 09:33, Xiaodi Wu  wrote:
>>> 
>>> 
>>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution 
>>>  wrote:
 
> On 9 Sep 2017, at 02:02, Xiaodi Wu  wrote:
> 
>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution 
>>  wrote:
>> 
>> 
 On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution 
  wrote:
 
 
 On 7 Sep 2017, at 22:02, Itai Ferber  wrote:
 
 protocol Fooable : Equatable { // Equatable is just a simple example
 var myFoo: Int { get }
 }
 
 extension Fooable {
 static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
 return lhs.myFoo == rhs.myFoo
 }
 }
 
 struct X : Fooable {
 let myFoo: Int
 let myName: String
 // Whoops, forgot to give an implementation of ==
 }
 
 print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // 
 true
 This property is necessary, but not sufficient to provide a correct 
 implementation. A default implementation might be able to assume 
 something about the types that it defines, but it does not necessarily 
 know enough.
>>> 
>>> Sorry but that's a bit of a contrived example; in this case the 
>>> protocol should not implement the equality operator if more information 
>>> may be required to define equality. It should only be implemented if 
>>> the protocol is absolutely clear that .myFoo is the only part of a 
>>> Fooable that can or should be compared as equatable, e.g- if a Fooable 
>>> is a database record and .myFoo is a primary key, the data could differ 
>>> but it would still be a reference to the same record.
>>> 
>>> To be clear, I'm not arguing that someone can't create a regular 
>>> default implementation that also makes flawed assumptions, but that 
>>> synthesised/reflective implementations by their very nature have to, as 
>>> they cannot under every circumstance guarantee correctness when using 
>>> parts of a concrete type that they know nothing about.
>> 
>> You can’t argue this both ways:
>> If you’re arguing this on principle, that in order for synthesized 
>> implementations to be correct, they must be able to — under every 
>> circumstance — guarantee correctness, then you have to apply the same 
>> reasoning to default protocol implementations. Given a default protocol 
>> implementation, it is possible to come up with a (no matter how 
>> contrived) case where the default implementation is wrong. Since you’re 
>> arguing this on principle, you cannot reject contrived examples.
>> If you are arguing this in practice, then you’re going to have to back 
>> up your argument with evidence that synthesized examples are more often 
>> wrong than default implementations. You can’t declare that synthesized 
>> implementations are by nature incorrect but allow default 
>> implementations to slide because in practice, many implementations are 
>> allowable. There’s a reason why synthesis passed code review and was 
>> accepted: in the majority of cases, synthesis was deemed to be 
>> beneficial, and would provide correct behavior. If you are willing to 
>> say that yes, sometimes default implementations are wrong but overall 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Jonathan Hull via swift-evolution
What if we tried a completely different type of solution (which might solve the 
issue for protocol default conformances too)?

Right now there are errors and warnings.  What if we add a third type of 
compiler feedback (let’s call it a note).  A note is a little bit like a 
warning, but it can be dismissed/acknowledged.  It is only generated once for a 
particular issue, and then it is remembered that you dismissed it so it won’t 
come back every time you compile.

So in this case, when you add an Equatable conformance post-hoc, you get a note 
(let’s say it looks like a warning, but is grey instead of yellow and has a 
different icon) saying something like “Equatable conformance was automatically 
synthesized”.  If you want to remember to add your own conformance, you can 
just leave the note there as a reminder to yourself until you do it.  If you 
want the automatic conformance then you just dismiss the note and it never 
bothers you again.

Thanks,
Jon

> On Sep 7, 2017, at 12:52 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> This is a particularly interesting use case that demonstrates a weakness 
> without a good workaround. I, for one, am glad you brought it up, and agree 
> with comments above that auto-generated mandatory enum conformance is a topic 
> perhaps worth revisiting, given this compelling example.
> On Thu, Sep 7, 2017 at 14:32 Gwendal Roué via swift-evolution 
> > wrote:
> 
>> Le 7 sept. 2017 à 19:53, Tony Allevato > > a écrit :
>> 
>> Again, this is not the issue that Haravikk is describing in this thread.
> 
> Yes, I better understand now. Please forgive the pollution.
> 
> Gwendal
> 
> ___
> 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


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Haravikk via swift-evolution

> On 9 Sep 2017, at 18:41, Xiaodi Wu  wrote:
> 
> 
> On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution 
> > wrote:
>> On 9 Sep 2017, at 09:33, Xiaodi Wu > > wrote:
>> 
>> 
>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution 
>> > wrote:
>> 
>>> On 9 Sep 2017, at 02:02, Xiaodi Wu >> > wrote:
>>> 
>>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution 
>>> > wrote:
>>> 
>>> 
 On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution 
 > wrote:
 
 
> On 7 Sep 2017, at 22:02, Itai Ferber  > wrote:
> 
> protocol Fooable : Equatable { // Equatable is just a simple example
> var myFoo: Int { get }
> }
> 
> extension Fooable {
> static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
> return lhs.myFoo == rhs.myFoo
> }
> }
> 
> struct X : Fooable {
> let myFoo: Int
> let myName: String
> // Whoops, forgot to give an implementation of ==
> }
> 
> print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // 
> true
> This property is necessary, but not sufficient to provide a correct 
> implementation. A default implementation might be able to assume 
> something about the types that it defines, but it does not necessarily 
> know enough.
 
 Sorry but that's a bit of a contrived example; in this case the protocol 
 should not implement the equality operator if more information may be 
 required to define equality. It should only be implemented if the protocol 
 is absolutely clear that .myFoo is the only part of a Fooable that can or 
 should be compared as equatable, e.g- if a Fooable is a database record 
 and .myFoo is a primary key, the data could differ but it would still be a 
 reference to the same record.
 
 To be clear, I'm not arguing that someone can't create a regular default 
 implementation that also makes flawed assumptions, but that 
 synthesised/reflective implementations by their very nature have to, as 
 they cannot under every circumstance guarantee correctness when using 
 parts of a concrete type that they know nothing about.
>>> 
>>> You can’t argue this both ways:
>>> If you’re arguing this on principle, that in order for synthesized 
>>> implementations to be correct, they must be able to — under every 
>>> circumstance — guarantee correctness, then you have to apply the same 
>>> reasoning to default protocol implementations. Given a default protocol 
>>> implementation, it is possible to come up with a (no matter how contrived) 
>>> case where the default implementation is wrong. Since you’re arguing this 
>>> on principle, you cannot reject contrived examples.
>>> If you are arguing this in practice, then you’re going to have to back up 
>>> your argument with evidence that synthesized examples are more often wrong 
>>> than default implementations. You can’t declare that synthesized 
>>> implementations are by nature incorrect but allow default implementations 
>>> to slide because in practice, many implementations are allowable. There’s a 
>>> reason why synthesis passed code review and was accepted: in the majority 
>>> of cases, synthesis was deemed to be beneficial, and would provide correct 
>>> behavior. If you are willing to say that yes, sometimes default 
>>> implementations are wrong but overall they’re correct, you’re going to have 
>>> to provide hard evidence to back up the opposite case for synthesized 
>>> implementations. You stated in a previous email that "A 
>>> synthesised/reflective implementation however may return a result that is 
>>> simply incorrect, because it is based on assumptions made by the protocol 
>>> developer, with no input from the developer of the concrete type. In this 
>>> case the developer must override it in to provide correct behaviour." — if 
>>> you can back this up with evidence (say, taking a survey of a large number 
>>> of model types and see if in the majority of cases synthesized 
>>> implementation would be incorrect) to provide a compelling argument, then 
>>> this is something that we should in that case reconsider.
>>> 
>>> Well put, and I agree with this position 100%. However, to play devil's 
>>> advocate here, let me summarize what I think Haravikk is saying:
>>> 
>>> I think the "synthesized" part of this is a red herring, if I understand 
>>> Haravikk's argument correctly. Instead, it is this:
>>> 
>>> (1) In principle, it is possible to have a default implementation for a 
>>> 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-09 Thread Gwendal Roué via swift-evolution
All right, I'll be more positive: our science, IT, is a *constructive* science, 
by *essence*. If there is a problem, there must be a way to show it.

It you can't, then there is no problem.

Gwendal

> Le 9 sept. 2017 à 15:26, Gwendal Roué  a écrit :
> 
> Hello Haravikk,
> 
> I'lm worried that you fail at preventing a real problem. May I suggest a 
> change in your strategy?
> 
> Sometimes, sample code greatly helps turning subtle ideas into blatant 
> evidence. After all, subtleties are all about corner cases, and corner cases 
> are the blind spots of imagination. What about giving that little something 
> that would help your readers grasp your arguments?
> 
> I don't quite know what example you will provide, but I could suggest the 
> exhibition of a practical problem with Equatable synthesis. We'll know better 
> if the problem can arise in the Standard lib, in third-party libraries, at 
> application level, or at several scales at the same time. It would also be 
> nice to see your solution to the problem, that is to say an alternative that 
> still provides code synthesis for developers that want to opt in the feature, 
> but avoids the caveat of the initial example. I hope this would greatly help 
> the discussion move forward.
> 
> Last general comment about the topic: if Haravikk is right, and that code 
> synthesis should indeed be explicit, then that wouldn't be such a shame.
> 
> My two cents,
> Gwendal Roué
> 
> 
>> Le 9 sept. 2017 à 13:41, Haravikk via swift-evolution 
>> > a écrit :
>> 
>>> 
>>> On 9 Sep 2017, at 09:33, Xiaodi Wu >> > wrote:
>>> 
>>> 
>>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution 
>>> > wrote:
>>> 
 On 9 Sep 2017, at 02:02, Xiaodi Wu > wrote:
 
 On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution 
 > wrote:
 
 
> On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution 
> > wrote:
> 
> 
>> On 7 Sep 2017, at 22:02, Itai Ferber > > wrote:
>> 
>> protocol Fooable : Equatable { // Equatable is just a simple example
>> var myFoo: Int { get }
>> }
>> 
>> extension Fooable {
>> static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
>> return lhs.myFoo == rhs.myFoo
>> }
>> }
>> 
>> struct X : Fooable {
>> let myFoo: Int
>> let myName: String
>> // Whoops, forgot to give an implementation of ==
>> }
>> 
>> print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // 
>> true
>> This property is necessary, but not sufficient to provide a correct 
>> implementation. A default implementation might be able to assume 
>> something about the types that it defines, but it does not necessarily 
>> know enough.
> 
> Sorry but that's a bit of a contrived example; in this case the protocol 
> should not implement the equality operator if more information may be 
> required to define equality. It should only be implemented if the 
> protocol is absolutely clear that .myFoo is the only part of a Fooable 
> that can or should be compared as equatable, e.g- if a Fooable is a 
> database record and .myFoo is a primary key, the data could differ but it 
> would still be a reference to the same record.
> 
> To be clear, I'm not arguing that someone can't create a regular default 
> implementation that also makes flawed assumptions, but that 
> synthesised/reflective implementations by their very nature have to, as 
> they cannot under every circumstance guarantee correctness when using 
> parts of a concrete type that they know nothing about.
 
 You can’t argue this both ways:
 If you’re arguing this on principle, that in order for synthesized 
 implementations to be correct, they must be able to — under every 
 circumstance — guarantee correctness, then you have to apply the same 
 reasoning to default protocol implementations. Given a default protocol 
 implementation, it is possible to come up with a (no matter how contrived) 
 case where the default implementation is wrong. Since you’re arguing this 
 on principle, you cannot reject contrived examples.
 If you are arguing this in practice, then you’re going to have to back up 
 your argument with evidence that synthesized examples are more often wrong 
 than default implementations. You can’t declare that synthesized 
 implementations are by nature incorrect but allow default implementations 
 to slide because in 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-09 Thread Xiaodi Wu via swift-evolution
On Sat, Sep 9, 2017 at 06:41 Haravikk via swift-evolution <
swift-evolution@swift.org> wrote:

> On 9 Sep 2017, at 09:33, Xiaodi Wu  wrote:
>
>
> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> On 9 Sep 2017, at 02:02, Xiaodi Wu  wrote:
>>
>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>>
>>> On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>
>>> On 7 Sep 2017, at 22:02, Itai Ferber  wrote:
>>>
>>> protocol Fooable : Equatable { // Equatable is just a simple example
>>> var myFoo: Int { get }}
>>> extension Fooable {
>>> static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
>>> return lhs.myFoo == rhs.myFoo
>>> }}
>>> struct X : Fooable {
>>> let myFoo: Int
>>> let myName: String
>>> // Whoops, forgot to give an implementation of ==}
>>> print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // true
>>>
>>> This property is *necessary*, but not *sufficient* to provide a correct
>>> implementation. A default implementation might be able to *assume* something
>>> about the types that it defines, but it does not necessarily know enough.
>>>
>>>
>>> Sorry but that's a bit of a contrived example; in this case the protocol
>>> should *not* implement the equality operator if more information may be
>>> required to define equality. It should only be implemented if the protocol
>>> is absolutely clear that .myFoo is the only part of a Fooable that can or
>>> should be compared as equatable, e.g- if a Fooable is a database record and
>>> .myFoo is a primary key, the data could differ but it would still be a
>>> reference to the same record.
>>>
>>> To be clear, I'm not arguing that someone can't create a regular default
>>> implementation that also makes flawed assumptions, but that
>>> synthesised/reflective implementations *by their very nature have to*,
>>> as they cannot under every circumstance guarantee correctness when using
>>> parts of a concrete type that they know nothing about.
>>>
>>> You can’t argue this both ways:
>>>
>>>- If you’re arguing this on principle, that in order for synthesized
>>>implementations to be correct, they *must* be able to — *under every
>>>circumstance* — guarantee correctness, then you have to apply the
>>>same reasoning to default protocol implementations. Given a default
>>>protocol implementation, it is possible to come up with a (no matter how
>>>contrived) case where the default implementation is wrong. Since you’re
>>>arguing this *on principle*, you cannot reject contrived examples.
>>>- If you are arguing this *in practice*, then you’re going to have
>>>to back up your argument with evidence that synthesized examples are more
>>>often wrong than default implementations. You can’t declare that
>>>synthesized implementations are *by nature* incorrect but allow
>>>default implementations to slide because *in practice*, many
>>>implementations are allowable. There’s a reason why synthesis passed code
>>>review and was accepted: in the majority of cases, synthesis was deemed 
>>> to
>>>be beneficial, and would provide correct behavior. If you are willing to
>>>say that yes, sometimes default implementations are wrong but overall
>>>they’re correct, you’re going to have to provide hard evidence to back up
>>>the opposite case for synthesized implementations. You stated in a 
>>> previous
>>>email that "A synthesised/reflective implementation however may
>>>return a result that is simply incorrect, because it is based on
>>>assumptions made by the protocol developer, with no input from the
>>>developer of the concrete type. In this case the developer must override 
>>> it
>>>in to provide *correct* behaviour." — if you can back this up with
>>>evidence (say, taking a survey of a large number of model types and see 
>>> if
>>>in the majority of cases synthesized implementation would be incorrect) 
>>> to
>>>provide a compelling argument, then this is something that we should in
>>>that case reconsider.
>>>
>>>
>> Well put, and I agree with this position 100%. However, to play devil's
>> advocate here, let me summarize what I think Haravikk is saying:
>>
>> I think the "synthesized" part of this is a red herring, if I understand
>> Haravikk's argument correctly. Instead, it is this:
>>
>> (1) In principle, it is possible to have a default implementation for a
>> protocol requirement that produces the correct result--though not
>> necessarily in the most performant way--for all possible conforming types,
>> where by conforming we mean that the type respects both the syntactic
>> requirements (enforced by the compiler) and the semantic requirements
>> (which may not necessarily be enforceable by 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-09 Thread Xiaodi Wu via swift-evolution
On Sat, Sep 9, 2017 at 07:51 Brent Royal-Gordon 
wrote:

> On Sep 8, 2017, at 6:03 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> For any open protocol (i.e., a protocol for which the universe of possible
> conforming types cannot be enumerated a priori by the protocol designer)
> worthy of being a protocol by the Swift standard ("what useful thing can
> you do with such a protocol that you could not without?"), any sufficiently
> interesting requirement (i.e., one for which user ergonomics would
> measurably benefit from a default implementation) either cannot have a
> universally guaranteed correct implementation or has an implementation
> which is also going to be the most performant one (which can therefore be a
> non-overridable protocol extension method rather than an overridable
> protocol requirement with a default implementation).
>
>
> Counter-example: `index(of:)`, or rather, the underscored requirement
> underlying `index(of:)`. The "loop over all indices and return the first
> whose element matches" default implementation is universally guaranteed to
> be correct, but a collection like `Set` or `SortedArray` can provide an
> implementation which is more performant than the default.
>

Don't get me started on Swift's handling of equality and arrays with NaN.
_customIndexOfEquatable, if I'm not mistaken, is a part of that whole
tangle of performance optimizations which gleefully refuse to acknowledge
Equatable's semantic peephole for some values of a type being unordered
with respect to everything else. In a world where this trade-off between
performance and correctness had not been taken, I don't imagine that it
would be possible to make the protocol extension method 'index(of:)' any
more performant than 'index(where: { $0 == $1 })'.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-09 Thread Gwendal Roué via swift-evolution
Hello Haravikk,

I'lm worried that you fail at preventing a real problem. May I suggest a change 
in your strategy?

Sometimes, sample code greatly helps turning subtle ideas into blatant 
evidence. After all, subtleties are all about corner cases, and corner cases 
are the blind spots of imagination. What about giving that little something 
that would help your readers grasp your arguments?

I don't quite know what example you will provide, but I could suggest the 
exhibition of a practical problem with Equatable synthesis. We'll know better 
if the problem can arise in the Standard lib, in third-party libraries, at 
application level, or at several scales at the same time. It would also be nice 
to see your solution to the problem, that is to say an alternative that still 
provides code synthesis for developers that want to opt in the feature, but 
avoids the caveat of the initial example. I hope this would greatly help the 
discussion move forward.

Last general comment about the topic: if Haravikk is right, and that code 
synthesis should indeed be explicit, then that wouldn't be such a shame.

My two cents,
Gwendal Roué


> Le 9 sept. 2017 à 13:41, Haravikk via swift-evolution 
>  a écrit :
> 
>> 
>> On 9 Sep 2017, at 09:33, Xiaodi Wu > > wrote:
>> 
>> 
>> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution 
>> > wrote:
>> 
>>> On 9 Sep 2017, at 02:02, Xiaodi Wu >> > wrote:
>>> 
>>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution 
>>> > wrote:
>>> 
>>> 
 On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution 
 > wrote:
 
 
> On 7 Sep 2017, at 22:02, Itai Ferber  > wrote:
> 
> protocol Fooable : Equatable { // Equatable is just a simple example
> var myFoo: Int { get }
> }
> 
> extension Fooable {
> static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
> return lhs.myFoo == rhs.myFoo
> }
> }
> 
> struct X : Fooable {
> let myFoo: Int
> let myName: String
> // Whoops, forgot to give an implementation of ==
> }
> 
> print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // 
> true
> This property is necessary, but not sufficient to provide a correct 
> implementation. A default implementation might be able to assume 
> something about the types that it defines, but it does not necessarily 
> know enough.
 
 Sorry but that's a bit of a contrived example; in this case the protocol 
 should not implement the equality operator if more information may be 
 required to define equality. It should only be implemented if the protocol 
 is absolutely clear that .myFoo is the only part of a Fooable that can or 
 should be compared as equatable, e.g- if a Fooable is a database record 
 and .myFoo is a primary key, the data could differ but it would still be a 
 reference to the same record.
 
 To be clear, I'm not arguing that someone can't create a regular default 
 implementation that also makes flawed assumptions, but that 
 synthesised/reflective implementations by their very nature have to, as 
 they cannot under every circumstance guarantee correctness when using 
 parts of a concrete type that they know nothing about.
>>> 
>>> You can’t argue this both ways:
>>> If you’re arguing this on principle, that in order for synthesized 
>>> implementations to be correct, they must be able to — under every 
>>> circumstance — guarantee correctness, then you have to apply the same 
>>> reasoning to default protocol implementations. Given a default protocol 
>>> implementation, it is possible to come up with a (no matter how contrived) 
>>> case where the default implementation is wrong. Since you’re arguing this 
>>> on principle, you cannot reject contrived examples.
>>> If you are arguing this in practice, then you’re going to have to back up 
>>> your argument with evidence that synthesized examples are more often wrong 
>>> than default implementations. You can’t declare that synthesized 
>>> implementations are by nature incorrect but allow default implementations 
>>> to slide because in practice, many implementations are allowable. There’s a 
>>> reason why synthesis passed code review and was accepted: in the majority 
>>> of cases, synthesis was deemed to be beneficial, and would provide correct 
>>> behavior. If you are willing to say that yes, sometimes default 
>>> implementations are wrong but overall they’re correct, you’re going to have 
>>> to provide hard evidence to back up the opposite case for synthesized 
>>> 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-09 Thread Brent Royal-Gordon via swift-evolution
> On Sep 8, 2017, at 6:03 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> For any open protocol (i.e., a protocol for which the universe of possible 
> conforming types cannot be enumerated a priori by the protocol designer) 
> worthy of being a protocol by the Swift standard ("what useful thing can you 
> do with such a protocol that you could not without?"), any sufficiently 
> interesting requirement (i.e., one for which user ergonomics would measurably 
> benefit from a default implementation) either cannot have a universally 
> guaranteed correct implementation or has an implementation which is also 
> going to be the most performant one (which can therefore be a non-overridable 
> protocol extension method rather than an overridable protocol requirement 
> with a default implementation). 

Counter-example: `index(of:)`, or rather, the underscored requirement 
underlying `index(of:)`. The "loop over all indices and return the first whose 
element matches" default implementation is universally guaranteed to be 
correct, but a collection like `Set` or `SortedArray` can provide an 
implementation which is more performant than the default.

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-09 Thread Haravikk via swift-evolution

> On 9 Sep 2017, at 09:33, Xiaodi Wu  wrote:
> 
> 
> On Sat, Sep 9, 2017 at 02:47 Haravikk via swift-evolution 
> > wrote:
> 
>> On 9 Sep 2017, at 02:02, Xiaodi Wu > > wrote:
>> 
>> On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution 
>>> > wrote:
>>> 
>>> 
 On 7 Sep 2017, at 22:02, Itai Ferber > wrote:
 
 protocol Fooable : Equatable { // Equatable is just a simple example
 var myFoo: Int { get }
 }
 
 extension Fooable {
 static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
 return lhs.myFoo == rhs.myFoo
 }
 }
 
 struct X : Fooable {
 let myFoo: Int
 let myName: String
 // Whoops, forgot to give an implementation of ==
 }
 
 print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // true
 This property is necessary, but not sufficient to provide a correct 
 implementation. A default implementation might be able to assume something 
 about the types that it defines, but it does not necessarily know enough.
>>> 
>>> Sorry but that's a bit of a contrived example; in this case the protocol 
>>> should not implement the equality operator if more information may be 
>>> required to define equality. It should only be implemented if the protocol 
>>> is absolutely clear that .myFoo is the only part of a Fooable that can or 
>>> should be compared as equatable, e.g- if a Fooable is a database record and 
>>> .myFoo is a primary key, the data could differ but it would still be a 
>>> reference to the same record.
>>> 
>>> To be clear, I'm not arguing that someone can't create a regular default 
>>> implementation that also makes flawed assumptions, but that 
>>> synthesised/reflective implementations by their very nature have to, as 
>>> they cannot under every circumstance guarantee correctness when using parts 
>>> of a concrete type that they know nothing about.
>> 
>> You can’t argue this both ways:
>> If you’re arguing this on principle, that in order for synthesized 
>> implementations to be correct, they must be able to — under every 
>> circumstance — guarantee correctness, then you have to apply the same 
>> reasoning to default protocol implementations. Given a default protocol 
>> implementation, it is possible to come up with a (no matter how contrived) 
>> case where the default implementation is wrong. Since you’re arguing this on 
>> principle, you cannot reject contrived examples.
>> If you are arguing this in practice, then you’re going to have to back up 
>> your argument with evidence that synthesized examples are more often wrong 
>> than default implementations. You can’t declare that synthesized 
>> implementations are by nature incorrect but allow default implementations to 
>> slide because in practice, many implementations are allowable. There’s a 
>> reason why synthesis passed code review and was accepted: in the majority of 
>> cases, synthesis was deemed to be beneficial, and would provide correct 
>> behavior. If you are willing to say that yes, sometimes default 
>> implementations are wrong but overall they’re correct, you’re going to have 
>> to provide hard evidence to back up the opposite case for synthesized 
>> implementations. You stated in a previous email that "A 
>> synthesised/reflective implementation however may return a result that is 
>> simply incorrect, because it is based on assumptions made by the protocol 
>> developer, with no input from the developer of the concrete type. In this 
>> case the developer must override it in to provide correct behaviour." — if 
>> you can back this up with evidence (say, taking a survey of a large number 
>> of model types and see if in the majority of cases synthesized 
>> implementation would be incorrect) to provide a compelling argument, then 
>> this is something that we should in that case reconsider.
>> 
>> Well put, and I agree with this position 100%. However, to play devil's 
>> advocate here, let me summarize what I think Haravikk is saying:
>> 
>> I think the "synthesized" part of this is a red herring, if I understand 
>> Haravikk's argument correctly. Instead, it is this:
>> 
>> (1) In principle, it is possible to have a default implementation for a 
>> protocol requirement that produces the correct result--though not 
>> necessarily in the most performant way--for all possible conforming types, 
>> where by conforming we mean that the type respects both the syntactic 
>> requirements (enforced by the compiler) and the semantic requirements (which 
>> may not necessarily be enforceable by the 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-08 Thread Xiaodi Wu via swift-evolution
On Fri, Sep 8, 2017 at 4:00 PM, Itai Ferber via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> On 7 Sep 2017, at 22:02, Itai Ferber  wrote:
>
> protocol Fooable : Equatable { // Equatable is just a simple example
> var myFoo: Int { get }}
> extension Fooable {
> static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
> return lhs.myFoo == rhs.myFoo
> }}
> struct X : Fooable {
> let myFoo: Int
> let myName: String
> // Whoops, forgot to give an implementation of ==}
> print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // true
>
> This property is *necessary*, but not *sufficient* to provide a correct
> implementation. A default implementation might be able to *assume* something
> about the types that it defines, but it does not necessarily know enough.
>
>
> Sorry but that's a bit of a contrived example; in this case the protocol
> should *not* implement the equality operator if more information may be
> required to define equality. It should only be implemented if the protocol
> is absolutely clear that .myFoo is the only part of a Fooable that can or
> should be compared as equatable, e.g- if a Fooable is a database record and
> .myFoo is a primary key, the data could differ but it would still be a
> reference to the same record.
>
> To be clear, I'm not arguing that someone can't create a regular default
> implementation that also makes flawed assumptions, but that
> synthesised/reflective implementations *by their very nature have to*, as
> they cannot under every circumstance guarantee correctness when using parts
> of a concrete type that they know nothing about.
>
> You can’t argue this both ways:
>
>- If you’re arguing this on principle, that in order for synthesized
>implementations to be correct, they *must* be able to — *under every
>circumstance* — guarantee correctness, then you have to apply the same
>reasoning to default protocol implementations. Given a default protocol
>implementation, it is possible to come up with a (no matter how contrived)
>case where the default implementation is wrong. Since you’re arguing this 
> *on
>principle*, you cannot reject contrived examples.
>- If you are arguing this *in practice*, then you’re going to have to
>back up your argument with evidence that synthesized examples are more
>often wrong than default implementations. You can’t declare that
>synthesized implementations are *by nature* incorrect but allow
>default implementations to slide because *in practice*, many
>implementations are allowable. There’s a reason why synthesis passed code
>review and was accepted: in the majority of cases, synthesis was deemed to
>be beneficial, and would provide correct behavior. If you are willing to
>say that yes, sometimes default implementations are wrong but overall
>they’re correct, you’re going to have to provide hard evidence to back up
>the opposite case for synthesized implementations. You stated in a previous
>email that "A synthesised/reflective implementation however may return
>a result that is simply incorrect, because it is based on assumptions made
>by the protocol developer, with no input from the developer of the concrete
>type. In this case the developer must override it in to provide
>*correct* behaviour." — if you can back this up with evidence (say,
>taking a survey of a large number of model types and see if in the majority
>of cases synthesized implementation would be incorrect) to provide a
>compelling argument, then this is something that we should in that case
>reconsider.
>
>
Well put, and I agree with this position 100%. However, to play devil's
advocate here, let me summarize what I think Haravikk is saying:

I think the "synthesized" part of this is a red herring, if I understand
Haravikk's argument correctly. Instead, it is this:

(1) In principle, it is possible to have a default implementation for a
protocol requirement that produces the correct result--though not
necessarily in the most performant way--for all possible conforming types,
where by conforming we mean that the type respects both the syntactic
requirements (enforced by the compiler) and the semantic requirements
(which may not necessarily be enforceable by the compiler) of the protocol
in question.

(2) However, there exist *some* requirements that, by their very nature,
cannot have default implementations which are guaranteed to produce the
correct result for all conforming types. In Haravikk's view, no default
implementations should be provided in these cases. (I don't necessarily
subscribe to this view in absolute terms, but for the sake of argument
let's grant this premise.)

(3) Equatable, Hashable, and Codable requirements are, by their very
nature, such requirements that cannot have 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-08 Thread Itai Ferber via swift-evolution


> On Sep 8, 2017, at 12:46 AM, Haravikk via swift-evolution 
>  wrote:
> 
> 
>> On 7 Sep 2017, at 22:02, Itai Ferber > > wrote:
>> 
>> protocol Fooable : Equatable { // Equatable is just a simple example
>> var myFoo: Int { get }
>> }
>> 
>> extension Fooable {
>> static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
>> return lhs.myFoo == rhs.myFoo
>> }
>> }
>> 
>> struct X : Fooable {
>> let myFoo: Int
>> let myName: String
>> // Whoops, forgot to give an implementation of ==
>> }
>> 
>> print(X(myFoo: 42, myName: "Alice") == X(myFoo: 42, myName: "Bob")) // true
>> This property is necessary, but not sufficient to provide a correct 
>> implementation. A default implementation might be able to assume something 
>> about the types that it defines, but it does not necessarily know enough.
> 
> Sorry but that's a bit of a contrived example; in this case the protocol 
> should not implement the equality operator if more information may be 
> required to define equality. It should only be implemented if the protocol is 
> absolutely clear that .myFoo is the only part of a Fooable that can or should 
> be compared as equatable, e.g- if a Fooable is a database record and .myFoo 
> is a primary key, the data could differ but it would still be a reference to 
> the same record.
> 
> To be clear, I'm not arguing that someone can't create a regular default 
> implementation that also makes flawed assumptions, but that 
> synthesised/reflective implementations by their very nature have to, as they 
> cannot under every circumstance guarantee correctness when using parts of a 
> concrete type that they know nothing about.
You can’t argue this both ways:
If you’re arguing this on principle, that in order for synthesized 
implementations to be correct, they must be able to — under every circumstance 
— guarantee correctness, then you have to apply the same reasoning to default 
protocol implementations. Given a default protocol implementation, it is 
possible to come up with a (no matter how contrived) case where the default 
implementation is wrong. Since you’re arguing this on principle, you cannot 
reject contrived examples.
If you are arguing this in practice, then you’re going to have to back up your 
argument with evidence that synthesized examples are more often wrong than 
default implementations. You can’t declare that synthesized implementations are 
by nature incorrect but allow default implementations to slide because in 
practice, many implementations are allowable. There’s a reason why synthesis 
passed code review and was accepted: in the majority of cases, synthesis was 
deemed to be beneficial, and would provide correct behavior. If you are 
willing to say that yes, sometimes default implementations are wrong but 
overall they’re correct, you’re going to have to provide hard evidence to back 
up the opposite case for synthesized implementations. You stated in a previous 
email that "A synthesised/reflective implementation however may return a result 
that is simply incorrect, because it is based on assumptions made by the 
protocol developer, with no input from the developer of the concrete type. In 
this case the developer must override it in to provide correct behaviour." — if 
you can back this up with evidence (say, taking a survey of a large number of 
model types and see if in the majority of cases synthesized implementation 
would be incorrect) to provide a compelling argument, then this is something 
that we should in that case reconsider.

>>> Reflective/synthesised default implementations must by their very nature 
>>> make assumptions about a concrete type that are not cannot be guaranteed to 
>>> be correct. The properties and methods they may end up interacting withmay 
>>> have nothing at all to do with the protocol. Equatable remains by far the 
>>> simplest example; just because a developer has used equatable properties 
>>> does not guarantee that all of them should be compared during a check for 
>>> equality.
>> In the same way that you might consider synthesized conformances to 
>> overreach into a type and touch things which are not related to a protocol, 
>> default implementations can be considered underreach in that they don’t know 
>> anything about properties which are necessary for providing a correct 
>> implementation.
> 
> If more information is necessary to provide a correct implementation, then a 
> default implementation shouldn't be provided. This is what unimplemented 
> properties and methods are for; either getting the developer to provide the 
> missing information, or getting them to implement the correct behaviour.
I agree, but you can’t selectively argue this.

> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Itai Ferber via swift-evolution


> On Sep 7, 2017, at 1:43 PM, Haravikk via swift-evolution 
>  wrote:
> 
>> 
>> On 7 Sep 2017, at 19:36, Tony Allevato > > wrote:
>> 
>> 
>> 
>> On Thu, Sep 7, 2017 at 11:18 AM Haravikk via swift-evolution 
>> > wrote:
>> 
>>> On 7 Sep 2017, at 18:53, Tony Allevato via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
>>> On Thu, Sep 7, 2017 at 10:39 AM Gwendal Roué >> > wrote:
 Le 7 sept. 2017 à 14:45, Tony Allevato > a écrit :
 
 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.
>>> 
>>> Yes.
>>> 
 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).
>>> 
>>> Yes, unfortunately.
>>> 
>>> 
 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.
>>> 
>>> Yes. I'm not talking about implementation itself. I know this has been the 
>>> main topic until I have tried to bring in the topic of the consequences of 
>>> non-avoidable synthesis (extra methods that may conflict with userland 
>>> methods).
>>> 
>>> If you ask me for a real-world case, then I think I gave one. Let me 
>>> rephrase it:
>>> 
>>> it's impossible to define a value-backed enum without getting free 
>>> Equatable conformance. This free conformance is sometimes unwanted, and I 
>>> gave the example of DSLs. Now this problem is not *severe*. It's more a 
>>> blind spot in the language, and finally just an unwanted side-effect of a 
>>> compiler convenience,
>>> 
>>> Again, this is not the issue that Haravikk is describing in this thread.
>>> 
>>> I'll clarify—your issue is specifically with the fact that enums with raw 
>>> values and enums without associated values receive Equatable even without 
>>> explicitly conforming to it, and therefore users have no way of opting out 
>>> of it. This predates SE-0185, and I didn't propose making any changes to 
>>> the conformance of those enums for source compatibility reasons, though I 
>>> wouldn't be opposed to it because it makes them consistent across the board.
>>> 
>>> Haravikk's argument is about synthesized conformances like Codable and 
>>> Equatable/Hashable in SE-0185, where the user must explicitly conform the 
>>> type to those protocols. His claim is that that act of opting in is not 
>>> sufficient and that it is still dangerous if those synthesized conformances 
>>> can access members that are not also declared in the protocol. That's a 
>>> completely separate issue to yours, and one that I hope he'll present more 
>>> evidence of. Right now, requiring that you not only explicitly conform to 
>>> the protocol but also explicitly request the synthesis feels like a 
>>> solution without an actual problem, and is a situation we already have 
>>> today with default method implementations.
>> 
>> The simplest real-world case is easy:
>> 
>>  struct Foo { var data:String }
>>  extension Foo : Equatable {} // This currently produces an error, in 
>> future it will not
>> 
>> 
>> Why is this a problem? It's no different than if someone extended Foo to 
>> conform to a protocol with a default implementation that was written in code.
> 
> I'm sorry but I have now explained why it isn't multiple times; a 
> non-reflective default conformance can ONLY act upon methods and properties 
> that the protocol itself has defined, meaning that it knows everything it 
> needs to know in order to do whatever it wants to do with those methods and 
> properties because it defined them.
Just because it might have defined the properties does not necessarily mean 
that those properties are sufficient context for providing a default 
implementation:
protocol Fooable : Equatable { // Equatable is just a simple example
var myFoo: Int { get }
}

extension Fooable {
static func ==(_ lhs: Self, _ rhs: Self) -> Bool {
return lhs.myFoo == 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Haravikk via swift-evolution

> On 7 Sep 2017, at 19:36, Tony Allevato  wrote:
> 
> 
> 
> On Thu, Sep 7, 2017 at 11:18 AM Haravikk via swift-evolution 
> > wrote:
> 
>> On 7 Sep 2017, at 18:53, Tony Allevato via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>> On Thu, Sep 7, 2017 at 10:39 AM Gwendal Roué > > wrote:
>>> Le 7 sept. 2017 à 14:45, Tony Allevato >> > a écrit :
>>> 
>>> 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.
>> 
>> Yes.
>> 
>>> 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).
>> 
>> Yes, unfortunately.
>> 
>> 
>>> 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.
>> 
>> Yes. I'm not talking about implementation itself. I know this has been the 
>> main topic until I have tried to bring in the topic of the consequences of 
>> non-avoidable synthesis (extra methods that may conflict with userland 
>> methods).
>> 
>> If you ask me for a real-world case, then I think I gave one. Let me 
>> rephrase it:
>> 
>> it's impossible to define a value-backed enum without getting free Equatable 
>> conformance. This free conformance is sometimes unwanted, and I gave the 
>> example of DSLs. Now this problem is not *severe*. It's more a blind spot in 
>> the language, and finally just an unwanted side-effect of a compiler 
>> convenience,
>> 
>> Again, this is not the issue that Haravikk is describing in this thread.
>> 
>> I'll clarify—your issue is specifically with the fact that enums with raw 
>> values and enums without associated values receive Equatable even without 
>> explicitly conforming to it, and therefore users have no way of opting out 
>> of it. This predates SE-0185, and I didn't propose making any changes to the 
>> conformance of those enums for source compatibility reasons, though I 
>> wouldn't be opposed to it because it makes them consistent across the board.
>> 
>> Haravikk's argument is about synthesized conformances like Codable and 
>> Equatable/Hashable in SE-0185, where the user must explicitly conform the 
>> type to those protocols. His claim is that that act of opting in is not 
>> sufficient and that it is still dangerous if those synthesized conformances 
>> can access members that are not also declared in the protocol. That's a 
>> completely separate issue to yours, and one that I hope he'll present more 
>> evidence of. Right now, requiring that you not only explicitly conform to 
>> the protocol but also explicitly request the synthesis feels like a solution 
>> without an actual problem, and is a situation we already have today with 
>> default method implementations.
> 
> The simplest real-world case is easy:
> 
>   struct Foo { var data:String }
>   extension Foo : Equatable {} // This currently produces an error, in 
> future it will not
> 
> 
> Why is this a problem? It's no different than if someone extended Foo to 
> conform to a protocol with a default implementation that was written in code.

I'm sorry but I have now explained why it isn't multiple times; a 
non-reflective default conformance can ONLY act upon methods and properties 
that the protocol itself has defined, meaning that it knows everything it needs 
to know in order to do whatever it wants to do with those methods and 
properties because it defined them.

Reflective/synthesised default implementations must by their very nature make 
assumptions about a concrete type that are not cannot be guaranteed to be 
correct. The properties and methods they may end up interacting with may have 
nothing at all to do with the protocol. Equatable remains by far the simplest 
example; just because a developer has used equatable properties does not 
guarantee that all of them should be compared during a check for equality.

These things are two very different beasts.

While a developer may wish to override a default implementation, it should only 
be to provide 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Xiaodi Wu via swift-evolution
This is a particularly interesting use case that demonstrates a weakness
without a good workaround. I, for one, am glad you brought it up, and agree
with comments above that auto-generated mandatory enum conformance is a
topic perhaps worth revisiting, given this compelling example.
On Thu, Sep 7, 2017 at 14:32 Gwendal Roué via swift-evolution <
swift-evolution@swift.org> wrote:

>
> Le 7 sept. 2017 à 19:53, Tony Allevato  a écrit :
>
> Again, this is not the issue that Haravikk is describing in this thread.
>
>
> Yes, I better understand now. Please forgive the pollution.
>
> Gwendal
>
> ___
> 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


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Gwendal Roué via swift-evolution

> Le 7 sept. 2017 à 19:53, Tony Allevato  a écrit :
> 
> Again, this is not the issue that Haravikk is describing in this thread.

Yes, I better understand now. Please forgive the pollution.

Gwendal

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Tony Allevato via swift-evolution
On Thu, Sep 7, 2017 at 10:39 AM Gwendal Roué  wrote:

> Le 7 sept. 2017 à 14:45, Tony Allevato  a écrit :
>
> 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.
>
>
> Yes.
>
> 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).
>
>
> Yes, unfortunately.
>
>
> 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.
>
>
> Yes. I'm not talking about implementation itself. I know this has been the
> main topic until I have tried to bring in the topic of the consequences of
> non-avoidable synthesis (extra methods that may conflict with userland
> methods).
>
> If you ask me for a real-world case, then I think I gave one. Let me
> rephrase it:
>
> it's impossible to define a value-backed enum without getting free
> Equatable conformance. This free conformance is sometimes unwanted, and I
> gave the example of DSLs. Now this problem is not *severe*. It's more a
> blind spot in the language, and finally just an unwanted side-effect of a
> compiler convenience,
>

Again, this is not the issue that Haravikk is describing in this thread.

I'll clarify—your issue is specifically with the fact that enums with raw
values and enums without associated values receive Equatable even without
explicitly conforming to it, and therefore users have no way of opting out
of it. This predates SE-0185, and I didn't propose making any changes to
the conformance of those enums for source compatibility reasons, though I
wouldn't be opposed to it because it makes them consistent across the board.

Haravikk's argument is about synthesized conformances like Codable and
Equatable/Hashable in SE-0185, where the user must explicitly conform the
type to those protocols. His claim is that that act of opting in is not
sufficient and that it is still dangerous if those synthesized conformances
can access members that are not also declared in the protocol. That's a
completely separate issue to yours, and one that I hope he'll present more
evidence of. Right now, requiring that you not only explicitly conform to
the protocol but also explicitly request the synthesis feels like a
solution without an actual problem, and is a situation we already have
today with default method implementations.


>
> This example gives a little argument, but still an argument, for "explicit
> synthetic behavior", the topic of this thread.
>
> Gwendal Roué
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Itai Ferber via swift-evolution
I think there is a bit of confusion here as to what code synthesis does 
— synthesized conformances (whether `Equatable`, `Hashable`, or 
`Codable`) merely provide default implementations for something which 
_already_ conforms to one of these protocols; they do not _add_ 
conformance to types on your behalf.


```swift
struct X {
let val: Int
}
```

under synthesized `Equatable` does _not_ get an `==` defined for it in 
the same way that it does not get `encode(to:)` or `init(from:)`. Since 
it does not conform to the `Equatable` (or `Codable`) protocol, no 
synthesis happens for it.


As opposed to

```swift
struct Y : Equatable {
let val: Int
}
```

which would get a default implementation for `static func ==(…)`, 
which it would otherwise already have to implement, by definition.


Synthesis does not add methods on your behalf; it only gives 
implementations for methods you’d have to implement, no matter what. I 
don’t know what’s going on in your case, but it’s not caused by 
synthesis — if your type conforms to `Equatable`, either you would 
have to define `==` yourself, or you’d get a free one. You’d see 
ambiguity regardless, since you asked for the type to be `Equatable` (or 
inherited that requirement).


On 7 Sep 2017, at 10:32, Gwendal Roué via swift-evolution wrote:

> Le 7 sept. 2017 à 14:37, Matthew Johnson  a 
écrit :


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.



I'll explain you:

The problem with synthesized Equatable is that it adds an unwanted == 
operator that returns a Bool.


This operator is unwanted because it conflicts with the == operator 
defined by the DSL which does not return a Bool.


// Without synthesised Equatable
let r = (a == b) // the type defined by the DSL

// With synthesised Equatable
let r = (a == b) // ambiguous

This is the same kind of conflict that happen when a function is 
overloaded with two return types:


func f() -> Int { ... }
func f() -> String { ... }
f() // ambiguous

Without the synthesized Equatable, the type would not have any == 
operator that returns a Bool, and thus no conflict with the == 
operator defined by the DSL (the one that returns an SQL expression, 
in our particular context).


I hope that I have explained how synthesized conformance may impact 
code by the mere fact that they define methods. I'm not talking about 
the correctness of the synthesized code. I'm talking about its mere 
existence.


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).


Sure, of course. I'm with you. I'm not talking against code synthesis. 
Again, I'm not talking about the correctness either.


I'm talking about the consequences of implicit and non-avoidable 
synthesis. Exactly the theme of this thread, unless I'm totally 
mistaken.


Gwendal Roué




___
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


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Gwendal Roué via swift-evolution

> Le 7 sept. 2017 à 14:45, Tony Allevato  a écrit :
> 
> 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.

Yes.

> 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).

Yes, unfortunately.

> 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.

Yes. I'm not talking about implementation itself. I know this has been the main 
topic until I have tried to bring in the topic of the consequences of 
non-avoidable synthesis (extra methods that may conflict with userland methods).

If you ask me for a real-world case, then I think I gave one. Let me rephrase 
it:

it's impossible to define a value-backed enum without getting free Equatable 
conformance. This free conformance is sometimes unwanted, and I gave the 
example of DSLs. Now this problem is not *severe*. It's more a blind spot in 
the language, and finally just an unwanted side-effect of a compiler 
convenience,

This example gives a little argument, but still an argument, for "explicit 
synthetic behavior", the topic of this thread.

Gwendal Roué

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Gwendal Roué via swift-evolution

> Le 7 sept. 2017 à 14:37, Matthew Johnson  a écrit :
> 
> 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.


I'll explain you:

The problem with synthesized Equatable is that it adds an unwanted == operator 
that returns a Bool.

This operator is unwanted because it conflicts with the == operator defined by 
the DSL which does not return a Bool.

// Without synthesised Equatable
let r = (a == b) // the type defined by the DSL

// With synthesised Equatable
let r = (a == b) // ambiguous

This is the same kind of conflict that happen when a function is overloaded 
with two return types:

func f() -> Int { ... }
func f() -> String { ... }
f() // ambiguous

Without the synthesized Equatable, the type would not have any == operator that 
returns a Bool, and thus no conflict with the == operator defined by the DSL 
(the one that returns an SQL expression, in our particular context).

I hope that I have explained how synthesized conformance may impact code by the 
mere fact that they define methods. I'm not talking about the correctness of 
the synthesized code. I'm talking about its mere existence.

> 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).  

Sure, of course. I'm with you. I'm not talking against code synthesis. Again, 
I'm not talking about the correctness either.

I'm talking about the consequences of implicit and non-avoidable synthesis. 
Exactly the theme of this thread, unless I'm totally mistaken.

Gwendal Roué

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Sep 7, 2017, at 7:45 AM, Tony Allevato  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 
>>  wrote:
>> 
>> 
>> Sent from my iPad
>> 
>>> On Sep 7, 2017, at 7:07 AM, Gwendal Roué via swift-evolution 
>>>  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 
>  a écrit :
> 
> 
>> On 7 Sep 2017, at 00:11, Brent Royal-Gordon  
>> wrote:
>> 
>> On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
>>  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 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Tony Allevato via swift-evolution
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).

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 
> 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 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Sep 7, 2017, at 7:07 AM, Gwendal Roué via swift-evolution 
>  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 
>>>  a écrit :
>>> 
>>> 
 On 7 Sep 2017, at 00:11, Brent Royal-Gordon  wrote:
 
 On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
  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 
  wrote:
> On Wed, Sep 6, 2017 at 5:42 PM, Haravikk via swift-evolution 
>  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 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Gwendal Roué via swift-evolution
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.

Thanks for reading,
Gwendal Roué
[1] http://github.com/groue/GRDB.swift

> Le 7 sept. 2017 à 12:20, Haravikk via swift-evolution 
>  a écrit :
> 
>> 
>> On 7 Sep 2017, at 00:11, Brent Royal-Gordon > > wrote:
>> 
>>> On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
>>> > 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 
>> > 
>> wrote:
>>> On Wed, Sep 6, 2017 at 5:42 PM, Haravikk via swift-evolution 
>>> > 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 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-07 Thread Haravikk via swift-evolution

> On 7 Sep 2017, at 00:11, Brent Royal-Gordon  wrote:
> 
>> On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
>> > 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 
>  wrote:
>> On Wed, Sep 6, 2017 at 5:42 PM, Haravikk via swift-evolution 
>> > 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  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.

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-06 Thread Andrew Thompson via swift-evolution
>> On Sep 6, 2017, at 1:32 AM, Haravikk via swift-evolution 
>>  wrote:
>>
>> As a general rule I would argue that Mirrors should almost never be used for 
>> any purpose, except perhaps debugging; in production code they can lead to 
>> subtle and misleading problems, not to mention any performance impacts. Even 
>> for things like serialising types, it is not a desirable way to do it, and 
>> should only be used as a last resort because of missing features in Swift.
>
> I'm just going to toss in that you and I apparently have diametrically 
> opposed needs and belief systems about what makes for a good programming 
> language.  I believe the exact opposite.
>
> After 20+ years of Cocoa development, I rely on these features heavily and 
> consider any language that lacks them to be more or less "dead" where I 
> consider languages that have them to be "self aware" and "lively".
>
> For instance, I think relying on the compiler to generate special code to 
> implement Codable rather than just exposing the meta facilities required to 
> do introspection is taking the long way around rather than the short cut.
>
> So add my vote for powerful reflection capabilities.

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 )


Regards,
Andrew Thompson

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-06 Thread Nevin Brackett-Rozinsky via swift-evolution
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.

If you wanted some other dough or sauce or cheese or toppings you would
have ordered it. And the fact is you *did* order a veggie pizza (ie.
conformed to a certain protocol). It’s not like they brought you something
you didn’t order. You ordered what you wanted, and that’s what they brought
you.

And for those times when you *do* want to customize your order, that is
perfectly fine too.

Nevin
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-06 Thread Haravikk via swift-evolution

> On 6 Sep 2017, at 16:26, Eagle Offshore  wrote:
>> On Sep 6, 2017, at 1:32 AM, Haravikk via swift-evolution 
>>  wrote:
>> As a general rule I would argue that Mirrors should almost never be used for 
>> any purpose, except perhaps debugging; in production code they can lead to 
>> subtle and misleading problems, not to mention any performance impacts. Even 
>> for things like serialising types, it is not a desirable way to do it, and 
>> should only be used as a last resort because of missing features in Swift.
> 
> I'm just going to toss in that you and I apparently have diametrically 
> opposed needs and belief systems about what makes for a good programming 
> language.  I believe the exact opposite.
> 
> After 20+ years of Cocoa development, I rely on these features heavily and 
> consider any language that lacks them to be more or less "dead" where I 
> consider languages that have them to be "self aware" and "lively".
> 
> For instance, I think relying on the compiler to generate special code to 
> implement Codable rather than just exposing the meta facilities required to 
> do introspection is taking the long way around rather than the short cut.
> 
> So add my vote for powerful reflection capabilities.  

Sorry I think my remark was unclear; my comment there was specifically about 
the use of run-time reflection, which I believe usually indicates a failure of 
a language to provide other, more appropriate features (like Codable in fact). 
I'm not against the features where they make sense and are implemented in well, 
I was just pointing out that the use of run-time reflection in code is usually 
a sign of a last resort.

That's not really important though; 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.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-06 Thread Eagle Offshore via swift-evolution


> On Sep 6, 2017, at 1:32 AM, Haravikk via swift-evolution 
>  wrote:
> 
> As a general rule I would argue that Mirrors should almost never be used for 
> any purpose, except perhaps debugging; in production code they can lead to 
> subtle and misleading problems, not to mention any performance impacts. Even 
> for things like serialising types, it is not a desirable way to do it, and 
> should only be used as a last resort because of missing features in Swift.


I'm just going to toss in that you and I apparently have diametrically opposed 
needs and belief systems about what makes for a good programming language.  I 
believe the exact opposite.

After 20+ years of Cocoa development, I rely on these features heavily and 
consider any language that lacks them to be more or less "dead" where I 
consider languages that have them to be "self aware" and "lively".

For instance, I think relying on the compiler to generate special code to 
implement Codable rather than just exposing the meta facilities required to do 
introspection is taking the long way around rather than the short cut.

So add my vote for powerful reflection capabilities.  
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-06 Thread Haravikk via swift-evolution

> On 6 Sep 2017, at 01:36, Robert Bennett  wrote:
> 
> I take issue with the fact that this problem is no different from 
> accidentally gaining the default inheritance of *any* member required by a 
> protocol and implemented in an extension of that protocol. The fact that in 
> this case conformance is synthesized by the compiler instead of written in 
> source code somewhere is immaterial; in principle, nothing is (was?) stopping 
> the same default implementation from being implemented with a Mirror instead 
> of the current approach.

This is why I'm proposing that Mirrors of `self` should likewise require the 
new attribute; while I realise it may be possible to sneak self-reflection in 
somehow regardless by tricking the compiler, this should at least pick up the 
most obvious cases. A more complete solution could possibly just consider all 
use of reflection to be synthetic, requiring methods callable from protocol 
extensions (global functions, static methods etc.) to use the attribute as 
well, so that the compiler can detect any function call with `self` that could 
potentially result in reflective behaviour.

The issue here isn't that there might be other ways to do it (these can be 
addressed), it's that all methods of doing this should require developers to 
explicitly opt-in, otherwise it leads to potential bugs and/or unwanted 
behaviour. It's also IMO a gross overreach for protocols to begin with, and 
sets a dangerous precedent for a language that's supposed to be about safety 
and prevention of bugs, especially when in the case of Equatable and Hashable 
it will actually hide bugs that are currently caught.

As a general rule I would argue that Mirrors should almost never be used for 
any purpose, except perhaps debugging; in production code they can lead to 
subtle and misleading problems, not to mention any performance impacts. Even 
for things like serialising types, it is not a desirable way to do it, and 
should only be used as a last resort because of missing features in Swift.

> I still think that the role keyword proposal is the best solution to this 
> problem proposed so far. 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170612/037484.html
>  
> 
While I support the idea of these role keywords, they don't solve all of the 
same problems. Consider for example a missing protocol requirement; currently 
it is caught if a protocol cannot offer a default implementation for it, 
however, in the presence of synthetic behaviour it is possible that the 
requirement is met, but by a method that will not work as desired.

The main issue here is that we're talking about methods that appear like 
default implementations, but go well beyond what the protocol itself defines; 
when you start delving into concrete types from within a protocol you are 
making assumptions about that concrete type that simply cannot be guaranteed. 
Any mistake or omission by a developer could lead to behaviour they do not 
want, and that may not be easy to debug, and in the case of Equatable and 
Hashable is a potential bug that is currently impossible.

>> On Sep 5, 2017, at 4:02 PM, Haravikk via swift-evolution 
>> > wrote:
>> Some of you will have seen my impassioned pleas on the synthesised 
>> Equatable/Hashable thread against implementing implicit synthesised 
>> behaviour on protocols that must, by necessity, make assumptions about a 
>> concrete type that could be incorrect.
>> 
>> For those that haven't, the concept of synthetic behaviour in discussion 
>> here is essentially any kind of default behaviour for a protocol that is 
>> automatically generated based upon the concrete type itself (rather than 
>> just what the protocol defines). Currently this refers to compiler magic as 
>> proposed for Codable, Equatable and Hashable, but also includes the 
>> reflection API and any future native macro support for Swift. Using any of 
>> these to implement default methods for protocols should IMO be made explicit 
>> to developers using any such protocol so that they can specifically opt-in 
>> to the behaviour only if they want to and understand what it does.
>> 
>> 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). If a default method does not have this attribute, then the 
>> compiler will produce an error with the appropriate fix-it. For convenience 
>> this attribute can be applied to any extension block or even a protocol 
>> definition in order to mark all 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-06 Thread Haravikk via swift-evolution

> On 6 Sep 2017, at 01:36, Robert Bennett  > wrote:
> 
> I take issue with the fact that this problem is no different from 
> accidentally gaining the default inheritance of *any* member required by a 
> protocol and implemented in an extension of that protocol. The fact that in 
> this case conformance is synthesized by the compiler instead of written in 
> source code somewhere is immaterial; in principle, nothing is (was?) stopping 
> the same default implementation from being implemented with a Mirror instead 
> of the current approach.

This is why I'm proposing that Mirrors of `self` should likewise require the 
new attribute; while I realise it may be possible to sneak self-reflection in 
somehow regardless by tricking the compiler, this should at least pick up the 
most obvious cases. A more complete solution could possibly just consider all 
use of reflection to be synthetic, requiring methods callable from protocol 
extensions (global functions, static methods etc.) to use the attribute as 
well, so that the compiler can detect any function call with `self` that could 
potentially result in reflective behaviour.

The issue here isn't that there might be other ways to do it (these can be 
addressed), it's that all methods of doing this should require developers to 
explicitly opt-in, otherwise it leads to potential bugs and/or unwanted 
behaviour. It's also IMO a gross overreach for protocols to begin with, and 
sets a dangerous precedent for a language that's supposed to be about safety 
and prevention of bugs, especially when in the case of Equatable and Hashable 
it will actually hide bugs that are currently caught.

As a general rule I would argue that Mirrors should almost never be used for 
any purpose, except perhaps debugging; in production code they can lead to 
subtle and misleading problems, not to mention any performance impacts. Even 
for things like serialising types, it is not a desirable way to do it, and 
should only be used as a last resort because of missing features in Swift.

> I still think that the role keyword proposal is the best solution to this 
> problem proposed so far. 
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170612/037484.html
>  
> 
While I support the idea of these role keywords, they don't solve all of the 
same problems. Consider for example a missing protocol requirement; currently 
it is caught if a protocol cannot offer a default implementation for it, 
however, in the presence of synthetic behaviour it is possible that the 
requirement is met, but by a method that will not work as desired.

The main issue here is that we're talking about methods that appear like 
default implementations, but go well beyond what the protocol itself defines; 
when you start delving into concrete types from within a protocol you are 
making assumptions about that concrete type that simply cannot be guaranteed. 
Any mistake or omission by a developer could lead to behaviour they do not 
want, and that may not be easy to debug, and in the case of Equatable and 
Hashable is a potential bug that is currently impossible.

>> On Sep 5, 2017, at 4:02 PM, Haravikk via swift-evolution 
>> > wrote:
>> Some of you will have seen my impassioned pleas on the synthesised 
>> Equatable/Hashable thread against implementing implicit synthesised 
>> behaviour on protocols that must, by necessity, make assumptions about a 
>> concrete type that could be incorrect.
>> 
>> For those that haven't, the concept of synthetic behaviour in discussion 
>> here is essentially any kind of default behaviour for a protocol that is 
>> automatically generated based upon the concrete type itself (rather than 
>> just what the protocol defines). Currently this refers to compiler magic as 
>> proposed for Codable, Equatable and Hashable, but also includes the 
>> reflection API and any future native macro support for Swift. Using any of 
>> these to implement default methods for protocols should IMO be made explicit 
>> to developers using any such protocol so that they can specifically opt-in 
>> to the behaviour only if they want to and understand what it does.
>> 
>> 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). If a default method does not have this attribute, then the 
>> compiler will produce an error with the appropriate fix-it. For convenience 
>> this attribute can be applied to any extension block or even a protocol 
>> 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-06 Thread Ben Rimmington via swift-evolution

> On 5 Sep 2017, at 21:02, Haravikk wrote:
> 
> Anyway, this is basically just a rough dump of the ideas for how the 
> synthesised Codable, Equatable and Hashable behaviours (and anything else 
> anyone can think of) should be changed before Swift 4 is released.

Swift 4, Xcode 9 and iOS 11 will **probably** be released on September 12:



All previous major versions have also been released in mid-September:



There isn't enough time to propose, review and implement @synthetic (AFAIK).

-- Ben

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-05 Thread Robert Bennett via swift-evolution
I take issue with the fact that this problem is no different from accidentally 
gaining the default inheritance of *any* member required by a protocol and 
implemented in an extension of that protocol. The fact that in this case 
conformance is synthesized by the compiler instead of written in source code 
somewhere is immaterial; in principle, nothing is (was?) stopping the same 
default implementation from being implemented with a Mirror instead of the 
current approach.

I still think that the role keyword proposal is the best solution to this 
problem proposed so far. 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170612/037484.html

> On Sep 5, 2017, at 4:02 PM, Haravikk via swift-evolution 
>  wrote:
> 
> Some of you will have seen my impassioned pleas on the synthesised 
> Equatable/Hashable thread against implementing implicit synthesised behaviour 
> on protocols that must, by necessity, make assumptions about a concrete type 
> that could be incorrect.
> 
> For those that haven't, the concept of synthetic behaviour in discussion here 
> is essentially any kind of default behaviour for a protocol that is 
> automatically generated based upon the concrete type itself (rather than just 
> what the protocol defines). Currently this refers to compiler magic as 
> proposed for Codable, Equatable and Hashable, but also includes the 
> reflection API and any future native macro support for Swift. Using any of 
> these to implement default methods for protocols should IMO be made explicit 
> to developers using any such protocol so that they can specifically opt-in to 
> the behaviour only if they want to and understand what it does.
> 
> 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). If a default method does not have this attribute, then the 
> compiler will produce an error with the appropriate fix-it. For convenience 
> this attribute can be applied to any extension block or even a protocol 
> definition in order to mark all methods in that block/type as synthetic, 
> though it's worth noting that doing so will prevent these default 
> implementations from being provided if they don't actually need this 
> attribute.
> 
> Basically the intention is that any protocol default implementation that 
> requires more knowledge about the concrete type than merely what the protocol 
> (and its parents) provide direct access to, must be marked as synthetic.
> 
> To use the synthetic behaviour of a protocol, developers must then use the 
> @synthetic keyword when conforming to it, explicitly indicating that they 
> want the extra behaviours rather than implementing the method(s) for 
> themselves. To ignore the synthetic behaviour (and thus require some kind of 
> manual implementation of methods as normal), simply omit the keyword:
> 
>   struct Foo : @synthetic Equatable { var someData:String }
>   // Type fully conforms to Equatable using synthetic behaviour 
> (equatable properties must be equal)
>   struct Foo : Equatable { var someData:String }
>   // Error due to unimplemented methods, but offers @synthetic as 
> a fix-it if all unimplemented methods are @synthetic
> 
> It is possible that the attribute could be expanded to have parameters, 
> allowing for synthetic conformance only on specific methods, but I'm unsure 
> if that'd be the best way to do it, or how likely that is to be needed.
> 
> With this kind of explicit declaration it becomes obvious within code when a 
> developer is specifically choosing to benefit from synthetic behaviour; this 
> hopefully makes it more likely that a developer will fully consider what the 
> implications of this may be, rather than doing it accidentally. The idea in 
> part is to distinguish such types as having separate protocol and synthesised 
> behaviour, where conformance without the @synthetic attribute specifically 
> requires that all protocol requirements be met in full, and that any default 
> behaviour is implemented only on the basis of the protocol itself, while 
> adding @synthetic identifies that more invasive automated behaviour is 
> permitted/requested.
> 
> At this stage I don't think there should be much of an impact for existing 
> code; as far as I can tell it should only affect any protocols that happen to 
> be using Mirror(reflecting: self) for some reason within a default 
> implementation, which I can't imagine represents a huge subsection of 
> existing code, and the fix is the simple addition of an attribute.
> 
> 
> Anyway, this is basically just a rough dump of the ideas for how the 
> synthesised Codable, 

[swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-05 Thread Haravikk via swift-evolution
Some of you will have seen my impassioned pleas on the synthesised 
Equatable/Hashable thread against implementing implicit synthesised behaviour 
on protocols that must, by necessity, make assumptions about a concrete type 
that could be incorrect.

For those that haven't, the concept of synthetic behaviour in discussion here 
is essentially any kind of default behaviour for a protocol that is 
automatically generated based upon the concrete type itself (rather than just 
what the protocol defines). Currently this refers to compiler magic as proposed 
for Codable, Equatable and Hashable, but also includes the reflection API and 
any future native macro support for Swift. Using any of these to implement 
default methods for protocols should IMO be made explicit to developers using 
any such protocol so that they can specifically opt-in to the behaviour only if 
they want to and understand what it does.

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). If a default method does not have this attribute, then the 
compiler will produce an error with the appropriate fix-it. For convenience 
this attribute can be applied to any extension block or even a protocol 
definition in order to mark all methods in that block/type as synthetic, though 
it's worth noting that doing so will prevent these default implementations from 
being provided if they don't actually need this attribute.

Basically the intention is that any protocol default implementation that 
requires more knowledge about the concrete type than merely what the protocol 
(and its parents) provide direct access to, must be marked as synthetic.

To use the synthetic behaviour of a protocol, developers must then use the 
@synthetic keyword when conforming to it, explicitly indicating that they want 
the extra behaviours rather than implementing the method(s) for themselves. To 
ignore the synthetic behaviour (and thus require some kind of manual 
implementation of methods as normal), simply omit the keyword:

struct Foo : @synthetic Equatable { var someData:String }
// Type fully conforms to Equatable using synthetic behaviour 
(equatable properties must be equal)
struct Foo : Equatable { var someData:String }
// Error due to unimplemented methods, but offers @synthetic as 
a fix-it if all unimplemented methods are @synthetic

It is possible that the attribute could be expanded to have parameters, 
allowing for synthetic conformance only on specific methods, but I'm unsure if 
that'd be the best way to do it, or how likely that is to be needed.

With this kind of explicit declaration it becomes obvious within code when a 
developer is specifically choosing to benefit from synthetic behaviour; this 
hopefully makes it more likely that a developer will fully consider what the 
implications of this may be, rather than doing it accidentally. The idea in 
part is to distinguish such types as having separate protocol and synthesised 
behaviour, where conformance without the @synthetic attribute specifically 
requires that all protocol requirements be met in full, and that any default 
behaviour is implemented only on the basis of the protocol itself, while adding 
@synthetic identifies that more invasive automated behaviour is 
permitted/requested.

At this stage I don't think there should be much of an impact for existing 
code; as far as I can tell it should only affect any protocols that happen to 
be using Mirror(reflecting: self) for some reason within a default 
implementation, which I can't imagine represents a huge subsection of existing 
code, and the fix is the simple addition of an attribute.


Anyway, this is basically just a rough dump of the ideas for how the 
synthesised Codable, Equatable and Hashable behaviours (and anything else 
anyone can think of) should be changed before Swift 4 is released. I'm hoping 
for feedback before I make a formal proposal as I don't have a lot of time at 
the moment, so am looking to do the more structured document once stuff has 
been hammered out a bit.

- Haravikk___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution