Re: [swift-evolution] Enums and Source Compatibility

2017-09-06 Thread Rod Brown via swift-evolution


> On 7 Sep 2017, at 2:33 pm, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
>> On Sep 5, 2017, at 5:19 PM, Jordan Rose via swift-evolution 
>> > wrote:
>> 
>> I've taken everyone's feedback into consideration and written this up as a 
>> proposal: 
>> https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md
>>  
>> .
>>  The next step is working on an implementation, but if people have further 
>> pre-review comments I'd be happy to hear them.
> 
> Hi Jordan,
> 
> I apologize in advance that I haven’t followed the back and forth on this 
> thread, so I’m sorry if these thoughts are duplicative:
> 
> I really would prefer to avoid introducing the notion of 
> exhaustive/nonexhaustive enums into Swift, and would much prefer that such a 
> thing be limited to C (which can’t express this concept already).
> 
> We’ve talked about enums many times across years, and it seems like the 
> appropriate model follows the generally understood resilience model.  
> Specifically, there should be three different kinds of enums, and the kind 
> should affect users outside their module in different ways:
> 
> 1. private/fileprivate/internal enum: cases can be added freely.  All clients 
> are in the same module, so the enum is implicitly fragile, and all switches 
> within the current module may therefore be exhaustive.
> 
> 2. public enum (i.e., one that isn’t marked fragile): cases may be added 
> freely.  Within the module that defines the enum, switches may be exhaustive. 
>  However, because the enum is public and non-fragile, clients outside the 
> current module must be prepared for the enum to add additional cases in 
> future revisions of the API, and therefore they cannot exhaustively match the 
> cases of the enum.
> 
> 3. fragile public enum: cases may not be added, because that would break the 
> fragility guarantee.  As such, clients within or outside of hte current 
> module may exhaustively match against the enum.
> 
> 
> This approach gives a very natural user model: app developers don’t have to 
> care about enum resilience until they mark an enum as public, and even then 
> they only have to care about it when/if they mark an enum as public.  This 
> also builds on the notion of fragility - something we need for other nominal 
> types like structs and classes - so it doesn’t introduce new language 
> complexity.  Also such an approach is entirely source compatible with Swift 
> 3/4, which require defaults (this isn’t an accident, it follows from the 
> anticipated design).
> 
> This approach doesn’t address the problem of what to do with C though, 
> because C doesn’t have a reasonable notion of “extensible” vs “nonextensible” 
> enum.  As such, we definitely do need an attribute (or something) to add to 
> Clang.  I think that your proposal for defaulting to “extensible” and using 
> __attribute__((enum_extensibility(closed))) override this is perfectly 
> sensible.
> 
> -Chris
> 

Hi Chris,

I think I agree with you in general, with 1 exception:

I think the wording “fragile”, while technically correct, implies the exact 
opposite of the promise contract, namely that it will not change between 
releases of your framework. Perhaps a term like “concrete” would be more 
appropriate? It would be fragile in that it is a fragile interface, but it 
would be concrete as a promise to external dependencies. If you are 
exhaustively enumerating, you’re basing it on the notion that it won’t change, 
not that it’s "easy to break” (which fragile as a word would seem to imply).

- Rod


> 
> 
> ___
> 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] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Taylor Swift via swift-evolution
okay so I think so far what’s been agreed on is

*1*. rename “Bytes” to “Memory” in the raw pointer API. Note: this brings
the `copyBytes(from:)` collection method into the scope of this proposal

*2*. change raw offsets to be in terms of bytes, not typed strides. This
argument will be called `atByteOffset:` and will only appear in
UnsafeMutableRawBufferPointer. “at:” arguments are no longer needed in
UnsafeMutableRawPointer, since we can just use pointer arithmetic now.


*3*. move UnsafeMutableBufferPointer’s `at:` arguments to the front of the
parameter list. mostly cause any pointer arithmetic happens in the front so
structurally we want to mirror that.

*4*. add dual (to:) single element initializers and assigners to
UnsafeMutablePointer, but not UnsafeMutableRawPointer because it’s
apparently not useful there.
`UnsafeMutableRawPointer.initializeMemory(as:repeating:count:)` still
loses its default count to prevent confusion with its buffer variant.

*5*. memory deallocation on buffer pointers is clearly documented to only
be defined behavior when the buffer matches a whole heap block.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Concurrency] async/await + actors

2017-09-06 Thread David Hart via swift-evolution


> On 7 Sep 2017, at 07:05, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
>> On Sep 5, 2017, at 7:31 PM, Eagle Offshore via swift-evolution 
>>  wrote:
>> 
>> OK, I've been watching this thing for a couple weeks.
>> 
>> I've done a lot of GCD network code.  Invariably my completion method starts 
>> with
>> 
>> dispatch_async(queue_want_to_handle_this_on,)
>> 
>> Replying on the same queue would be nice I guess, only often all I need to 
>> do is update the UI in the completion code.
>> 
>> OTOH, I have situations where the reply is complicated and I need to persist 
>> a lot of data, then update the UI.
>> 
>> So honestly, any assumption you make about how this is supposed to work is 
>> going to be wrong about half the time unless
>> 
>> you let me specify the reply queue directly.
>> 
>> That is the only thing that works all the time.  Even then, I'm very apt to 
>> make the choice to do some of the work off the main thread and then queue up 
>> the minimal amount of work onto the main thread.
> 
> I (think that I) understand what you’re saying here, but I don’t think that 
> we’re talking about the same thing.  
> 
> You seem to be making an argument about what is most *useful* (being able to 
> vector a completion handler to a specific queue), but I’m personally 
> concerned about what is most *surprising* and therefore unnatural and prone 
> to introduce bugs and misunderstandings by people who haven’t written the 
> code.  To make this more concrete, shift from the “person who writes to code” 
> to the “person who has to maintain someone else's code”:
> 
> Imagine you are maintaining a large codebase, and you come across this 
> (intentionally abstract) code:
> 
>foo()
>await bar()
>baz()
> 
> Regardless of what is the most useful, I’d argue that it is only natural to 
> expect baz() to run on the same queue/thread/execution-context as foo and 
> bar.  If, in the same model, you see something like:
> 
>foo()
>await bar()
>anotherQueue.async {
>baz()
>}

Couldn’t it end up being:

foo()
await bar()
await anotherQueue.async()
// on another queue

> Then it is super clear what is going on: an intentional queue hop from 
> whatever foo/bar are run on to anotherQueue.
> 
> I interpret your email as arguing for something like this:
> 
>foo()
>await(anotherQueue) bar()
>baz()
> 
> I’m not sure if that’s exactly the syntax you’re arguing for, but anything 
> like this presents a number of challenges:
> 
> 1) it is “just sugar” over the basic model, so we could argue to add it at 
> any time (and would argue strongly to defer it out of this round of 
> discussions).
> 
> 2) We’d have to find a syntax that implies that baz() runs on anotherQueue, 
> but bar() runs on the existing queue.  The syntax I sketched above does NOT 
> provide this indication.
> 
> -Chris
> 
> 
> ___
> 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] Enums and Source Compatibility

2017-09-06 Thread Chris Lattner via swift-evolution

> On Sep 5, 2017, at 5:19 PM, Jordan Rose via swift-evolution 
>  wrote:
> 
> I've taken everyone's feedback into consideration and written this up as a 
> proposal: 
> https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md
>  
> .
>  The next step is working on an implementation, but if people have further 
> pre-review comments I'd be happy to hear them.

Hi Jordan,

I apologize in advance that I haven’t followed the back and forth on this 
thread, so I’m sorry if these thoughts are duplicative:

I really would prefer to avoid introducing the notion of 
exhaustive/nonexhaustive enums into Swift, and would much prefer that such a 
thing be limited to C (which can’t express this concept already).

We’ve talked about enums many times across years, and it seems like the 
appropriate model follows the generally understood resilience model.  
Specifically, there should be three different kinds of enums, and the kind 
should affect users outside their module in different ways:

1. private/fileprivate/internal enum: cases can be added freely.  All clients 
are in the same module, so the enum is implicitly fragile, and all switches 
within the current module may therefore be exhaustive.

2. public enum (i.e., one that isn’t marked fragile): cases may be added 
freely.  Within the module that defines the enum, switches may be exhaustive.  
However, because the enum is public and non-fragile, clients outside the 
current module must be prepared for the enum to add additional cases in future 
revisions of the API, and therefore they cannot exhaustively match the cases of 
the enum.

3. fragile public enum: cases may not be added, because that would break the 
fragility guarantee.  As such, clients within or outside of hte current module 
may exhaustively match against the enum.


This approach gives a very natural user model: app developers don’t have to 
care about enum resilience until they mark an enum as public, and even then 
they only have to care about it when/if they mark an enum as public.  This also 
builds on the notion of fragility - something we need for other nominal types 
like structs and classes - so it doesn’t introduce new language complexity.  
Also such an approach is entirely source compatible with Swift 3/4, which 
require defaults (this isn’t an accident, it follows from the anticipated 
design).

This approach doesn’t address the problem of what to do with C though, because 
C doesn’t have a reasonable notion of “extensible” vs “nonextensible” enum.  As 
such, we definitely do need an attribute (or something) to add to Clang.  I 
think that your proposal for defaulting to “extensible” and using 
__attribute__((enum_extensibility(closed))) override this is perfectly sensible.

-Chris




___
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 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] Enums and Source Compatibility

2017-09-06 Thread Rod Brown via swift-evolution
Hi Brent,

Thanks for the analysis of the issues here. I think you’re right that there are 
two major types of enums, and that there are a set developers tend to switch on 
that are usually fixed, where additional cases won’t make sense.

I think there are several issues that I see with these different ideas, and 
they stem back to a similar source:

1. They are overly complex solutions to a specific problem: inter-library 
variable enums. We would be destroying some of the awesome simplicity and 
design characteristics of enums in Swift to deal with an outlying problem.

2. Project enums should always be exhaustive. Your design introduces 
‘exhaustive’ and has an end goal of removing ‘@nonexhaustive’ but the fact is 
that keyword should be the default internal of a project. It seems an odd 
trajectory change to make purely for public enums.

It would seem much simpler to have a word that denotes that an enum is not 
considered ‘exhaustive’ in public code, or to force users to annotate their 
intention of exhaustive vs extensible when they make their enum public, and 
have intra-project enums remain exhaustive. This then requires a simple 
addition of a default argument to handle outlier cases you may encounter. Your 
solutions seem to me to require a large to deal with a relatively narrow use 
case, radically changing the enum system.

I agree that we could include something as part of @testable to add an 
additional case to test the edge case. We do have specific language elements 
for testing, why not here?

- Rod


> On 6 Sep 2017, at 10:53 pm, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Sep 5, 2017, at 5:19 PM, Jordan Rose via swift-evolution 
>> > wrote:
>> 
>> I've taken everyone's feedback into consideration and written this up as a 
>> proposal: 
>> https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md
>>  
>> .
>>  The next step is working on an implementation, but if people have further 
>> pre-review comments I'd be happy to hear them.
> 
> I disagree with the choice of `exhaustive` and `nonexhaustive`. They are too 
> long; the more resilient keyword is longer than the more fragile one (and 
> difficult to read!); and they don't match the clang annotation. We may have 
> to compromise on one or two of these, but the combination of all three ought 
> to be considered disqualifying.
> 
> I think `final`/`nonfinal`, `total`/`partial`, `fixed`/? or `permanent`/? are 
> all better because they're shorter, although they all have problems with 
> their antonyms. `candid`/`coy` or `candid`/`shy` produce the right soft 
> default, but are kind of weirdly figurative.
> 
> But I don't think a change of keywords will fix everything here. 
> Fundamentally, I am not convinced that source compatibility of `switch` 
> statements should be weighed so heavily. Based on your survey of Foundation, 
> you suggest that the vast majority of imported enums should source-break all 
> switches in Swift 5. Why is that acceptable, but making Swift enums 
> source-breaking unacceptable?
> 
> I suspect that, in practice, `public` enums tend to fall into two categories:
> 
>   1. "Data enums" which represent important data that happens to consist 
> of a set of alternatives. Outside users will frequently need to switch over 
> these, but they are not very likely to evolve or have private cases.
> 
>   2. "Mode enums" which tweak the behavior of an API. These are very 
> likely to evolve or have private cases, but outside users are not very likely 
> to need to switch over them.
> 
> An example of a data enum would be, as you mentioned, `NSComparisonResult`. 
> People really *do* need to be able to test against it, but barring some 
> fundamental break in the nature of reality, it will only ever have those 
> three cases. So it's fine to make it exhaustive.
> 
> An example of a mode enum would be `UIViewAnimationCurve`, which tells UIKit 
> how to ease an animation. I chose that example because I actually traced a 
> bug just last week to my mistaken impression that this enum had no private 
> cases. I was mapping values of this type to their corresponding 
> `UIViewAnimationOptions` values; because there were private cases, this was 
> Objective-C code, and I didn't include sufficiently aggressive assertions, I 
> ended up reading garbage data from memory. But while debugging this, it 
> struck me that this was actually *really weird* code. How often do you, as a 
> developer outside UIKit, need to interpret the value of a type like 
> `UIViewAnimationCurve`? If the compiler suddenly changed the exhaustiveness 
> behavior of `UIViewAnimationCurve`, probably less than 1% of apps would even 
> notice—and the affected code would probably have latent 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Andrew Trick via swift-evolution

> On Sep 6, 2017, at 5:17 PM, Taylor Swift  wrote:
> 
> 
> 
> On Sep 6, 2017, at 7:01 PM, Andrew Trick  > wrote:
> 
>> 
>>> On Sep 6, 2017, at 4:54 PM, Taylor Swift >> > wrote:
>>> 
 The semantics of buffer.deallocate() needs to be: free `buffer.count` 
 bytes of memory at `buffer.baseAddress`. So, that will always be the fast 
 path!
 Kelvin, do you agree with that?
>>> 
>>> this could be problematic if you have multiple contiguous buffers carved 
>>> out of the same heap block. i agree that this is the best semantics for 
>>> buffer pointers but we need the sized backend in Swift before this is 
>>> possible else we will end up in the same boat we’re in right now with 
>>> `deallocate(capacity:)` where we would have to make buffer deallocate heap 
>>> block-based for now and then pull the rug out from underneath users later 
>>> in order to switch to the improved semantics
>> 
>> If I understand your proposal, it’s only valid to deallocate a buffer that 
>> was allocated with the same capacity. Anything else should assert.
>> -Andy
> 
> the proposal isn’t specific enough there and that’s my fault but this seems 
> like a good solution. in the future if we get a sized backend we can loosen 
> the assertions and make the partial heap block buffer case defined behavior.

The important thing is that the UnsafeBufferPointer API is clearly documented. 
We do not want users to think it’s ok to deallocate a smaller buffer than they 
allocated.

Unfortunately, there’s actually no way to assert this in the runtime because 
malloc_size could be larger than the allocated capacity. Incorrect code could 
happen to work and we can live with that.

This is really the same issue that we punted on earlier… there’s no way to 
indicate that a buffer owns its memory. So we need to rely on clear 
documentation and discourage buffer “rebasing”.

In the future, a safe buffer will always own its memory and buffer slices will 
refer back to it. 

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Taylor Swift via swift-evolution


> On Sep 6, 2017, at 7:01 PM, Andrew Trick  wrote:
> 
> 
>>> On Sep 6, 2017, at 4:54 PM, Taylor Swift  wrote:
>>> 
>>> The semantics of buffer.deallocate() needs to be: free `buffer.count` bytes 
>>> of memory at `buffer.baseAddress`. So, that will always be the fast path!
>>> Kelvin, do you agree with that?
>> 
>> this could be problematic if you have multiple contiguous buffers carved out 
>> of the same heap block. i agree that this is the best semantics for buffer 
>> pointers but we need the sized backend in Swift before this is possible else 
>> we will end up in the same boat we’re in right now with 
>> `deallocate(capacity:)` where we would have to make buffer deallocate heap 
>> block-based for now and then pull the rug out from underneath users later in 
>> order to switch to the improved semantics
> 
> If I understand your proposal, it’s only valid to deallocate a buffer that 
> was allocated with the same capacity. Anything else should assert.
> -Andy

the proposal isn’t specific enough there and that’s my fault but this seems 
like a good solution. in the future if we get a sized backend we can loosen the 
assertions and make the partial heap block buffer case defined behavior.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Taylor Swift via swift-evolution


> On Sep 6, 2017, at 6:56 PM, Andrew Trick  wrote:
> 
> 
>>> On Sep 6, 2017, at 4:46 PM, Taylor Swift  wrote:
>>> 
>>> A sized implementation may fail more obviously when you violate the 
>>> contract in the future. Not having sized deallocation is a known deficiency 
>>> of the C model we've been fairly diligent about avoiding in Swift's 
>>> allocation interfaces, and it would be extremely unfortunate for us to 
>>> backpedal from it.
>>> 
>>> -Joe
>> 
>> Which is worse, an active gaping hole in Swift’s memory system, or 
>> potentially discouraging users from using a hypothetical future allocation 
>> API? 
>> 
>> Making sure the existing allocation API is working properly is a 
>> prerequisite to introducing a future more advanced allocation API.
> 
> I think we agree that the runtime should assert when it is passed an invalid 
> deallocation size. The problem you’re describing could still occur with the 
> UnsafeBufferPointer.deallocate() method if the user happened to slice and 
> rebase the buffer.
> 
> -Andy 

the proposal specifically defines UnsafeMutableBufferPointer.deallocate() 
behavior in terms of calling deallocate() on its baseAddress if non-nil. this 
operation doesn’t have any relation to the length of the buffer itself. that 
being said, it *should*, and i’d be down for redefining it in terms of 
deallocating self.count elements, if this was technically possible but it’s not___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Andrew Trick via swift-evolution

> On Sep 6, 2017, at 4:54 PM, Taylor Swift  wrote:
> 
>> The semantics of buffer.deallocate() needs to be: free `buffer.count` bytes 
>> of memory at `buffer.baseAddress`. So, that will always be the fast path!
>> Kelvin, do you agree with that?
> 
> this could be problematic if you have multiple contiguous buffers carved out 
> of the same heap block. i agree that this is the best semantics for buffer 
> pointers but we need the sized backend in Swift before this is possible else 
> we will end up in the same boat we’re in right now with 
> `deallocate(capacity:)` where we would have to make buffer deallocate heap 
> block-based for now and then pull the rug out from underneath users later in 
> order to switch to the improved semantics

If I understand your proposal, it’s only valid to deallocate a buffer that was 
allocated with the same capacity. Anything else should assert.
-Andy___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Andrew Trick via swift-evolution

> On Sep 6, 2017, at 4:46 PM, Taylor Swift  wrote:
> 
>> A sized implementation may fail more obviously when you violate the contract 
>> in the future. Not having sized deallocation is a known deficiency of the C 
>> model we've been fairly diligent about avoiding in Swift's allocation 
>> interfaces, and it would be extremely unfortunate for us to backpedal from 
>> it.
>> 
>> -Joe
> 
> Which is worse, an active gaping hole in Swift’s memory system, or 
> potentially discouraging users from using a hypothetical future allocation 
> API? 
> 
> Making sure the existing allocation API is working properly is a prerequisite 
> to introducing a future more advanced allocation API.

I think we agree that the runtime should assert when it is passed an invalid 
deallocation size. The problem you’re describing could still occur with the 
UnsafeBufferPointer.deallocate() method if the user happened to slice and 
rebase the buffer.

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Taylor Swift via swift-evolution


> On Sep 6, 2017, at 6:27 PM, Andrew Trick  wrote:
> 
> 
>> On Sep 6, 2017, at 3:42 PM, Joe Groff  wrote:
>> 
>> 
>>> On Sep 6, 2017, at 3:26 PM, Andrew Trick  wrote:
>>> 
>>> 
> On Sep 6, 2017, at 2:31 PM, Joe Groff  wrote:
> 
> 
> The fact that we’re using malloc and free is already part of the ABI 
> because old libraries need to be able to deallocate memory allocated by 
> newer libraries.
 
 The compiler doesn't ever generate calls directly to malloc and free, and 
 the runtime entry points we do use already take size and alignment on both 
 allocation and deallocation.
>>> 
>>> True, we’ve never said that UnsafePointer deallocation is compatible with 
>>> C, and I we don't currently expose malloc_size functionality in any API 
>>> AFAIK.
>>> 
> Within the standard library we could make use of some new deallocation 
> fast path in the future without worrying about backward deployment.
> 
> Outside of the standard library, clients will get the benefits of 
> whatever allocator is available on their deployed platform because we now 
> encourage them to use UnsafeBufferPointer.deallocate(). We can change the 
> implementation inside UnsafeBufferPointer all we want, as long as it’s 
> still malloc-compatible.
> 
> I’m sure we’ll want to provide a better allocation/deallocation API in 
> the future for systems programmers based on move-only types. That will 
> already be deployment-limited.
> 
> Absolute worst case, we introduce a sized UnsafePointer.deallocate in the 
> future. Any new code outside the stdlib that wants the performance 
> advantage would either need to
> - trivially wrap deallocation using UnsafeBufferPointer
> - create a trivial UnsafePointer.deallocate thunk under an availability 
> flag
 
 Since we already have sized deallocate, why would we take it away? If the 
 name is misleading, we can change the name.
>>> 
>>> I don't think leaving it as an optional argument is worthwhile, as I 
>>> explained above. Deallocation capacity is either required or we drop it 
>>> completely. If we keep it, then `allocatedCapacity` is the right name.
>>> 
>>> The reason for taking it away, beside being misleading, is that it exposes 
>>> another level of unsafety.
>>> 
>>> My thinking has been that this is not the allocation fast path of the 
>>> future, and the stdlib itself could track the size of unsafely-allocated 
>>> blocks if it ever used a different underlying allocator.
>>> 
>>> Now I realize this isn't really about fast/slow deallocation paths. 
>>> Removing `capacity` or even making it optional forces all future Swift 
>>> implementations to provide malloc_size functionality for any piece of 
>>> memory that is compatible with the Unsafe API.
>>> 
>>> I'm actually ok with that, because I think it's generally desirable for 
>>> application memory to reside in either in malloc-compatible blocks or fixed 
>>> size pools. i.e. I think malloc_size is something the platform needs. 
>>> However, you seem to think this would be too restrictive in the future. How 
>>> is this a known problem for C and what's your confidence level it will be a 
>>> problem for Swift?
>> 
>> No, I agree that being malloc-compatible is a reasonable goal; on Apple 
>> platforms, being able to register any custom allocator we come up with as a 
>> malloc zone would mean that the platform's existing memory profiling and 
>> debugging tools can still work. Even if we have a scheme where the allocator 
>> directly reaches into per-thread fixed-sized pools, it seems to me like it'd 
>> be hard to make malloc_size impossible to implement, though it might be 
>> slow, asking each pool for each thread whether an address is inside it. 
>> Strongly encouraging, if not requiring, user code to provide deallocation 
>> sizes seems to me like a prerequisite to making that sort of design a net 
>> win over plain malloc/free. 
>> 
>> -Joe
> 
> Ok good. For growable buffers, we also want the OS to give us malloc_size 
> which may be larger than requested capacity.
> 
> The semantics of buffer.deallocate() needs to be: free `buffer.count` bytes 
> of memory at `buffer.baseAddress`. So, that will always be the fast path!
> Kelvin, do you agree with that?

this could be problematic if you have multiple contiguous buffers carved out of 
the same heap block. i agree that this is the best semantics for buffer 
pointers but we need the sized backend in Swift before this is possible else we 
will end up in the same boat we’re in right now with `deallocate(capacity:)` 
where we would have to make buffer deallocate heap block-based for now and then 
pull the rug out from underneath users later in order to switch to the improved 
semantics

> 
> Any future safe API for manual buffer allocation/deallocation will also track 
> the buffer size, so that 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Taylor Swift via swift-evolution


> On Sep 6, 2017, at 5:12 PM, Joe Groff  wrote:
> 
> 
>> On Sep 6, 2017, at 3:07 PM, Taylor Swift  wrote:
>> 
>> 
>> 
>>> On Sep 6, 2017, at 4:31 PM, Joe Groff  wrote:
>>> 
>>> 
 On Sep 6, 2017, at 2:28 PM, Andrew Trick  wrote:
 
 
>> On Sep 6, 2017, at 1:12 PM, Joe Groff via swift-evolution 
>>  wrote:
>> 
>> 
>> On Sep 6, 2017, at 1:06 PM, Taylor Swift  wrote:
>> 
>> 
>> 
>>> On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution 
>>>  wrote:
>>> Currently, memory is deallocated by an instance method on 
>>> UnsafeMutablePointer, deallocate(count:). Like much of the Swift 
>>> pointer API, performing this operation on a buffer pointer requires 
>>> extracting baseAddress! and count. It is very common for the allocation 
>>> code above to be immediately followed by:
>>> 
>>> defer
>>> 
>>> {
>>> buffer.
>>> baseAddress?.deallocate(capacity: buffer.count
>>> )
>>> }
>>> 
>>> This method is extremely problematic because nearly all users, on first 
>>> seeing the signature of deallocate(capacity:), will naturally conclude 
>>> from the capacity label that deallocate(capacity:) is equivalent to 
>>> some kind of realloc()that can only shrink the buffer. However this is 
>>> not the actual behavior — deallocate(capacity:) actually ignores the 
>>> capacity argument and just calls free() on self. The current API is not 
>>> only awkward and suboptimal, it is misleading. You can write perfectly 
>>> legal Swift code that shouldn’t segfault, but still can, for example
>>> 
>>> var ptr = UnsafeMutablePointer.allocate(capacity: 100
>>> )
>>> ptr.
>>> initialize(to: 13, count: 100
>>> )
>>> ptr.
>>> deallocate(capacity: 50) // deallocate the second half of the 
>>> memory block
>>> ptr[0] // segmentation fault
>>> where the first 50 addresses should still be valid if the 
>>> documentation is to be read literally.
>> 
>> The fact that the Swift runtime currently uses malloc/free is an 
>> implementation detail. Tracking deallocation size is a very useful 
>> optimization for better allocator backends, and C++ underwent an ABI 
>> break to make it so that sized delete can be supported. Maybe we can 
>> change the name to `deallocate(allocatedCapacity:)` to make it clear 
>> that it isn't resizing the memory, and/or make the capacity argument 
>> optional so that you can pay for the overhead of the allocator deriving 
>> the size if it's inconvenient for the calling code to carry the size 
>> around, but we shouldn't remove the functionality altogether.
>> 
>> -Joe
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> The idea is to get the house in order by removing all parameters from 
>> deallocate(), since that’s what it really does right now. Then, in the 
>> future, if Swift gets a more sophisticated allocator backend, a new 
>> method like deallocate(capacity:) or reallocate(toCapacity:) could be 
>> added without conflicting with the currently named 
>> deallocate(capacity:). However, using the function signature to pretend 
>> that it does something it can’t actually do right now is extremely 
>> dangerous.
> 
> I don't think that's a good idea in this case, because it's not unlikely 
> we would explore an optimized allocator soon after ABI stability, and 
> retrofitting these interfaces in a future version of Swift would put a 
> deployment target limit on when they can be used, and mean that a lot of 
> user code would need to be retrofitted to carry allocated capacities 
> where needed to see any benefit.
> 
> -Joe
 
 The fact that we’re using malloc and free is already part of the ABI 
 because old libraries need to be able to deallocate memory allocated by 
 newer libraries.
>>> 
>>> The compiler doesn't ever generate calls directly to malloc and free, and 
>>> the runtime entry points we do use already take size and alignment on both 
>>> allocation and deallocation.
>>> 
 Within the standard library we could make use of some new deallocation 
 fast path in the future without worrying about backward deployment.
 
 Outside of the standard library, clients will get the benefits of whatever 
 allocator is available on their deployed platform because we now encourage 
 them to use UnsafeBufferPointer.deallocate(). We can change the 
 implementation inside UnsafeBufferPointer all we want, as long as it’s 
 still malloc-compatible.
 
 I’m 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Andrew Trick via swift-evolution

> On Sep 6, 2017, at 3:42 PM, Joe Groff  wrote:
> 
> 
>> On Sep 6, 2017, at 3:26 PM, Andrew Trick  wrote:
>> 
>> 
>>> On Sep 6, 2017, at 2:31 PM, Joe Groff  wrote:
>>> 
 
 The fact that we’re using malloc and free is already part of the ABI 
 because old libraries need to be able to deallocate memory allocated by 
 newer libraries.
>>> 
>>> The compiler doesn't ever generate calls directly to malloc and free, and 
>>> the runtime entry points we do use already take size and alignment on both 
>>> allocation and deallocation.
>> 
>> True, we’ve never said that UnsafePointer deallocation is compatible with C, 
>> and I we don't currently expose malloc_size functionality in any API AFAIK.
>> 
 Within the standard library we could make use of some new deallocation 
 fast path in the future without worrying about backward deployment.
 
 Outside of the standard library, clients will get the benefits of whatever 
 allocator is available on their deployed platform because we now encourage 
 them to use UnsafeBufferPointer.deallocate(). We can change the 
 implementation inside UnsafeBufferPointer all we want, as long as it’s 
 still malloc-compatible.
 
 I’m sure we’ll want to provide a better allocation/deallocation API in the 
 future for systems programmers based on move-only types. That will already 
 be deployment-limited.
 
 Absolute worst case, we introduce a sized UnsafePointer.deallocate in the 
 future. Any new code outside the stdlib that wants the performance 
 advantage would either need to
 - trivially wrap deallocation using UnsafeBufferPointer
 - create a trivial UnsafePointer.deallocate thunk under an availability 
 flag
>>> 
>>> Since we already have sized deallocate, why would we take it away? If the 
>>> name is misleading, we can change the name.
>> 
>> I don't think leaving it as an optional argument is worthwhile, as I 
>> explained above. Deallocation capacity is either required or we drop it 
>> completely. If we keep it, then `allocatedCapacity` is the right name.
>> 
>> The reason for taking it away, beside being misleading, is that it exposes 
>> another level of unsafety.
>> 
>> My thinking has been that this is not the allocation fast path of the 
>> future, and the stdlib itself could track the size of unsafely-allocated 
>> blocks if it ever used a different underlying allocator.
>> 
>> Now I realize this isn't really about fast/slow deallocation paths. Removing 
>> `capacity` or even making it optional forces all future Swift 
>> implementations to provide malloc_size functionality for any piece of memory 
>> that is compatible with the Unsafe API.
>> 
>> I'm actually ok with that, because I think it's generally desirable for 
>> application memory to reside in either in malloc-compatible blocks or fixed 
>> size pools. i.e. I think malloc_size is something the platform needs. 
>> However, you seem to think this would be too restrictive in the future. How 
>> is this a known problem for C and what's your confidence level it will be a 
>> problem for Swift?
> 
> No, I agree that being malloc-compatible is a reasonable goal; on Apple 
> platforms, being able to register any custom allocator we come up with as a 
> malloc zone would mean that the platform's existing memory profiling and 
> debugging tools can still work. Even if we have a scheme where the allocator 
> directly reaches into per-thread fixed-sized pools, it seems to me like it'd 
> be hard to make malloc_size impossible to implement, though it might be slow, 
> asking each pool for each thread whether an address is inside it. Strongly 
> encouraging, if not requiring, user code to provide deallocation sizes seems 
> to me like a prerequisite to making that sort of design a net win over plain 
> malloc/free. 
> 
> -Joe

Ok good. For growable buffers, we also want the OS to give us malloc_size which 
may be larger than requested capacity.

The semantics of buffer.deallocate() needs to be: free `buffer.count` bytes of 
memory at `buffer.baseAddress`. So, that will always be the fast path!
Kelvin, do you agree with that?

Any future safe API for manual buffer allocation/deallocation will also track 
the buffer size, so that will also be the fast path.

In the future, pointer.deallocate() without capacity might become a slower 
path. But I think that the UnsafePointer allocation/deallocation paths are 
Swift's equivalent of malloc/free. If the client code knows the buffer size, it 
shouldn't be using those. In fact, we don't want to force the client to track 
capacity if deallocation is *not* performance critical.

I suppose an optional `allocatedCapacity` argument would be ok, since we should 
be asserting in the runtime anyway. It just adds complexity to the API and I 
don't buy the backward deployment argument.

-Andy

___

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] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Joe Groff via swift-evolution

> On Sep 6, 2017, at 3:26 PM, Andrew Trick  wrote:
> 
> 
>> On Sep 6, 2017, at 2:31 PM, Joe Groff  wrote:
>> 
>>> 
>>> The fact that we’re using malloc and free is already part of the ABI 
>>> because old libraries need to be able to deallocate memory allocated by 
>>> newer libraries.
>> 
>> The compiler doesn't ever generate calls directly to malloc and free, and 
>> the runtime entry points we do use already take size and alignment on both 
>> allocation and deallocation.
> 
> True, we’ve never said that UnsafePointer deallocation is compatible with C, 
> and I we don't currently expose malloc_size functionality in any API AFAIK.
> 
>>> Within the standard library we could make use of some new deallocation fast 
>>> path in the future without worrying about backward deployment.
>>> 
>>> Outside of the standard library, clients will get the benefits of whatever 
>>> allocator is available on their deployed platform because we now encourage 
>>> them to use UnsafeBufferPointer.deallocate(). We can change the 
>>> implementation inside UnsafeBufferPointer all we want, as long as it’s 
>>> still malloc-compatible.
>>> 
>>> I’m sure we’ll want to provide a better allocation/deallocation API in the 
>>> future for systems programmers based on move-only types. That will already 
>>> be deployment-limited.
>>> 
>>> Absolute worst case, we introduce a sized UnsafePointer.deallocate in the 
>>> future. Any new code outside the stdlib that wants the performance 
>>> advantage would either need to
>>> - trivially wrap deallocation using UnsafeBufferPointer
>>> - create a trivial UnsafePointer.deallocate thunk under an availability flag
>> 
>> Since we already have sized deallocate, why would we take it away? If the 
>> name is misleading, we can change the name.
> 
> I don't think leaving it as an optional argument is worthwhile, as I 
> explained above. Deallocation capacity is either required or we drop it 
> completely. If we keep it, then `allocatedCapacity` is the right name.
> 
> The reason for taking it away, beside being misleading, is that it exposes 
> another level of unsafety.
> 
> My thinking has been that this is not the allocation fast path of the future, 
> and the stdlib itself could track the size of unsafely-allocated blocks if it 
> ever used a different underlying allocator.
> 
> Now I realize this isn't really about fast/slow deallocation paths. Removing 
> `capacity` or even making it optional forces all future Swift implementations 
> to provide malloc_size functionality for any piece of memory that is 
> compatible with the Unsafe API.
> 
> I'm actually ok with that, because I think it's generally desirable for 
> application memory to reside in either in malloc-compatible blocks or fixed 
> size pools. i.e. I think malloc_size is something the platform needs. 
> However, you seem to think this would be too restrictive in the future. How 
> is this a known problem for C and what's your confidence level it will be a 
> problem for Swift?

No, I agree that being malloc-compatible is a reasonable goal; on Apple 
platforms, being able to register any custom allocator we come up with as a 
malloc zone would mean that the platform's existing memory profiling and 
debugging tools can still work. Even if we have a scheme where the allocator 
directly reaches into per-thread fixed-sized pools, it seems to me like it'd be 
hard to make malloc_size impossible to implement, though it might be slow, 
asking each pool for each thread whether an address is inside it. Strongly 
encouraging, if not requiring, user code to provide deallocation sizes seems to 
me like a prerequisite to making that sort of design a net win over plain 
malloc/free. 

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Andrew Trick via swift-evolution

> On Sep 6, 2017, at 2:31 PM, Joe Groff  wrote:
> 
>> 
>> The fact that we’re using malloc and free is already part of the ABI because 
>> old libraries need to be able to deallocate memory allocated by newer 
>> libraries.
> 
> The compiler doesn't ever generate calls directly to malloc and free, and the 
> runtime entry points we do use already take size and alignment on both 
> allocation and deallocation.

True, we’ve never said that UnsafePointer deallocation is compatible with C, 
and I we don't currently expose malloc_size functionality in any API AFAIK.

>> Within the standard library we could make use of some new deallocation fast 
>> path in the future without worrying about backward deployment.
>> 
>> Outside of the standard library, clients will get the benefits of whatever 
>> allocator is available on their deployed platform because we now encourage 
>> them to use UnsafeBufferPointer.deallocate(). We can change the 
>> implementation inside UnsafeBufferPointer all we want, as long as it’s still 
>> malloc-compatible.
>> 
>> I’m sure we’ll want to provide a better allocation/deallocation API in the 
>> future for systems programmers based on move-only types. That will already 
>> be deployment-limited.
>> 
>> Absolute worst case, we introduce a sized UnsafePointer.deallocate in the 
>> future. Any new code outside the stdlib that wants the performance advantage 
>> would either need to
>> - trivially wrap deallocation using UnsafeBufferPointer
>> - create a trivial UnsafePointer.deallocate thunk under an availability flag
> 
> Since we already have sized deallocate, why would we take it away? If the 
> name is misleading, we can change the name.


I don't think leaving it as an optional argument is worthwhile, as I explained 
above. Deallocation capacity is either required or we drop it completely. If we 
keep it, then `allocatedCapacity` is the right name.

The reason for taking it away, beside being misleading, is that it exposes 
another level of unsafety.

My thinking has been that this is not the allocation fast path of the future, 
and the stdlib itself could track the size of unsafely-allocated blocks if it 
ever used a different underlying allocator.

Now I realize this isn't really about fast/slow deallocation paths. Removing 
`capacity` or even making it optional forces all future Swift implementations 
to provide malloc_size functionality for any piece of memory that is compatible 
with the Unsafe API.

I'm actually ok with that, because I think it's generally desirable for 
application memory to reside in either in malloc-compatible blocks or fixed 
size pools. i.e. I think malloc_size is something the platform needs. However, 
you seem to think this would be too restrictive in the future. How is this a 
known problem for C and what's your confidence level it will be a problem for 
Swift?

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Joe Groff via swift-evolution

> On Sep 6, 2017, at 3:07 PM, Taylor Swift  wrote:
> 
> 
> 
>> On Sep 6, 2017, at 4:31 PM, Joe Groff  wrote:
>> 
>> 
>>> On Sep 6, 2017, at 2:28 PM, Andrew Trick  wrote:
>>> 
>>> 
> On Sep 6, 2017, at 1:12 PM, Joe Groff via swift-evolution 
>  wrote:
> 
> 
> On Sep 6, 2017, at 1:06 PM, Taylor Swift  wrote:
> 
> 
> 
>> On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution 
>>  wrote:
>> Currently, memory is deallocated by an instance method on 
>> UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer 
>> API, performing this operation on a buffer pointer requires extracting 
>> baseAddress! and count. It is very common for the allocation code above 
>> to be immediately followed by:
>> 
>> defer
>> 
>> {
>>  buffer.
>> baseAddress?.deallocate(capacity: buffer.count
>> )
>> }
>> 
>> This method is extremely problematic because nearly all users, on first 
>> seeing the signature of deallocate(capacity:), will naturally conclude 
>> from the capacity label that deallocate(capacity:) is equivalent to some 
>> kind of realloc()that can only shrink the buffer. However this is not 
>> the actual behavior — deallocate(capacity:) actually ignores the 
>> capacity argument and just calls free() on self. The current API is not 
>> only awkward and suboptimal, it is misleading. You can write perfectly 
>> legal Swift code that shouldn’t segfault, but still can, for example
>> 
>> var ptr = UnsafeMutablePointer.allocate(capacity: 100
>> )
>> ptr.
>> initialize(to: 13, count: 100
>> )
>> ptr.
>> deallocate(capacity: 50) // deallocate the second half of the memory 
>> block
>> ptr[0] // segmentation fault
>> where the first 50 addresses should still be valid if the 
>> documentation is to be read literally.
> 
> The fact that the Swift runtime currently uses malloc/free is an 
> implementation detail. Tracking deallocation size is a very useful 
> optimization for better allocator backends, and C++ underwent an ABI 
> break to make it so that sized delete can be supported. Maybe we can 
> change the name to `deallocate(allocatedCapacity:)` to make it clear that 
> it isn't resizing the memory, and/or make the capacity argument optional 
> so that you can pay for the overhead of the allocator deriving the size 
> if it's inconvenient for the calling code to carry the size around, but 
> we shouldn't remove the functionality altogether.
> 
> -Joe
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> The idea is to get the house in order by removing all parameters from 
> deallocate(), since that’s what it really does right now. Then, in the 
> future, if Swift gets a more sophisticated allocator backend, a new 
> method like deallocate(capacity:) or reallocate(toCapacity:) could be 
> added without conflicting with the currently named deallocate(capacity:). 
> However, using the function signature to pretend that it does something 
> it can’t actually do right now is extremely dangerous.
 
 I don't think that's a good idea in this case, because it's not unlikely 
 we would explore an optimized allocator soon after ABI stability, and 
 retrofitting these interfaces in a future version of Swift would put a 
 deployment target limit on when they can be used, and mean that a lot of 
 user code would need to be retrofitted to carry allocated capacities where 
 needed to see any benefit.
 
 -Joe
>>> 
>>> The fact that we’re using malloc and free is already part of the ABI 
>>> because old libraries need to be able to deallocate memory allocated by 
>>> newer libraries.
>> 
>> The compiler doesn't ever generate calls directly to malloc and free, and 
>> the runtime entry points we do use already take size and alignment on both 
>> allocation and deallocation.
>> 
>>> Within the standard library we could make use of some new deallocation fast 
>>> path in the future without worrying about backward deployment.
>>> 
>>> Outside of the standard library, clients will get the benefits of whatever 
>>> allocator is available on their deployed platform because we now encourage 
>>> them to use UnsafeBufferPointer.deallocate(). We can change the 
>>> implementation inside UnsafeBufferPointer all we want, as long as it’s 
>>> still malloc-compatible.
>>> 
>>> I’m sure we’ll want to provide a better allocation/deallocation API in the 
>>> future for systems programmers based on move-only types. That will already 
>>> be deployment-limited.
>>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Taylor Swift via swift-evolution


> On Sep 6, 2017, at 4:31 PM, Joe Groff  wrote:
> 
> 
>> On Sep 6, 2017, at 2:28 PM, Andrew Trick  wrote:
>> 
>> 
 On Sep 6, 2017, at 1:12 PM, Joe Groff via swift-evolution 
  wrote:
 
 
 On Sep 6, 2017, at 1:06 PM, Taylor Swift  wrote:
 
 
 
> On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution 
>  wrote:
> Currently, memory is deallocated by an instance method on 
> UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer 
> API, performing this operation on a buffer pointer requires extracting 
> baseAddress! and count. It is very common for the allocation code above 
> to be immediately followed by:
> 
> defer
> 
> {
>   buffer.
> baseAddress?.deallocate(capacity: buffer.count
> )
> }
> 
> This method is extremely problematic because nearly all users, on first 
> seeing the signature of deallocate(capacity:), will naturally conclude 
> from the capacity label that deallocate(capacity:) is equivalent to some 
> kind of realloc()that can only shrink the buffer. However this is not the 
> actual behavior — deallocate(capacity:) actually ignores the capacity 
> argument and just calls free() on self. The current API is not only 
> awkward and suboptimal, it is misleading. You can write perfectly legal 
> Swift code that shouldn’t segfault, but still can, for example
> 
> var ptr = UnsafeMutablePointer.allocate(capacity: 100
> )
> ptr.
> initialize(to: 13, count: 100
> )
> ptr.
> deallocate(capacity: 50) // deallocate the second half of the memory 
> block
> ptr[0] // segmentation fault
> where the first 50 addresses should still be valid if the 
> documentation is to be read literally.
 
 The fact that the Swift runtime currently uses malloc/free is an 
 implementation detail. Tracking deallocation size is a very useful 
 optimization for better allocator backends, and C++ underwent an ABI break 
 to make it so that sized delete can be supported. Maybe we can change the 
 name to `deallocate(allocatedCapacity:)` to make it clear that it isn't 
 resizing the memory, and/or make the capacity argument optional so that 
 you can pay for the overhead of the allocator deriving the size if it's 
 inconvenient for the calling code to carry the size around, but we 
 shouldn't remove the functionality altogether.
 
 -Joe
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
 
 The idea is to get the house in order by removing all parameters from 
 deallocate(), since that’s what it really does right now. Then, in the 
 future, if Swift gets a more sophisticated allocator backend, a new method 
 like deallocate(capacity:) or reallocate(toCapacity:) could be added 
 without conflicting with the currently named deallocate(capacity:). 
 However, using the function signature to pretend that it does something it 
 can’t actually do right now is extremely dangerous.
>>> 
>>> I don't think that's a good idea in this case, because it's not unlikely we 
>>> would explore an optimized allocator soon after ABI stability, and 
>>> retrofitting these interfaces in a future version of Swift would put a 
>>> deployment target limit on when they can be used, and mean that a lot of 
>>> user code would need to be retrofitted to carry allocated capacities where 
>>> needed to see any benefit.
>>> 
>>> -Joe
>> 
>> The fact that we’re using malloc and free is already part of the ABI because 
>> old libraries need to be able to deallocate memory allocated by newer 
>> libraries.
> 
> The compiler doesn't ever generate calls directly to malloc and free, and the 
> runtime entry points we do use already take size and alignment on both 
> allocation and deallocation.
> 
>> Within the standard library we could make use of some new deallocation fast 
>> path in the future without worrying about backward deployment.
>> 
>> Outside of the standard library, clients will get the benefits of whatever 
>> allocator is available on their deployed platform because we now encourage 
>> them to use UnsafeBufferPointer.deallocate(). We can change the 
>> implementation inside UnsafeBufferPointer all we want, as long as it’s still 
>> malloc-compatible.
>> 
>> I’m sure we’ll want to provide a better allocation/deallocation API in the 
>> future for systems programmers based on move-only types. That will already 
>> be deployment-limited.
>> 
>> Absolute worst case, we introduce a sized UnsafePointer.deallocate in the 
>> future. Any new code outside the stdlib that wants the performance advantage 
>> would either need to
>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Joe Groff via swift-evolution

> On Sep 6, 2017, at 2:28 PM, Andrew Trick  wrote:
> 
> 
>> On Sep 6, 2017, at 1:12 PM, Joe Groff via swift-evolution 
>>  wrote:
>> 
>>> 
>>> On Sep 6, 2017, at 1:06 PM, Taylor Swift  wrote:
>>> 
>>> 
>>> 
>>> On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution 
>>>  wrote:
 Currently, memory is deallocated by an instance method on 
 UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer 
 API, performing this operation on a buffer pointer requires extracting 
 baseAddress! and count. It is very common for the allocation code above to 
 be immediately followed by:
 
 defer
 
 {
buffer.
 baseAddress?.deallocate(capacity: buffer.count
 )
 }
 
 This method is extremely problematic because nearly all users, on first 
 seeing the signature of deallocate(capacity:), will naturally conclude 
 from the capacity label that deallocate(capacity:) is equivalent to some 
 kind of realloc()that can only shrink the buffer. However this is not the 
 actual behavior — deallocate(capacity:) actually ignores the capacity 
 argument and just calls free() on self. The current API is not only 
 awkward and suboptimal, it is misleading. You can write perfectly legal 
 Swift code that shouldn’t segfault, but still can, for example
 
 var ptr = UnsafeMutablePointer.allocate(capacity: 100
 )
 ptr.
 initialize(to: 13, count: 100
 )
 ptr.
 deallocate(capacity: 50) // deallocate the second half of the memory 
 block
 ptr[0] // segmentation fault
 where the first 50 addresses should still be valid if the 
 documentation is to be read literally.
>>> 
>>> The fact that the Swift runtime currently uses malloc/free is an 
>>> implementation detail. Tracking deallocation size is a very useful 
>>> optimization for better allocator backends, and C++ underwent an ABI break 
>>> to make it so that sized delete can be supported. Maybe we can change the 
>>> name to `deallocate(allocatedCapacity:)` to make it clear that it isn't 
>>> resizing the memory, and/or make the capacity argument optional so that you 
>>> can pay for the overhead of the allocator deriving the size if it's 
>>> inconvenient for the calling code to carry the size around, but we 
>>> shouldn't remove the functionality altogether.
>>> 
>>> -Joe
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> The idea is to get the house in order by removing all parameters from 
>>> deallocate(), since that’s what it really does right now. Then, in the 
>>> future, if Swift gets a more sophisticated allocator backend, a new method 
>>> like deallocate(capacity:) or reallocate(toCapacity:) could be added 
>>> without conflicting with the currently named deallocate(capacity:). 
>>> However, using the function signature to pretend that it does something it 
>>> can’t actually do right now is extremely dangerous.
>> 
>> I don't think that's a good idea in this case, because it's not unlikely we 
>> would explore an optimized allocator soon after ABI stability, and 
>> retrofitting these interfaces in a future version of Swift would put a 
>> deployment target limit on when they can be used, and mean that a lot of 
>> user code would need to be retrofitted to carry allocated capacities where 
>> needed to see any benefit.
>> 
>> -Joe
> 
> The fact that we’re using malloc and free is already part of the ABI because 
> old libraries need to be able to deallocate memory allocated by newer 
> libraries.

The compiler doesn't ever generate calls directly to malloc and free, and the 
runtime entry points we do use already take size and alignment on both 
allocation and deallocation.

> Within the standard library we could make use of some new deallocation fast 
> path in the future without worrying about backward deployment.
> 
> Outside of the standard library, clients will get the benefits of whatever 
> allocator is available on their deployed platform because we now encourage 
> them to use UnsafeBufferPointer.deallocate(). We can change the 
> implementation inside UnsafeBufferPointer all we want, as long as it’s still 
> malloc-compatible.
> 
> I’m sure we’ll want to provide a better allocation/deallocation API in the 
> future for systems programmers based on move-only types. That will already be 
> deployment-limited.
> 
> Absolute worst case, we introduce a sized UnsafePointer.deallocate in the 
> future. Any new code outside the stdlib that wants the performance advantage 
> would either need to
> - trivially wrap deallocation using UnsafeBufferPointer
> - create a trivial UnsafePointer.deallocate thunk under an availability flag

Since we already have sized deallocate, why would we 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Andrew Trick via swift-evolution

> On Sep 6, 2017, at 1:12 PM, Joe Groff via swift-evolution 
>  wrote:
> 
>> 
>> On Sep 6, 2017, at 1:06 PM, Taylor Swift  wrote:
>> 
>> 
>> 
>> On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution 
>>  wrote:
>>> Currently, memory is deallocated by an instance method on 
>>> UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer 
>>> API, performing this operation on a buffer pointer requires extracting 
>>> baseAddress! and count. It is very common for the allocation code above to 
>>> be immediately followed by:
>>> 
>>> defer
>>> 
>>> {
>>>buffer.
>>> baseAddress?.deallocate(capacity: buffer.count
>>> )
>>> }
>>> 
>>> This method is extremely problematic because nearly all users, on first 
>>> seeing the signature of deallocate(capacity:), will naturally conclude from 
>>> the capacity label that deallocate(capacity:) is equivalent to some kind of 
>>> realloc()that can only shrink the buffer. However this is not the actual 
>>> behavior — deallocate(capacity:) actually ignores the capacity argument and 
>>> just calls free() on self. The current API is not only awkward and 
>>> suboptimal, it is misleading. You can write perfectly legal Swift code that 
>>> shouldn’t segfault, but still can, for example
>>> 
>>> var ptr = UnsafeMutablePointer.allocate(capacity: 100
>>> )
>>> ptr.
>>> initialize(to: 13, count: 100
>>> )
>>> ptr.
>>> deallocate(capacity: 50) // deallocate the second half of the memory 
>>> block
>>> ptr[0] // segmentation fault
>>> where the first 50 addresses should still be valid if the documentation 
>>> is to be read literally.
>> 
>> The fact that the Swift runtime currently uses malloc/free is an 
>> implementation detail. Tracking deallocation size is a very useful 
>> optimization for better allocator backends, and C++ underwent an ABI break 
>> to make it so that sized delete can be supported. Maybe we can change the 
>> name to `deallocate(allocatedCapacity:)` to make it clear that it isn't 
>> resizing the memory, and/or make the capacity argument optional so that you 
>> can pay for the overhead of the allocator deriving the size if it's 
>> inconvenient for the calling code to carry the size around, but we shouldn't 
>> remove the functionality altogether.
>> 
>> -Joe
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> The idea is to get the house in order by removing all parameters from 
>> deallocate(), since that’s what it really does right now. Then, in the 
>> future, if Swift gets a more sophisticated allocator backend, a new method 
>> like deallocate(capacity:) or reallocate(toCapacity:) could be added without 
>> conflicting with the currently named deallocate(capacity:). However, using 
>> the function signature to pretend that it does something it can’t actually 
>> do right now is extremely dangerous.
> 
> I don't think that's a good idea in this case, because it's not unlikely we 
> would explore an optimized allocator soon after ABI stability, and 
> retrofitting these interfaces in a future version of Swift would put a 
> deployment target limit on when they can be used, and mean that a lot of user 
> code would need to be retrofitted to carry allocated capacities where needed 
> to see any benefit.
> 
> -Joe


The fact that we’re using malloc and free is already part of the ABI because 
old libraries need to be able to deallocate memory allocated by newer libraries.

Within the standard library we could make use of some new deallocation fast 
path in the future without worrying about backward deployment.

Outside of the standard library, clients will get the benefits of whatever 
allocator is available on their deployed platform because we now encourage them 
to use UnsafeBufferPointer.deallocate(). We can change the implementation 
inside UnsafeBufferPointer all we want, as long as it’s still malloc-compatible.

I’m sure we’ll want to provide a better allocation/deallocation API in the 
future for systems programmers based on move-only types. That will already be 
deployment-limited.

Absolute worst case, we introduce a sized UnsafePointer.deallocate in the 
future. Any new code outside the stdlib that wants the performance advantage 
would either need to
- trivially wrap deallocation using UnsafeBufferPointer
- create a trivial UnsafePointer.deallocate thunk under an availability flag

-Andy___
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] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Joe Groff via swift-evolution

> On Sep 6, 2017, at 1:06 PM, Taylor Swift  wrote:
> 
> 
> 
> On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution 
>  wrote:
> > Currently, memory is deallocated by an instance method on 
> > UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer 
> > API, performing this operation on a buffer pointer requires extracting 
> > baseAddress! and count. It is very common for the allocation code above to 
> > be immediately followed by:
> >
> > defer
> >
> > {
> > buffer.
> > baseAddress?.deallocate(capacity: buffer.count
> > )
> > }
> >
> > This method is extremely problematic because nearly all users, on first 
> > seeing the signature of deallocate(capacity:), will naturally conclude from 
> > the capacity label that deallocate(capacity:) is equivalent to some kind of 
> > realloc()that can only shrink the buffer. However this is not the actual 
> > behavior — deallocate(capacity:) actually ignores the capacity argument and 
> > just calls free() on self. The current API is not only awkward and 
> > suboptimal, it is misleading. You can write perfectly legal Swift code that 
> > shouldn’t segfault, but still can, for example
> >
> > var ptr = UnsafeMutablePointer.allocate(capacity: 100
> > )
> > ptr.
> > initialize(to: 13, count: 100
> > )
> > ptr.
> > deallocate(capacity: 50) // deallocate the second half of the memory 
> > block
> > ptr[0] // segmentation fault
> > where the first 50 addresses should still be valid if the documentation 
> > is to be read literally.
> 
> The fact that the Swift runtime currently uses malloc/free is an 
> implementation detail. Tracking deallocation size is a very useful 
> optimization for better allocator backends, and C++ underwent an ABI break to 
> make it so that sized delete can be supported. Maybe we can change the name 
> to `deallocate(allocatedCapacity:)` to make it clear that it isn't resizing 
> the memory, and/or make the capacity argument optional so that you can pay 
> for the overhead of the allocator deriving the size if it's inconvenient for 
> the calling code to carry the size around, but we shouldn't remove the 
> functionality altogether.
> 
> -Joe
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> The idea is to get the house in order by removing all parameters from 
> deallocate(), since that’s what it really does right now. Then, in the 
> future, if Swift gets a more sophisticated allocator backend, a new method 
> like deallocate(capacity:) or reallocate(toCapacity:) could be added without 
> conflicting with the currently named deallocate(capacity:). However, using 
> the function signature to pretend that it does something it can’t actually do 
> right now is extremely dangerous.

I don't think that's a good idea in this case, because it's not unlikely we 
would explore an optimized allocator soon after ABI stability, and retrofitting 
these interfaces in a future version of Swift would put a deployment target 
limit on when they can be used, and mean that a lot of user code would need to 
be retrofitted to carry allocated capacities where needed to see any benefit.

-Joe

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Taylor Swift via swift-evolution
On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution <
swift-evolution@swift.org> wrote:

> > Currently, memory is deallocated by an instance method on
> UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer
> API, performing this operation on a buffer pointer requires extracting
> baseAddress! and count. It is very common for the allocation code above to
> be immediately followed by:
> >
> > defer
> >
> > {
> > buffer.
> > baseAddress?.deallocate(capacity: buffer.count
> > )
> > }
> >
> > This method is extremely problematic because nearly all users, on first
> seeing the signature of deallocate(capacity:), will naturally conclude from
> the capacity label that deallocate(capacity:) is equivalent to some kind of
> realloc()that can only shrink the buffer. However this is not the actual
> behavior — deallocate(capacity:) actually ignores the capacity argument and
> just calls free() on self. The current API is not only awkward and
> suboptimal, it is misleading. You can write perfectly legal Swift code that
> shouldn’t segfault, but still can, for example
> >
> > var ptr = UnsafeMutablePointer.allocate(capacity: 100
> > )
> > ptr.
> > initialize(to: 13, count: 100
> > )
> > ptr.
> > deallocate(capacity: 50) // deallocate the second half of the memory
> block
> > ptr[0] // segmentation fault
> > where the first 50 addresses should still be valid if the
> documentation is to be read literally.
>
> The fact that the Swift runtime currently uses malloc/free is an
> implementation detail. Tracking deallocation size is a very useful
> optimization for better allocator backends, and C++ underwent an ABI break
> to make it so that sized delete can be supported. Maybe we can change the
> name to `deallocate(allocatedCapacity:)` to make it clear that it isn't
> resizing the memory, and/or make the capacity argument optional so that you
> can pay for the overhead of the allocator deriving the size if it's
> inconvenient for the calling code to carry the size around, but we
> shouldn't remove the functionality altogether.
>
> -Joe
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>

The idea is to get the house in order by removing all parameters from
deallocate(), since that’s what it really does right now. Then, in the
future, if Swift gets a more sophisticated allocator backend, a new method
like deallocate(capacity:) or reallocate(toCapacity:) could be added
without conflicting with the currently named deallocate(capacity:).
However, using the function signature to pretend that it does something it
can’t actually do right now is extremely dangerous.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] DateComponents{Encoding/Decoding}Strategy in JSON{Encoder/Decoder}

2017-09-06 Thread Pitiphong Phongpattranont via swift-evolution
Hi Itai,

Thanks for a good and solid explanation. First I want to express my use case 
that was the reason I try to pitch this idea. We have a schedule service and 
the data model that represent the occurrence holds an information on what date 
of this occurrence was created in terms of a date string “2017-09-06” which is 
conform to ISO 8601. In this case we don’t intend to store a `Date` value 
(which is a specific point in the time line) but only store an information of 
what date it was occurred. So I decided to parse the date string into a 
`DateComponents` value.

What motivates me to pitch this idea in the end was that I tried to rely on the 
auto synthesized code by the compiler. Since the `DateComponents` already 
conforms to the Encodable/Decodable protocol which already allow the compiler 
to synthesize the code for encode(to:) and init(from:), however since I need to 
decode from the data I told you at first, those generated code will fail to 
decode the `DateComponents` and cause me some bugs. That’s what encourage me to 
do this pitch.

— Pitiphong P.




> On 7 Sep BE 2560, at 01:03, Itai Ferber  wrote:
> 
> Hi Pitiphong,
> 
> Don’t worry — your original email was clear, and we are on the same page 
> about Date{En,De}codingStrategy and DateComponents{En,De}codingStrategy being 
> separate things.
> To clarify my points, though, there are two main things I want to say:
> 
> I think there is a mismatch here between your goal of representing the 
> components of a date (and what DateComponents can specifically hold) and the 
> goal of ISO 8601
> I think that there is an inherent problem in parsing DateComponents due to 
> ambiguity
> I think both of these issues can be solved by reading and writing a Date 
> (formatted however you need it to be) instead of DateComponents.
> 
> To elaborate:
> 
> DateComponents is meant to be a container for an arbitrary subset of 
> information about a Date. A Date represents a specific instant in time, but 
> DateComponents are effectively meaningless without additional context. In the 
> examples that you give, it’s possible to represent the concepts at hand with 
> DateComponents, but in order to make those components actionable and 
> meaningful, you still need to convert them to Dates. Note also that:
> 
> It’s entirely possible to create a DateComponents which represents a date 
> which does not exist, or a time which does not exist
> Any of these concepts can also be represented by a Date instead of just 
> components; e.g., an all-day event can be represented by a Date that 
> represents the beginning of the day (00:00:00) and a flag that indicates that 
> the time of the event can be ignored, or by a start Date that represents the 
> start of the day and and end Date that represents the end of the day
> Unlike DateComponents, ISO 8601 strings have some structure to them. They 
> cannot represent just a time zone, for instance, or some singular components 
> of a date/time (e.g. a month without a year, a day without a month and year, 
> a minute without an hour, a second without a minute and hour, etc.). I think 
> this is a relatively large conceptual mismatch that is worth considering 
> deeply. There are a lot of DateComponents instances which simply cannot be 
> represented by an ISO 8601 string
> 
> There is also the issue of decoding arbitrary ISO 8601 strings into 
> DateComponents. DateComponents, having no structure at all, have no specified 
> format they can expect to decode from, and ISO 8601 does not always provide 
> that structure. Consider the following example:
> 
> ISO 8601 allows for date representations by year, month, and day 
> (-MM-DD), among other forms. But it also allows days to be left 
> unspecified (-MM), and even months ()
> Similarly, it allows for a time representations by hour, minute, and second 
> (hh:mm:ss), but also just hour and minute (hh:mm), and just hour (hh). 
> Importantly, it allows time separators to be omitted (hhmmss, hhmm, hh)
> Consider then, attempting to parse the string "2017" without any context — 
> what DateComponents should be read out? Intuitively, 2017 looks like a year 
> (), but it is equally valid to parse as the time 20:17 (hhmm). Without 
> knowing the expected format, parsing is ambiguous
> We cannot promise to parse DateComponents in all cases because there are many 
> combinations of strings that are just completely ambiguous.
> 
> So, to get at the core of this — if there is a specific format that you would 
> like to encode to and from, why not do so with a Date and a DateFormatter (or 
> if you need ISO 8601 specifically, ISO8601DateFormatter)? With a formatter, 
> the format is unambiguous because you explicitly provide it, and there is 
> nothing the date can’t represent that DateComponents can. You can always 
> parse the date and pull out only those components that you care about. You 
> also mention interoperability with an external JSON 

Re: [swift-evolution] Enums and Source Compatibility

2017-09-06 Thread Jose Cheyo Jimenez via swift-evolution
Here is an alternative view. I've been thinking about this and I feel that 
instead of adding this to an enum why not make RawRepresentable structs a swift 
construct. 

You could declare it like this:

enum struct {
   case a, b, c
}

This would be a struct that acts like an enum but it is open like a 
RawRepresentable but using the enum case sugar. 

> On Sep 5, 2017, at 5:37 PM, Jordan Rose via swift-evolution 
>  wrote:
> 
> It's in the "Alternatives Considered" section. :-) That was my desired design 
> when we started, but feedback convinced me that the break from Swift 4 mode 
> would be too drastic. The same valid code would have a different meaning 
> whether you were writing Swift 4 or Swift 5.
> 
> Jordan
> 
> 
>> On Sep 5, 2017, at 17:30, Rod Brown  wrote:
>> 
>> Hi Jordan,
>> 
>> I’m not sure how much bearing on this my comment will have.
>> 
>> Have you considered having only “exhaustive” as a keyword, and make the 
>> default non-exhaustive? It seems that “exhaustive" would be the rarer case, 
>> as it promises a lot more about compatibility (much like there is no such 
>> thing as “non-final”). Also, non exhaustive seems a massive mouthful despite 
>> it probably being the correct term.
>> 
>> - Rod
>> 
>>> On 6 Sep 2017, at 10:19 am, Jordan Rose  wrote:
>>> 
>>> I've taken everyone's feedback into consideration and written this up as a 
>>> proposal: 
>>> https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md.
>>>  The next step is working on an implementation, but if people have further 
>>> pre-review comments I'd be happy to hear them.
>>> 
>>> Jordan
> 
> ___
> 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] [Pitch] DateComponents{Encoding/Decoding}Strategy in JSON{Encoder/Decoder}

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

Hi Pitiphong,

Don’t worry — your original email was clear, and we are on the same 
page about `Date{En,De}codingStrategy` and 
`DateComponents{En,De}codingStrategy` being separate things.

To clarify my points, though, there are two main things I want to say:

1. I think there is a mismatch here between your goal of representing 
the components of a date (and what `DateComponents` can specifically 
hold) and the goal of ISO 8601
2. I think that there is an inherent problem in parsing `DateComponents` 
due to ambiguity


I think both of these issues can be solved by reading and writing a 
`Date` (formatted however you need it to be) instead of 
`DateComponents`.


To elaborate:

* `DateComponents` is meant to be a container for an _arbitrary_ subset 
of information about a `Date`. A `Date` represents a specific instant in 
time, but `DateComponents` are effectively meaningless without 
additional context. In the examples that you give, it’s possible to 
represent the concepts at hand with `DateComponents`, but in order to 
make those components actionable and meaningful, you still need to 
convert them to `Date`s. Note also that:


* It’s entirely possible to create a `DateComponents` which 
represents a date which does not exist, or a time which does not exist
* Any of these concepts can also be represented by a `Date` instead 
of just components; e.g., an all-day event can be represented by a 
`Date` that represents the beginning of the day (`00:00:00`) and a flag 
that indicates that the time of the event can be ignored, or by a start 
`Date` that represents the start of the day and and end `Date` that 
represents the end of the day


* Unlike `DateComponents`, ISO 8601 strings have some structure to them. 
They cannot represent just a time zone, for instance, or some singular 
components of a date/time (e.g. a month without a year, a day without a 
month and year, a minute without an hour, a second without a minute and 
hour, etc.). I think this is a relatively large conceptual mismatch that 
is worth considering deeply. There are a lot of `DateComponents` 
instances which simply cannot be represented by an ISO 8601 string
* There is also the issue of decoding arbitrary ISO 8601 strings into 
`DateComponents`. `DateComponents`, having no structure at all, have no 
specified format they can expect to decode from, and ISO 8601 does not 
always provide that structure. Consider the following example:


* ISO 8601 allows for date representations by year, month, and day 
(`-MM-DD`), among other forms. But it also allows days to be left 
unspecified (`-MM`), and even months (``)
* Similarly, it allows for a time representations by hour, minute, 
and second (`hh:mm:ss`), but also just hour and minute (`hh:mm`), and 
just hour (`hh`). Importantly, it allows time separators to be omitted 
(`hhmmss`, `hhmm`, `hh`)
* Consider then, attempting to parse the string `"2017"` without 
any context — what `DateComponents` should be read out? Intuitively, 
`2017` looks like a year (``), but it is equally valid to parse as 
the time `20:17` (`hhmm`). Without knowing the expected format, parsing 
is ambiguous


  We cannot promise to parse `DateComponents` in all cases because 
there are many combinations of strings that are just completely 
ambiguous.


* So, to get at the core of this — if there is a specific format that 
you would like to encode to and from, why not do so with a `Date` and a 
`DateFormatter` (or if you need ISO 8601 specifically, 
`ISO8601DateFormatter`)? With a formatter, the format is unambiguous 
because you explicitly provide it, and there is nothing the date can’t 
represent that `DateComponents` can. You can always parse the date and 
pull out only those components that you care about. You also mention 
interoperability with an external JSON source — how is that source 
producing a string/parsing one back? [What I’m getting at here is: 
what is the value of adding a new, potentially risky strategy over 
existing methods that might work just as well, or better?]
* And lastly, if `.iso8601` is not necessarily a good fit for this 
strategy, what separates `.custom` from just overriding `encode(to:)` 
and `init(from:)` and writing the components out in the format that you 
need?


I think answers to these questions can help us push this forward. :)

— Itai

On 5 Sep 2017, at 10:41, Pitiphong Phongpattranont wrote:


Hi Itai,

I think my first pitch email was not clear enough and want to sorry 
for that. I have been working on a calendar app for awhile and 
understand the concept of calendar or date and time programming in 
some level. I didn’t pitch the idea of encoding and decoding `Date` 
value with this `DateComponents{Encoding/Decoding}Strategy`. I still 
agree that `Date` value should be encoded/decoded with the 
`Date{Encoding/Decoding}Strategy`. The 
DateComponents{Encoding/Decoding}Strategy I pitched only apply for 
`DateComponents` value only.


About the 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0184: Unsafe[Mutable][Raw][Buffer]Pointer: add missing methods, adjust existing labels for clarity, and remove deallocation size

2017-09-06 Thread Joe Groff via swift-evolution
> Currently, memory is deallocated by an instance method on 
> UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer API, 
> performing this operation on a buffer pointer requires extracting 
> baseAddress! and count. It is very common for the allocation code above to be 
> immediately followed by:
> 
> defer
> 
> {
> buffer.
> baseAddress?.deallocate(capacity: buffer.count
> )
> }
> 
> This method is extremely problematic because nearly all users, on first 
> seeing the signature of deallocate(capacity:), will naturally conclude from 
> the capacity label that deallocate(capacity:) is equivalent to some kind of 
> realloc()that can only shrink the buffer. However this is not the actual 
> behavior — deallocate(capacity:) actually ignores the capacity argument and 
> just calls free() on self. The current API is not only awkward and 
> suboptimal, it is misleading. You can write perfectly legal Swift code that 
> shouldn’t segfault, but still can, for example
> 
> var ptr = UnsafeMutablePointer.allocate(capacity: 100
> )
> ptr.
> initialize(to: 13, count: 100
> )
> ptr.
> deallocate(capacity: 50) // deallocate the second half of the memory block
> ptr[0] // segmentation fault
> where the first 50 addresses should still be valid if the documentation 
> is to be read literally.

The fact that the Swift runtime currently uses malloc/free is an implementation 
detail. Tracking deallocation size is a very useful optimization for better 
allocator backends, and C++ underwent an ABI break to make it so that sized 
delete can be supported. Maybe we can change the name to 
`deallocate(allocatedCapacity:)` to make it clear that it isn't resizing the 
memory, and/or make the capacity argument optional so that you can pay for the 
overhead of the allocator deriving the size if it's inconvenient for the 
calling code to carry the size around, but we shouldn't remove the 
functionality altogether.

-Joe
___
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] Enums and Source Compatibility

2017-09-06 Thread Brent Royal-Gordon via swift-evolution
> On Sep 5, 2017, at 5:19 PM, Jordan Rose via swift-evolution 
>  wrote:
> 
> I've taken everyone's feedback into consideration and written this up as a 
> proposal: 
> https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md
>  
> .
>  The next step is working on an implementation, but if people have further 
> pre-review comments I'd be happy to hear them.

I disagree with the choice of `exhaustive` and `nonexhaustive`. They are too 
long; the more resilient keyword is longer than the more fragile one (and 
difficult to read!); and they don't match the clang annotation. We may have to 
compromise on one or two of these, but the combination of all three ought to be 
considered disqualifying.

I think `final`/`nonfinal`, `total`/`partial`, `fixed`/? or `permanent`/? are 
all better because they're shorter, although they all have problems with their 
antonyms. `candid`/`coy` or `candid`/`shy` produce the right soft default, but 
are kind of weirdly figurative.

But I don't think a change of keywords will fix everything here. Fundamentally, 
I am not convinced that source compatibility of `switch` statements should be 
weighed so heavily. Based on your survey of Foundation, you suggest that the 
vast majority of imported enums should source-break all switches in Swift 5. 
Why is that acceptable, but making Swift enums source-breaking unacceptable?

I suspect that, in practice, `public` enums tend to fall into two categories:

1. "Data enums" which represent important data that happens to consist 
of a set of alternatives. Outside users will frequently need to switch over 
these, but they are not very likely to evolve or have private cases.

2. "Mode enums" which tweak the behavior of an API. These are very 
likely to evolve or have private cases, but outside users are not very likely 
to need to switch over them.

An example of a data enum would be, as you mentioned, `NSComparisonResult`. 
People really *do* need to be able to test against it, but barring some 
fundamental break in the nature of reality, it will only ever have those three 
cases. So it's fine to make it exhaustive.

An example of a mode enum would be `UIViewAnimationCurve`, which tells UIKit 
how to ease an animation. I chose that example because I actually traced a bug 
just last week to my mistaken impression that this enum had no private cases. I 
was mapping values of this type to their corresponding `UIViewAnimationOptions` 
values; because there were private cases, this was Objective-C code, and I 
didn't include sufficiently aggressive assertions, I ended up reading garbage 
data from memory. But while debugging this, it struck me that this was actually 
*really weird* code. How often do you, as a developer outside UIKit, need to 
interpret the value of a type like `UIViewAnimationCurve`? If the compiler 
suddenly changed the exhaustiveness behavior of `UIViewAnimationCurve`, 
probably less than 1% of apps would even notice—and the affected code would 
probably have latent bugs!

Here's my point: Suddenly treating a mode enum as non-exhaustive is 
*technically* source-breaking, but *people aren't doing things to them that 
would break*. It is only the data enums that would actually experience source 
breakage, and we both seem to agree those are relatively uncommon. So I would 
argue the relatively rare source breaks are acceptable.

Basically, what I would suggest is this:

1. In Swift 4.1, we should add a permanent `exhaustive`* keyword and a 
temporary `@nonexhaustive` attribute to Swift. These are no-ops, or maybe 
`@nonexhaustive` simply silences the "unreachable default case" warning.

2. In Swift 4.2 (or whatever Swift 5's Swift 4 mode is called), we 
should warn about any enum which does not have either `exhaustive` or 
`@nonexhaustive` attached to it, but publishes them as non-exhaustive. `switch` 
requires a `default` case for any non-exhaustive public enum.

3. Swift 5 in Swift 5 mode does the same thing, but does *not* warn 
about the absence of `@nonexhaustive`.

4. Swift 5 importing Objective-C treats enums as non-exhaustive by 
default, unless marked with an attribute.

The dummy keywords in Swift 4.1 ensure that developers can write code that 
works in both a true Swift 4 compiler and a Swift 5 compiler in Swift 4 mode. 
(If we don't like that approach, though, we can bump the versions—give Swift 
4.2 the behavior I described for Swift 4, give Swift 5 the behavior I described 
for 4.2, and plan to give Swift 6 the behavior I described for Swift 5.)

* I'm still not super-happy with `exhaustive`, but since `@nonexhaustive` is 
temporary in this scheme, that at least improves one of the complaints about 
it. I think the keywords I discussed above would still be improvements.

  

Re: [swift-evolution] Enums and Source Compatibility

2017-09-06 Thread Matthew Johnson via swift-evolution
Hi Jordan,

The proposal looks very reasonable to me.

I don’t have too strong an opinion on this topic, but it occurred to me that 
your discussion of `future` left out one possible design approach.  We could 
restrict code in the `future` clause to be `break` or `fatalError()`.  One of 
these is probably what most people would do any way and neither really requires 
testing.  As you noted, it will be possible to have untestable code in a 
`default` clause which is probably what people asking for `future` will have in 
the relevant switch statements.  

Supporting `future` does seem like a nice way to allow libraries to add cases 
without a breaking change while allowing users to opt-in to a breaking change 
when that happens.  It’s a nice compromise that doesn’t appear to harm anyone.  

The main argument against it is: what are the use cases?  I haven’t thought 
enough about it to answer that question.  I would challenge people asking for 
`future` to try to provide some concrete examples, probably referencing enums 
in Apple frameworks.  Maybe if sufficient motivation can be demonstrated we 
should reconsider the more limited form of `future` that doesn’t involve 
untestable code.  On the other hand, `future` is something that can always be 
added later.

As I said, I don’t have a strong opinion about this either way at the moment.

Matthew

> On Sep 5, 2017, at 7:19 PM, Jordan Rose  wrote:
> 
> I've taken everyone's feedback into consideration and written this up as a 
> proposal: 
> https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md
>  
> .
>  The next step is working on an implementation, but if people have further 
> pre-review comments I'd be happy to hear them.
> 
> Jordan
> 
> 
>> On Aug 8, 2017, at 15:27, Jordan Rose > > wrote:
>> 
>> Hi, everyone. Now that Swift 5 is starting up, I'd like to circle back to an 
>> issue that's been around for a while: the source compatibility of enums. 
>> Today, it's an error to switch over an enum without handling all the cases, 
>> but this breaks down in a number of ways:
>> 
>> - A C enum may have "private cases" that aren't defined inside the original 
>> enum declaration, and there's no way to detect these in a switch without 
>> dropping down to the rawValue.
>> - For the same reason, the compiler-synthesized 'init(rawValue:)' on an 
>> imported enum never produces 'nil', because who knows how anyone's using C 
>> enums anyway?
>> - Adding a new case to a Swift enum in a library breaks any client code that 
>> was trying to switch over it.
>> 
>> (This list might sound familiar, and that's because it's from a message of 
>> mine on a thread started by Matthew Johnson back in February called "[Pitch] 
>> consistent public access modifiers". Most of the rest of this email is going 
>> to go the same way, because we still need to make progress here.)
>> 
>> At the same time, we really like our exhaustive switches, especially over 
>> enums we define ourselves. And there's a performance side to this whole 
>> thing too; if all cases of an enum are known, it can be passed around much 
>> more efficiently than if it might suddenly grow a new case containing a 
>> struct with 5000 Strings in it.
>> 
>> 
>> Behavior
>> 
>> I think there's certain behavior that is probably not terribly controversial:
>> 
>> - When enums are imported from Apple frameworks, they should always require 
>> a default case, except for a few exceptions like NSRectEdge. (It's Apple's 
>> job to handle this and get it right, but if we get it wrong with an imported 
>> enum there's still the workaround of dropping down to the raw value.)
>> - When I define Swift enums in the current framework, there's obviously no 
>> compatibility issues; we should allow exhaustive switches.
>> 
>> Everything else falls somewhere in the middle, both for enums defined in 
>> Objective-C:
>> 
>> - If I define an Objective-C enum in the current framework, should it allow 
>> exhaustive switching, because there are no compatibility issues, or not, 
>> because there could still be private cases defined in a .m file?
>> - If there's an Objective-C enum in another framework (that I built locally 
>> with Xcode, Carthage, CocoaPods, SwiftPM, etc.), should it allow exhaustive 
>> switching, because there are no binary compatibility issues, or not, because 
>> there may be source compatibility issues? We'd really like adding a new enum 
>> case to not be a breaking change even at the source level.
>> - If there's an Objective-C enum coming in through a bridging header, should 
>> it allow exhaustive switching, because I might have defined it myself, or 
>> not, because it might be non-modular content I've used the bridging header 
>> to import?
>> 
>> And in Swift:

Re: [swift-evolution] [Concurrency] Reactive streams as building blocks for actors etc.

2017-09-06 Thread Howard Lovatt via swift-evolution
I have put on Github three concurrency libraries (
https://github.com/hlovatt/Concurrency-Utilities):

  1. Atomic - with `get`, `set`, and `update` methods
  2. Future - with `get`, `cancel`, and `status` methods
  3. Reactive Streams - with protocols `Processor`, `Producer`,
`Subscriber`, and `Subscription`, with implementations of `ForEachProducer`
and `ReduceSubscriber`, and with operator `~>` for subscriptions

For those not familiar, Reactive Streams are a standardised form of a type
of actor that have become popular and are available in multiple languages.

Here is Hello World in the Reactive Stream library:

let helloWorldPublisher = ForEachPublisher(sequence: "Hello,
world!".characters)
let helloWorldSubscriber = ReduceSubscriber(into: "") { (result: inout
String, next: Character) in
result.append(next) // Copy the string a character at a time.
}
helloWorldPublisher ~> helloWorldSubscriber // Subscribe
let helloWorldResult = helloWorldSubscriber.get ?? "Failed!" // Wait
for result and check for error

Note how the arguments to `ForEachProducer` and `ReduceSubscriber` mimic
those to similarly named methods in Swifts `Sequence` protocol, how `~>` is
evocative of the process that is occurring, and how future's `get` controls
execution and error reporting.

If anyone experiments with them and provide feedback :), it would be
greatly appreciated.

Thanks,

 -- Howard.

  -- Howard.

On 3 September 2017 at 17:36, Georgios Moschovitis <
george.moschovi...@icloud.com> wrote:

> That would be definitely a great addition to the language. IMO, Dart gets
> this right:
>
> https://www.dartlang.org/tutorials/language/futures
> https://www.dartlang.org/tutorials/language/streams
>
> In general, I would prefer an async story like this:
>
> - support coroutines / generators (yield)
> - use coroutines to implement Future and Stream/Observable
> - optionally provide async/await as syntax sugar for Future/Stream (or
> just reuse yield)
>
> -g.
>
> On 29 Aug 2017, at 4:56 AM, Howard Lovatt via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Many of the currently popular server side frameworks are switching to
> Reactive Streams:
>
> http://en.wikipedia.org/wiki/Reactive_Streams#Adoption
>
> for their underlying communication, including Akka. Reactive Streams are
> also to become builtin to Java, as the Flow class, in version 9.
>
> Would it be wise if Swift 5 also builtin Reactive Stream protocols and
> built its Actor implementation etc. on top of this protocol?
>
>   -- Howard.
>
> More info on Reactive streams:
>
> https://github.com/reactive-streams/reactive-streams-jvm/
> blob/v1.0.1/README.md#specification
>
> http://bryangilbert.com/post/code/scala/akka-reactive-streams/
>
>
> ___
> 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-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] Enums and Source Compatibility

2017-09-06 Thread Rod Brown via swift-evolution

>> I see the logic of this position, but it traps at cases which are unforeseen 
>> unrelated to OS releases. As this proposal notes, there are cases that Apple 
>> uses internal of their frameworks that they consider private may still be 
>> passed through your API.
>> 
>> For example, if there was a new button type, and you enumerated all public 
>> types in your method, but UIKit had a private custom button type, you 
>> couldn’t catch on it, nor would you have any idea that it existed. This 
>> isn’t related to the release cycle timing, but you’re still going to start 
>> crashing despite the fact that you believe you’ve exhaustively handled all 
>> cases.
> 
> Fully understood, though when you are in the middle of some calculation, you 
> are unlikely to do anything by fatalError in the "future" case...
> 
> Imagine e.g. your DateFormatter and you get a new Style in the formatting - 
> what do you do? Fallback on a different one? I personally would simply call 
> fatalError in the future case anyway…

I would tend to agree, which is part of why I think “future” doesn’t make sense 
and should stay in the Alternatives Considered but dropped.

I think the point of extensible/nonexhaustive enums is precisely so we think 
about what are appropriate defaults, otherwise we would just add a “fatalError” 
into the compilation of Switches when no case is caught, and that would be the 
end of this proposal.

In your example, is there a fair default fallback for this behaviour? Just 
choose a reasonable default date style and run with it as an appropriate 
fallback. 95% of the time, there are more reasonable solutions than crashing 
just because your text on screen line breaks weirdly.

Only in occasions where either a) the default case makes no sense, or b) I 
really cannot use a fair default in this calculation, would I fatalError in 
this case. This would seem to me to be far more reasonable than “I can’t hard 
code it, stop the presses, crash everything, blow up the world” for most cases. 
Additionally, it would seem wise for a framework developer to annotate why they 
marked their enum as “nonexhaustive” to give some hint as to a reasonable 
handling of these cases, where it’s not clearly evident.

> 
>> 
>> Also, we need to be thinking bigger than just the Apple Ecosystem. While 
>> Swift started on the Mac and iOS, this is hardly guaranteed, nor are release 
>> timings. Also, just because the dynamic frameworks update at regular 
>> intervals now, doesn’t mean the same will happen on Linux, where a 
>> dynamically linked framework could just update without anyone knowing. Part 
>> of the consideration of ABI stability isn’t just for Apple to ship 
>> frameworks, but for anyone to ship frameworks that are not contained within 
>> the signed bundle of the application. It is short sighted to say “well, this 
>> works for us right now” in my opinion. Part of this discussion is to mature 
>> Swift away from these kinds of assumptions (Apple, Obj-C, etc).

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


Re: [swift-evolution] Enums and Source Compatibility

2017-09-06 Thread Charlie Monroe via swift-evolution

> On Sep 6, 2017, at 8:50 AM, Rod Brown  wrote:
> 
> 
>> On 6 Sep 2017, at 2:31 pm, Charlie Monroe > > wrote:
>>> On Sep 6, 2017, at 5:44 AM, Rod Brown via swift-evolution 
>>> > wrote:
>>> I think what you’re really asking for here is the “future” case mentioned 
>>> in the Alternatives Considered section. I think that Jordan makes a good 
>>> point that this would result in untestable code, which is bad practice. 
>>> While the lack of clear highlighting of non-exhaustive cases is 
>>> undesirable, I think untestable code is a much larger problem here.
>> 
>> This is generally the switch! that I've suggested listed in alternatives as 
>> well - that generally brings current behavior. For a project that is 
>> regularly maintained, I believe that this makes sense given that the enums 
>> are only likely to change once a year at most (with new OS releases)…
> 
> I see the logic of this position, but it traps at cases which are unforeseen 
> unrelated to OS releases. As this proposal notes, there are cases that Apple 
> uses internal of their frameworks that they consider private may still be 
> passed through your API.
> 
> For example, if there was a new button type, and you enumerated all public 
> types in your method, but UIKit had a private custom button type, you 
> couldn’t catch on it, nor would you have any idea that it existed. This isn’t 
> related to the release cycle timing, but you’re still going to start crashing 
> despite the fact that you believe you’ve exhaustively handled all cases.

Fully understood, though when you are in the middle of some calculation, you 
are unlikely to do anything by fatalError in the "future" case...

Imagine e.g. your DateFormatter and you get a new Style in the formatting - 
what do you do? Fallback on a different one? I personally would simply call 
fatalError in the future case anyway...

> 
> Also, we need to be thinking bigger than just the Apple Ecosystem. While 
> Swift started on the Mac and iOS, this is hardly guaranteed, nor are release 
> timings. Also, just because the dynamic frameworks update at regular 
> intervals now, doesn’t mean the same will happen on Linux, where a 
> dynamically linked framework could just update without anyone knowing. Part 
> of the consideration of ABI stability isn’t just for Apple to ship 
> frameworks, but for anyone to ship frameworks that are not contained within 
> the signed bundle of the application. It is short sighted to say “well, this 
> works for us right now” in my opinion. Part of this discussion is to mature 
> Swift away from these kinds of assumptions (Apple, Obj-C, etc).
> 
>> 
>>> 
>>> Either way we need a way to handle forward compatibility for our code when 
>>> cases get added to external frameworks, that much is clear. Swift is broken 
>>> in regards to this, and we need to handle it somehow. I’m hoping you’re not 
>>> suggesting that we just don’t make this change at all. We need this for 
>>> forward compatibility for framework development with Swift.
>>> _
>>> 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] Enums and Source Compatibility

2017-09-06 Thread Rod Brown via swift-evolution


> On 6 Sep 2017, at 4:35 pm, David Hart  wrote:
> 
> Hi Jordan,
> 
> I like this new direction. But I have Rod’s inverse question: have you 
> considered only having the nonexhaustive keyword? Similar to how non-final 
> doesn't exist because its opposite is the default behaviour. That would also 
> free us from searching for a good pair of keywords and only find one good 
> keyword (extensible, expandable, …) which doesn’t contain a negative.

I was thinking the same. If exhaustive is the default, and how Swift has always 
worked, then why have that keyword anyway? I like extensible/expandable but I 
worry the connotation some might come away with that you could add cases 
externally, which is not in scope.

> 
> David.
> 
>> On 6 Sep 2017, at 02:36, Jordan Rose > > wrote:
>> 
>> It's in the "Alternatives Considered" section. :-) That was my desired 
>> design when we started, but feedback convinced me that the break from Swift 
>> 4 mode would be too drastic. The same valid code would have a different 
>> meaning whether you were writing Swift 4 or Swift 5.
>> 
>> Jordan
>> 
>> 
>>> On Sep 5, 2017, at 17:30, Rod Brown >> > wrote:
>>> 
>>> Hi Jordan,
>>> 
>>> I’m not sure how much bearing on this my comment will have.
>>> 
>>> Have you considered having only “exhaustive” as a keyword, and make the 
>>> default non-exhaustive? It seems that “exhaustive" would be the rarer case, 
>>> as it promises a lot more about compatibility (much like there is no such 
>>> thing as “non-final”). Also, non exhaustive seems a massive mouthful 
>>> despite it probably being the correct term.
>>> 
>>> - Rod
>>> 
 On 6 Sep 2017, at 10:19 am, Jordan Rose > wrote:
 
 I've taken everyone's feedback into consideration and written this up as a 
 proposal: 
 https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md
  
 .
  The next step is working on an implementation, but if people have further 
 pre-review comments I'd be happy to hear them.
 
 Jordan
>> 
> 

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


Re: [swift-evolution] Enums and Source Compatibility

2017-09-06 Thread Rod Brown via swift-evolution

> On 6 Sep 2017, at 2:31 pm, Charlie Monroe  wrote:
>> On Sep 6, 2017, at 5:44 AM, Rod Brown via swift-evolution 
>> > wrote:
>> I think what you’re really asking for here is the “future” case mentioned in 
>> the Alternatives Considered section. I think that Jordan makes a good point 
>> that this would result in untestable code, which is bad practice. While the 
>> lack of clear highlighting of non-exhaustive cases is undesirable, I think 
>> untestable code is a much larger problem here.
> 
> This is generally the switch! that I've suggested listed in alternatives as 
> well - that generally brings current behavior. For a project that is 
> regularly maintained, I believe that this makes sense given that the enums 
> are only likely to change once a year at most (with new OS releases)…

I see the logic of this position, but it traps at cases which are unforeseen 
unrelated to OS releases. As this proposal notes, there are cases that Apple 
uses internal of their frameworks that they consider private may still be 
passed through your API.

For example, if there was a new button type, and you enumerated all public 
types in your method, but UIKit had a private custom button type, you couldn’t 
catch on it, nor would you have any idea that it existed. This isn’t related to 
the release cycle timing, but you’re still going to start crashing despite the 
fact that you believe you’ve exhaustively handled all cases.

Also, we need to be thinking bigger than just the Apple Ecosystem. While Swift 
started on the Mac and iOS, this is hardly guaranteed, nor are release timings. 
Also, just because the dynamic frameworks update at regular intervals now, 
doesn’t mean the same will happen on Linux, where a dynamically linked 
framework could just update without anyone knowing. Part of the consideration 
of ABI stability isn’t just for Apple to ship frameworks, but for anyone to 
ship frameworks that are not contained within the signed bundle of the 
application. It is short sighted to say “well, this works for us right now” in 
my opinion. Part of this discussion is to mature Swift away from these kinds of 
assumptions (Apple, Obj-C, etc).

> 
>> 
>> Either way we need a way to handle forward compatibility for our code when 
>> cases get added to external frameworks, that much is clear. Swift is broken 
>> in regards to this, and we need to handle it somehow. I’m hoping you’re not 
>> suggesting that we just don’t make this change at all. We need this for 
>> forward compatibility for framework development with Swift.
>> _
>> 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] Enums and Source Compatibility

2017-09-06 Thread David Hart via swift-evolution
Hi Jordan,

I like this new direction. But I have Rod’s inverse question: have you 
considered only having the nonexhaustive keyword? Similar to how non-final 
doesn't exist because its opposite is the default behaviour. That would also 
free us from searching for a good pair of keywords and only find one good 
keyword (extensible, expandable, …) which doesn’t contain a negative.

David.

> On 6 Sep 2017, at 02:36, Jordan Rose  wrote:
> 
> It's in the "Alternatives Considered" section. :-) That was my desired design 
> when we started, but feedback convinced me that the break from Swift 4 mode 
> would be too drastic. The same valid code would have a different meaning 
> whether you were writing Swift 4 or Swift 5.
> 
> Jordan
> 
> 
>> On Sep 5, 2017, at 17:30, Rod Brown > > wrote:
>> 
>> Hi Jordan,
>> 
>> I’m not sure how much bearing on this my comment will have.
>> 
>> Have you considered having only “exhaustive” as a keyword, and make the 
>> default non-exhaustive? It seems that “exhaustive" would be the rarer case, 
>> as it promises a lot more about compatibility (much like there is no such 
>> thing as “non-final”). Also, non exhaustive seems a massive mouthful despite 
>> it probably being the correct term.
>> 
>> - Rod
>> 
>>> On 6 Sep 2017, at 10:19 am, Jordan Rose >> > wrote:
>>> 
>>> I've taken everyone's feedback into consideration and written this up as a 
>>> proposal: 
>>> https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md
>>>  
>>> .
>>>  The next step is working on an implementation, but if people have further 
>>> pre-review comments I'd be happy to hear them.
>>> 
>>> Jordan
> 

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