Re: [swift-evolution] Enums and Source Compatibility

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


> On 8 Sep 2017, at 2:55 am, Vladimir.S  wrote:
> 
> On 07.09.2017 18:23, Rod Brown wrote:
>> 
>> This was discussed earlier. As I mentioned, we should be realistic: it’s 
>> rarely a
>> truly fatal error when you get an unknown enum. Unless you really can’t find 
>> a
>> reasonable default, then there are almost always reasonable logical ways to 
>> handle
>> it (perhaps just breaking out?). And in cases where you really need to 
>> handle each
>> case, this would (almost?) always be an exhaustive enum. I can’t even 
>> imagine the
>> case where it would be so critical you couldn’t handle it with reasonable 
>> control
>> flow. There are always solutions like returning early, breaking out, default
>> details. I see Swift code littered with fatalError() not because its needed, 
>> but
>> because the developer often didn’t care enough to think it through.
> 
> Thank you for replies, Rod!
> 
> Thinking about this, if "in cases where you really need to handle each case, 
> this would (almost?) always be an exhaustive enum", then I tend to agree with 
> you.
> 
> So, currently my point of view is that we need to move the way suggested by 
> Chris, when we need to mark public 'closed' enum, so 'open' is default, and 
> with warning for first time and with error in next version of Swift for 
> switches on 'open' enum without 'default' case. Not the way described in the 
> proposal itself.

Agreed, though we shouldn't use “open/closed” as discussed in the proposal 
draft.

> 
>> “Future” might be a decent idea, but I think we’re overcomplicating it. Just 
>> use
>> “default” as we always have? “Future” as a word doesn’t seem to apply, as I 
>> have
>> mentioned earlier: there are cases where your framework has a private case 
>> on an
>> enum. This isn’t necessarily a future case - it could be “current”. If we 
>> were to
>> do this, it would make more sense to call this case word “other” instead. 
>> Again,
>> though, we’re adding complexity to a switch for a very rare case and a 
>> little bit
>> of developer convenience in that case.
> 
> Well... yes, seems like this. I didn't get current but private cases into 
> account. But I was more focused on Swift's enums, not on C's.
> 
> What do you(and others) think about such idea: if we have an exhaustive 
> switch on _open_ enum _without_ 'default' case, and there are *no* more known 
> available cases for this enum currently - compiler generates error/warning 
> like "you have exhaustive switch but this is an open enum new cases can be 
> added later, so add 'default' case to process them". But, if such(exhaustive 
> on _open_ enum _without_ 'default' case) switch contains not all known cases, 
> warning/error will be different like "you have not exhaustive switch on open 
> enum, add 'default' case to process all others and future cases”.

I agree. This is going to be a confusing case, especially when transitioning. 
Stating clearly why they need a default clause despite the “appearance” of 
exhaustively handling all cases should be part of the error wording.

> 
> I believe that with this accepted proposal, if you ever will need to keep 
> switch exhaustive on 'open' enum, support this code, this will be a nightmare 
> without at least such warnings, when you can comment the 'default' case in 
> switch and check(by warning/error message) if you processed all the cases or 
> missed some. Otherwise, the alternative, is to manually check one-by-one what 
> you have in your switch and what cases are in enum(in case you have new 
> version of enum's module).
> 
> Vladimir.
___
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-07 Thread Andrew Trick via swift-evolution

> On Sep 7, 2017, at 5:56 PM, Jordan Rose  wrote:
> 
> 
> 
>> On Sep 7, 2017, at 17:46, Andrew Trick > > wrote:
>> 
>> 
>>> On Sep 7, 2017, at 5:40 PM, Joe Groff >> > wrote:
>>> 
>>> 
 
> But then given that, I don't understand why the 'capacity' parameter is 
> necessary. Under what circumstances would it actually be faster than 
> "just" calling malloc_size?
 
 The runtime may need to hash the address or traverse a lookup table to 
 find out which allocation pool the block resides in. Now, that’s only if 
 some platform ditches full malloc compatibility for user allocations, so 
 I’m not sure how realistic it is.
>>> 
>>> It seems to me that you could still provide malloc/free compatibility with 
>>> a zone that had to do a relatively expensive traversal on free() to recover 
>>> the pool the memory came from; malloc/free just wouldn't be the ideal 
>>> interface in that situation.
>>> 
>>> -Joe
>> 
>> Joe is right, and I just learned how amazing malloc zones are.
> 
> As long as you support multiple allocators (or hide everything behind 
> malloc/free), there's already a cost of malloc_zone_from_ptr or equivalent. 
> Without seeing a concrete use case, I wouldn't want to stay with the 
> harder-to-use API in UnsafePointer itself. It might be a feature of a 
> particular allocator that you need to keep the capacity around, but it isn't 
> something generally true about Swift's memory model, and probably never will 
> be.
> 
> (Interesting reference points: malloc/malloc.h and the implementation of 
> malloc on macOS 
> 
>  - search for "free(void *ptr)".)
> 
> Jordan

I’m primarily arguing from the point of view that UnsafeBufferPointer should 
pass it’s deallocation capacity and should be implementable in terms of 
UnsafePointer. But I’m fine hiding the capacity argument from the public API 
for now. We know what the proposal author wants to do, so unless Joe still 
feels strongly, we could accept the proposal as-is, put the API decision to 
rest and focus on better documentation and and assertions.

-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-07 Thread Andrew Trick via swift-evolution

> On Sep 7, 2017, at 5:37 PM, Joe Groff  wrote:
>> 
>> 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.
> 
> Would it be sufficient to assert that malloc_good_size(passedCapacity) == 
> malloc_size(base) ? It wouldn't be perfect but could still catch a lot of 
> misuses.


That theory does hold up for a million random values, but I don’t know if we 
can rely on malloc_size never being larger than roundUp(sz, 16). Greg?

-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-07 Thread Jordan Rose via swift-evolution


> On Sep 7, 2017, at 17:46, Andrew Trick  wrote:
> 
> 
>> On Sep 7, 2017, at 5:40 PM, Joe Groff  wrote:
>> 
>> 
>>> 
 But then given that, I don't understand why the 'capacity' parameter is 
 necessary. Under what circumstances would it actually be faster than 
 "just" calling malloc_size?
>>> 
>>> The runtime may need to hash the address or traverse a lookup table to find 
>>> out which allocation pool the block resides in. Now, that’s only if some 
>>> platform ditches full malloc compatibility for user allocations, so I’m not 
>>> sure how realistic it is.
>> 
>> It seems to me that you could still provide malloc/free compatibility with a 
>> zone that had to do a relatively expensive traversal on free() to recover 
>> the pool the memory came from; malloc/free just wouldn't be the ideal 
>> interface in that situation.
>> 
>> -Joe
> 
> Joe is right, and I just learned how amazing malloc zones are.

As long as you support multiple allocators (or hide everything behind 
malloc/free), there's already a cost of malloc_zone_from_ptr or equivalent. 
Without seeing a concrete use case, I wouldn't want to stay with the 
harder-to-use API in UnsafePointer itself. It might be a feature of a 
particular allocator that you need to keep the capacity around, but it isn't 
something generally true about Swift's memory model, and probably never will be.

(Interesting reference points: malloc/malloc.h and the implementation of malloc 
on macOS 

 - search for "free(void *ptr)".)

Jordan

___
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-07 Thread Andrew Trick via swift-evolution

> On Sep 7, 2017, at 5:40 PM, Joe Groff  wrote:
> 
> 
>> 
>>> But then given that, I don't understand why the 'capacity' parameter is 
>>> necessary. Under what circumstances would it actually be faster than "just" 
>>> calling malloc_size?
>> 
>> The runtime may need to hash the address or traverse a lookup table to find 
>> out which allocation pool the block resides in. Now, that’s only if some 
>> platform ditches full malloc compatibility for user allocations, so I’m not 
>> sure how realistic it is.
> 
> It seems to me that you could still provide malloc/free compatibility with a 
> zone that had to do a relatively expensive traversal on free() to recover the 
> pool the memory came from; malloc/free just wouldn't be the ideal interface 
> in that situation.
> 
> -Joe

Joe is right, and I just learned how amazing malloc zones are.
-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-07 Thread Joe Groff via swift-evolution

> On Sep 7, 2017, at 5:34 PM, Andrew Trick  wrote:
> 
>> 
>> On Sep 7, 2017, at 5:17 PM, Jordan Rose  wrote:
>> 
>> 
>> 
>>> On Sep 7, 2017, at 17:09, Andrew Trick  wrote:
>>> 
>>> 
 On Sep 7, 2017, at 2:29 PM, Jordan Rose  wrote:
 
> 
> We do want the Swift memory model to be consistent with the reality that 
> on most platforms, we need the runtime to track block size.
 
 I don't know where this comes from. If you don't need to be 
 malloc-compatible, you don't strictly "need" this information. (It would 
 break tools like 'leaks', though.)
>>> 
>>> There are two distinct but related issues (1) malloc compatibility (2) 
>>> malloc/free like functionality. I know developers sometimes expect or want 
>>> #2. Realistically, we will always want the runtime to provide malloc_size, 
>>> even if it’s not super fast, so we’re not giving up anything long term by 
>>> providing #2. The fact the #1 is also a likely goal on major platforms just 
>>> reinforces that position.
>> 
>> I don't understand why "realistically, we will always want the runtime to 
>> provide malloc_size". Could you explain why?
> 
> The standard library already makes good use of malloc_size. More to the 
> point, I think “realistically" it needs to be possible to write tools for 
> memory analysis and debugging. I meant “always” in the temporal sense. I 
> don’t think all memory needs this, only memory that is directly under the 
> user’s control.
> 
>> But then given that, I don't understand why the 'capacity' parameter is 
>> necessary. Under what circumstances would it actually be faster than "just" 
>> calling malloc_size?
> 
> The runtime may need to hash the address or traverse a lookup table to find 
> out which allocation pool the block resides in. Now, that’s only if some 
> platform ditches full malloc compatibility for user allocations, so I’m not 
> sure how realistic it is.

It seems to me that you could still provide malloc/free compatibility with a 
zone that had to do a relatively expensive traversal on free() to recover the 
pool the memory came from; malloc/free just wouldn't be the ideal interface in 
that situation.

-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-07 Thread Joe Groff via swift-evolution

> On Sep 6, 2017, at 5:31 PM, Andrew Trick  wrote:
> 
> 
>> 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.

Would it be sufficient to assert that malloc_good_size(passedCapacity) == 
malloc_size(base) ? It wouldn't be perfect but could still catch a lot of 
misuses.

-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-07 Thread Andrew Trick via swift-evolution

> On Sep 7, 2017, at 5:17 PM, Jordan Rose  wrote:
> 
> 
> 
>> On Sep 7, 2017, at 17:09, Andrew Trick > > wrote:
>> 
>> 
>>> On Sep 7, 2017, at 2:29 PM, Jordan Rose >> > wrote:
>>> 
 
 We do want the Swift memory model to be consistent with the reality that 
 on most platforms, we need the runtime to track block size.
>>> 
>>> I don't know where this comes from. If you don't need to be 
>>> malloc-compatible, you don't strictly "need" this information. (It would 
>>> break tools like 'leaks', though.)
>> 
>> There are two distinct but related issues (1) malloc compatibility (2) 
>> malloc/free like functionality. I know developers sometimes expect or want 
>> #2. Realistically, we will always want the runtime to provide malloc_size, 
>> even if it’s not super fast, so we’re not giving up anything long term by 
>> providing #2. The fact the #1 is also a likely goal on major platforms just 
>> reinforces that position.
> 
> I don't understand why "realistically, we will always want the runtime to 
> provide malloc_size". Could you explain why?

The standard library already makes good use of malloc_size. More to the point, 
I think “realistically" it needs to be possible to write tools for memory 
analysis and debugging. I meant “always” in the temporal sense. I don’t think 
all memory needs this, only memory that is directly under the user’s control.

> But then given that, I don't understand why the 'capacity' parameter is 
> necessary. Under what circumstances would it actually be faster than "just" 
> calling malloc_size?

The runtime may need to hash the address or traverse a lookup table to find out 
which allocation pool the block resides in. Now, that’s only if some platform 
ditches full malloc compatibility for user allocations, so I’m not sure how 
realistic it is.

-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-07 Thread Jordan Rose via swift-evolution


> On Sep 7, 2017, at 17:09, Andrew Trick  wrote:
> 
> 
>> On Sep 7, 2017, at 2:29 PM, Jordan Rose > > wrote:
>> 
>>> 
>>> We do want the Swift memory model to be consistent with the reality that on 
>>> most platforms, we need the runtime to track block size.
>> 
>> I don't know where this comes from. If you don't need to be 
>> malloc-compatible, you don't strictly "need" this information. (It would 
>> break tools like 'leaks', though.)
> 
> There are two distinct but related issues (1) malloc compatibility (2) 
> malloc/free like functionality. I know developers sometimes expect or want 
> #2. Realistically, we will always want the runtime to provide malloc_size, 
> even if it’s not super fast, so we’re not giving up anything long term by 
> providing #2. The fact the #1 is also a likely goal on major platforms just 
> reinforces that position.

I don't understand why "realistically, we will always want the runtime to 
provide malloc_size". Could you explain why?

But then given that, I don't understand why the 'capacity' parameter is 
necessary. Under what circumstances would it actually be faster than "just" 
calling malloc_size?

Jordan

> 
>>> If our memory model states that the runtime tracks capacity of manually 
>>> allocated blocks, then the deallocation capacity should be optional to 
>>> reflect that.
>>> 
>>> Still waiting to hear any arguments that something about that memory model 
>>> is bad.
>> 
>> I don't see an advantage to having the parameter if we're going to promise 
>> that it's always present. It is additional complexity for very little win in 
>> a generic interface. If someone wants to write a special allocation entry 
>> point that actually makes use of this, they can do so, but it shouldn't live 
>> on UnsafePointer.
>> 
>> (We also have nothing that prevents you from doing `(ptr+1).deallocate()`, 
>> but, well, "unsafe".)
> 
> I also don’t see any usability advantage in providing the extra argument for 
> anyone directly using UnsafePointer, which is why I initially objected to Joe 
> Groff’s request. Then I realized I care less about usability and potential 
> confusion than I care that UnsafePointer API can be viewed is a specification 
> of the Swift's basic memory management functionality. We want to communicate 
> that data structures doing manual allocation/deallocation should provide the 
> allocated capacity during deallocation if it is available. The runtime could 
> make good use of that. In particular, I want UnsafeBufferPointer’s 
> deallocate() to be able to call UnsafePointer.deallocate(allocatedCapacity: 
> buffer.count), rather than implementing it in terms of Builtins.
> 
> Incidentally, FWIW, I think compiled code should continue to be required to 
> pass the capacity to the runtime during deallocation. That way, any changes 
> in the runtime implementation of deallocation, particularly extra address 
> checks, are isolated to the standard library.

___
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-07 Thread Andrew Trick via swift-evolution

> On Sep 7, 2017, at 2:29 PM, Jordan Rose  wrote:
> 
>> 
>> We do want the Swift memory model to be consistent with the reality that on 
>> most platforms, we need the runtime to track block size.
> 
> I don't know where this comes from. If you don't need to be 
> malloc-compatible, you don't strictly "need" this information. (It would 
> break tools like 'leaks', though.)

There are two distinct but related issues (1) malloc compatibility (2) 
malloc/free like functionality. I know developers sometimes expect or want #2. 
Realistically, we will always want the runtime to provide malloc_size, even if 
it’s not super fast, so we’re not giving up anything long term by providing #2. 
The fact the #1 is also a likely goal on major platforms just reinforces that 
position.

>> If our memory model states that the runtime tracks capacity of manually 
>> allocated blocks, then the deallocation capacity should be optional to 
>> reflect that.
>> 
>> Still waiting to hear any arguments that something about that memory model 
>> is bad.
> 
> I don't see an advantage to having the parameter if we're going to promise 
> that it's always present. It is additional complexity for very little win in 
> a generic interface. If someone wants to write a special allocation entry 
> point that actually makes use of this, they can do so, but it shouldn't live 
> on UnsafePointer.
> 
> (We also have nothing that prevents you from doing `(ptr+1).deallocate()`, 
> but, well, "unsafe".)

I also don’t see any usability advantage in providing the extra argument for 
anyone directly using UnsafePointer, which is why I initially objected to Joe 
Groff’s request. Then I realized I care less about usability and potential 
confusion than I care that UnsafePointer API can be viewed is a specification 
of the Swift's basic memory management functionality. We want to communicate 
that data structures doing manual allocation/deallocation should provide the 
allocated capacity during deallocation if it is available. The runtime could 
make good use of that. In particular, I want UnsafeBufferPointer’s deallocate() 
to be able to call UnsafePointer.deallocate(allocatedCapacity: buffer.count), 
rather than implementing it in terms of Builtins.

Incidentally, FWIW, I think compiled code should continue to be required to 
pass the capacity to the runtime during deallocation. That way, any changes in 
the runtime implementation of deallocation, particularly extra address checks, 
are isolated to the standard library.

-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-07 Thread Taylor Swift via swift-evolution


> On Sep 7, 2017, at 3:10 PM, Joe Groff  wrote:
> 
> 
>> On Sep 7, 2017, at 11:57 AM, Taylor Swift  wrote:
>> 
>> 
>> 
>> On Thu, Sep 7, 2017 at 1:39 PM, Jordan Rose  wrote:
>>> 
>>> 
> On Sep 7, 2017, at 10:31, Andrew Trick via swift-evolution 
>  wrote:
> 
> 
> On Sep 7, 2017, at 8:06 AM, Taylor Swift  wrote:
> 
> I don’t see any source for this claim in the documentation, or the source 
> code. As far as I can tell the expected behavior is that partial 
> deallocation “should” work.
> 
>> On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff  wrote:
>> 
>> The segfaulting example is an incorrect usage. The only valid parameters 
>> to deallocate(capacity:) are the base address of an allocation, and the 
>> original capacity passed into allocate(); it has never been intended to 
>> support partial deallocation of allocated blocks. It seems to me like 
>> this proposal is based on a misunderstanding of how the API works. The 
>> documentation and/or name should be clarified.
>> 
>> -Joe
>> 
>> > “fixing” this bug will cause programs that once operated on previously 
>> > valid assumptions of “free()” semantics to behave differently, without 
>> > any warnings ever being generated. Conversely incorrect code will 
>> > suddenly become “correct” though this is less of a problem.
>> >
>> >> 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
 
 This discussion needs to be grounded by reiterating role of the API. 
 UnsafePointer specifies the memory model without extraneous functionality 
 or convenience.
 
 The UnsafePointer.deallocate() API *is not*:
 
 - a common, expected, or encouraged way to deallocate
 
 - the simplest, safest, or most convenient way to deallocate
 
 - necessarilly the most optimal path for deallocation
>>> 
>>> I don't think this is correct. UnsafePointer.deallocate is the API you must 
>>> use to deallocate memory allocated with UnsafePointer.allocate. My question 
>>> is whether it's acceptable to break all the people who didn't know this and 
>>> are using it to deallocate memory allocated with malloc or new on Apple 
>>> platforms. It sounds like the answer to that is "no, we want to be 
>>> malloc-compatible", and therefore the 'capacity' parameter isn't currently 
>>> serving a purpose today. We will always need to check if the memory is 
>>> actually in the Swift pool before even believing the 'capacity' parameter.
>>> 
>>> (It is definitely true that the intent was for this to be the allocation 
>>> capacity, and I'm surprised you interpreted it as supporting partial 
>>> deallocation. But we probably can't fix that at this point.)
>>> 
>>> Jordan
>>> 
 
 There is only one decision that needs to be made here. Does the Swift 
 runtime track allocation size for manually allocated blocks? I think the 
 answer should be "yes", or at least haven't heard a strong argument 
 against it. UnsafePointer.deallocate() needs to direcly reflect that model 
 by making `allocatedCapacity` an *optional* argument.
 
 Discussion about whether this API is unsafe, misleading, suboptimal or 
 incorrectly implemented are secondary. Those are all deficiencies in the 
 current documentation, current implementation, and availability of 
 higher-level APIs.
 
 Note that yesterday I argued that an optional argument wasn't worth the 
 potential for confusion. That's true from a practical perspective, but I 
 had lost sight of need to clearly specify the memory model. We want the 
 Swift runtime to both have the functionality for tracking block size and 
 also allow user code to track it more efficiently. Both those intentions 
 need to be reflected in this API.
 
 -Andy
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>> 
>> I mean I would have thought it’s reasonable to expect that if the method 
>> asks for a capacity parameter, it will actually use it 
> 
> It will.
> 
> -Joe

but it doesn’t___
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-07 Thread Jordan Rose via swift-evolution


> On Sep 7, 2017, at 13:02, Andrew Trick  wrote:
> 
> 
>> On Sep 7, 2017, at 11:39 AM, Jordan Rose > > wrote:
>> 
>>> This discussion needs to be grounded by reiterating role of the API. 
>>> UnsafePointer specifies the memory model without extraneous functionality 
>>> or convenience.
>>> 
>>> The UnsafePointer.deallocate() API *is not*:
>>> 
>>> - a common, expected, or encouraged way to deallocate
>>> 
>>> - the simplest, safest, or most convenient way to deallocate
>>> 
>>> - necessarilly the most optimal path for deallocation
>> 
>> I don't think this is correct. UnsafePointer.deallocate is the API you must 
>> use to deallocate memory allocated with UnsafePointer.allocate.
> 
> No, all of Swift’s APIs for manual allocation/deallocation need to be 
> compatible. UnsafeBufferPointer is highly preferable to UnsafePointer today. 
> In the future we will have a safe API for manual allocation, still based on 
> the underlying model specified by UnsafePointer.
> 
> UnsafePointer.allocate() is *not*
> 
> - a common, expected, or encouraged way to allocate
> 
> - the simplest, safest, or most convenient way to allocate
> 
> - necessarily the most optimal path for allocation
> 
> Even though high-level APIs are specified in terms of this model, they can be 
> implemented via their own fast-paths.

That's all fine; I'll rephrase to say that if I allocated with 
UnsafeMutablePointer.allocate, I'll probably deallocate with 
Unsafe[Mutable]Pointer.deallocate. They're not independent.


> 
>>  Myquestion is whether it's acceptable to break all the people who didn't 
>> know this and are using it to deallocate memory allocated with malloc or new 
>> on Apple platforms. It sounds like the answer to that is "no, we want to be 
>> malloc-compatible", and therefore the 'capacity' parameter isn't currently 
>> serving a purpose today. We will always need to check if the memory is 
>> actually in the Swift pool before even believing the 'capacity' parameter.
> 
> We don’t need to claim that manually allocated Swift memory is malloc 
> compatible on every platform that happens to have malloc.

I suspect that we cannot revoke that from existing platforms.

> We do want the Swift memory model to be consistent with the reality that on 
> most platforms, we need the runtime to track block size.

I don't know where this comes from. If you don't need to be malloc-compatible, 
you don't strictly "need" this information. (It would break tools like 'leaks', 
though.)


> 
>> (It is definitely true that the intent was for this to be the allocation 
>> capacity, and I'm surprised you interpreted it as supporting partial 
>> deallocation. But we probably can't fix that at this point.)
> 
> I never misinterpreted the meaning of the API, but apparently multiple people 
> on the evolution list did. Regardless, that is not valid reason for changing 
> the API. It’s only a valid reason for improving documentation and encouraging 
> the use of safer APIs.

That "you" was addressed to Kelvin (Taylor), but if we really think people are 
mixing malloc/free and UnsafePointer APIs today, we should not break that on 
our existing platforms. It's unfortunate, but we're on Swift 4 already. It is 
not worth the cost.


> If our memory model states that the runtime tracks capacity of manually 
> allocated blocks, then the deallocation capacity should be optional to 
> reflect that.
> 
> Still waiting to hear any arguments that something about that memory model is 
> bad.

I don't see an advantage to having the parameter if we're going to promise that 
it's always present. It is additional complexity for very little win in a 
generic interface. If someone wants to write a special allocation entry point 
that actually makes use of this, they can do so, but it shouldn't live on 
UnsafePointer.

(We also have nothing that prevents you from doing `(ptr+1).deallocate()`, but, 
well, "unsafe".)

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


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

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


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

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

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

2017-09-07 Thread Haravikk via swift-evolution

> On 7 Sep 2017, at 19:36, Tony Allevato  wrote:
> 
> 
> 
> On Thu, Sep 7, 2017 at 11:18 AM Haravikk via swift-evolution 
> > wrote:
> 
>> On 7 Sep 2017, at 18:53, Tony Allevato via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>> On Thu, Sep 7, 2017 at 10:39 AM Gwendal Roué > > wrote:
>>> Le 7 sept. 2017 à 14:45, Tony Allevato >> > a écrit :
>>> 
>>> Right, let's make sure we're talking about the right thing here. Gwendal, 
>>> your issue isn't with synthesis in the form of Codable or the new additions 
>>> to Equatable/Hashable which are opt-in-by-conformance, it's with the 
>>> specific case of raw value enums or enums without associated values where 
>>> the synthesis is implicit with no way to opt-out. That's a big difference.
>> 
>> Yes.
>> 
>>> I can definitely see the latter being an issue if it were more widespread, 
>>> and I'd be supportive of those enums being required to declare their 
>>> conformance for consistency (though it would be source breaking).
>> 
>> Yes, unfortunately.
>> 
>> 
>>> However, I still haven't seen a real issue that has come up because of the 
>>> distinction being drawn here between default implementations vs. 
>>> implementations that can access other parts of the concrete type. It sounds 
>>> like this discussion is trying to protect against a hypothetical problem 
>>> that hasn't happened yet and may not happen; it would be helpful to show 
>>> some motivating real-world cases where this is indeed a severe problem.
>> 
>> Yes. I'm not talking about implementation itself. I know this has been the 
>> main topic until I have tried to bring in the topic of the consequences of 
>> non-avoidable synthesis (extra methods that may conflict with userland 
>> methods).
>> 
>> If you ask me for a real-world case, then I think I gave one. Let me 
>> rephrase it:
>> 
>> it's impossible to define a value-backed enum without getting free Equatable 
>> conformance. This free conformance is sometimes unwanted, and I gave the 
>> example of DSLs. Now this problem is not *severe*. It's more a blind spot in 
>> the language, and finally just an unwanted side-effect of a compiler 
>> convenience,
>> 
>> Again, this is not the issue that Haravikk is describing in this thread.
>> 
>> I'll clarify—your issue is specifically with the fact that enums with raw 
>> values and enums without associated values receive Equatable even without 
>> explicitly conforming to it, and therefore users have no way of opting out 
>> of it. This predates SE-0185, and I didn't propose making any changes to the 
>> conformance of those enums for source compatibility reasons, though I 
>> wouldn't be opposed to it because it makes them consistent across the board.
>> 
>> Haravikk's argument is about synthesized conformances like Codable and 
>> Equatable/Hashable in SE-0185, where the user must explicitly conform the 
>> type to those protocols. His claim is that that act of opting in is not 
>> sufficient and that it is still dangerous if those synthesized conformances 
>> can access members that are not also declared in the protocol. That's a 
>> completely separate issue to yours, and one that I hope he'll present more 
>> evidence of. Right now, requiring that you not only explicitly conform to 
>> the protocol but also explicitly request the synthesis feels like a solution 
>> without an actual problem, and is a situation we already have today with 
>> default method implementations.
> 
> The simplest real-world case is easy:
> 
>   struct Foo { var data:String }
>   extension Foo : Equatable {} // This currently produces an error, in 
> future it will not
> 
> 
> Why is this a problem? It's no different than if someone extended Foo to 
> conform to a protocol with a default implementation that was written in code.

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

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

These things are two very different beasts.

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

Re: [swift-evolution] [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-07 Thread Joe Groff via swift-evolution

> On Sep 7, 2017, at 11:55 AM, Taylor Swift  wrote:
> 
> 
> 
> On Thu, Sep 7, 2017 at 12:31 PM, Andrew Trick  > wrote:
> 
>> On Sep 7, 2017, at 8:06 AM, Taylor Swift > > wrote:
>> 
>> I don’t see any source for this claim in the documentation 
>> ,
>>  or the source code 
>> .
>>  As far as I can tell the expected behavior is that partial deallocation 
>> “should” work.
>> 
>> On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff > > wrote:
>> 
>> The segfaulting example is an incorrect usage. The only valid parameters to 
>> deallocate(capacity:) are the base address of an allocation, and the 
>> original capacity passed into allocate(); it has never been intended to 
>> support partial deallocation of allocated blocks. It seems to me like this 
>> proposal is based on a misunderstanding of how the API works. The 
>> documentation and/or name should be clarified.
>> 
>> -Joe
>> 
>> > “fixing” this bug will cause programs that once operated on previously 
>> > valid assumptions of “free()” semantics to behave differently, without any 
>> > warnings ever being generated. Conversely incorrect code will suddenly 
>> > become “correct” though this is less of a problem.
>> >
>> >> 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
> 
> This discussion needs to be grounded by reiterating role of the API. 
> UnsafePointer specifies the memory model without extraneous functionality or 
> convenience.
> 
> The UnsafePointer.deallocate() API *is not*:
> 
> - a common, expected, or encouraged way to deallocate
> 
> - the simplest, safest, or most convenient way to deallocate
> 
> - necessarilly the most optimal path for deallocation
> 
> There is only one decision that needs to be made here. Does the Swift runtime 
> track allocation size for manually allocated blocks? I think the answer 
> should be "yes", or at least haven't heard a strong argument against it. 
> UnsafePointer.deallocate() needs to direcly reflect that model by making 
> `allocatedCapacity` an *optional* argument.
> 
> Discussion about whether this API is unsafe, misleading, suboptimal or 
> incorrectly implemented are secondary. Those are all deficiencies in the 
> current documentation, current implementation, and availability of 
> higher-level APIs.
> 
> Note that yesterday I argued that an optional argument wasn't worth the 
> potential for confusion. That's true from a practical perspective, but I had 
> lost sight of need to clearly specify the memory model. We want the Swift 
> runtime to both have the functionality for tracking block size and also allow 
> user code to track it more efficiently. Both those intentions need to be 
> reflected in this API.
> 
> -Andy
> 
> idk how the swift heap is planned to be implemented, but why is passing the 
> capacity to deallocate considered the fast path anyway? i thought the block 
> size was stored in a header right before the block pointer

It doesn't have to be. When all allocation and deallocation calls carry 
matching capacity values, then that overhead can be eliminated when allocating 
out of a heterogeneous heap. Optimized allocators also generally have 
per-thread pools for common allocation sizes, and if you have the capacity 
value on hand, it can be quickly matched to the right pool size, and constant 
allocation sizes can potentially be recognized by the compiler and turned into 
allocator calls that directly allocate out of a specific pool.

-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-07 Thread Joe Groff via swift-evolution

> On Sep 7, 2017, at 11:57 AM, Taylor Swift  wrote:
> 
> 
> 
> On Thu, Sep 7, 2017 at 1:39 PM, Jordan Rose  > wrote:
> 
> 
>> On Sep 7, 2017, at 10:31, Andrew Trick via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Sep 7, 2017, at 8:06 AM, Taylor Swift >> > wrote:
>>> 
>>> I don’t see any source for this claim in the documentation 
>>> ,
>>>  or the source code 
>>> .
>>>  As far as I can tell the expected behavior is that partial deallocation 
>>> “should” work.
>>> 
>>> On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff >> > wrote:
>>> 
>>> The segfaulting example is an incorrect usage. The only valid parameters to 
>>> deallocate(capacity:) are the base address of an allocation, and the 
>>> original capacity passed into allocate(); it has never been intended to 
>>> support partial deallocation of allocated blocks. It seems to me like this 
>>> proposal is based on a misunderstanding of how the API works. The 
>>> documentation and/or name should be clarified.
>>> 
>>> -Joe
>>> 
>>> > “fixing” this bug will cause programs that once operated on previously 
>>> > valid assumptions of “free()” semantics to behave differently, without 
>>> > any warnings ever being generated. Conversely incorrect code will 
>>> > suddenly become “correct” though this is less of a problem.
>>> >
>>> >> 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
>> 
>> This discussion needs to be grounded by reiterating role of the API. 
>> UnsafePointer specifies the memory model without extraneous functionality or 
>> convenience.
>> 
>> The UnsafePointer.deallocate() API *is not*:
>> 
>> - a common, expected, or encouraged way to deallocate
>> 
>> - the simplest, safest, or most convenient way to deallocate
>> 
>> - necessarilly the most optimal path for deallocation
> 
> I don't think this is correct. UnsafePointer.deallocate is the API you must 
> use to deallocate memory allocated with UnsafePointer.allocate. My question 
> is whether it's acceptable to break all the people who didn't know this and 
> are using it to deallocate memory allocated with malloc or new on Apple 
> platforms. It sounds like the answer to that is "no, we want to be 
> malloc-compatible", and therefore the 'capacity' parameter isn't currently 
> serving a purpose today. We will always need to check if the memory is 
> actually in the Swift pool before even believing the 'capacity' parameter.
> 
> (It is definitely true that the intent was for this to be the allocation 
> capacity, and I'm surprised you interpreted it as supporting partial 
> deallocation. But we probably can't fix that at this point.)
> 
> Jordan
> 
>> 
>> There is only one decision that needs to be made here. Does the Swift 
>> runtime track allocation size for manually allocated blocks? I think the 
>> answer should be "yes", or at least haven't heard a strong argument against 
>> it. UnsafePointer.deallocate() needs to direcly reflect that model by making 
>> `allocatedCapacity` an *optional* argument.
>> 
>> Discussion about whether this API is unsafe, misleading, suboptimal or 
>> incorrectly implemented are secondary. Those are all deficiencies in the 
>> current documentation, current implementation, and availability of 
>> higher-level APIs.
>> 
>> Note that yesterday I argued that an optional argument wasn't worth the 
>> potential for confusion. That's true from a practical perspective, but I had 
>> lost sight of need to clearly specify the memory model. We want the Swift 
>> runtime to both have the functionality for tracking block size and also 
>> allow user code to track it more efficiently. Both those intentions need to 
>> be reflected in this API.
>> 
>> -Andy
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
> 
> 
> I mean I would have thought it’s reasonable to expect that if the method asks 
> for a capacity parameter, it will actually use it 

It will.

-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-07 Thread Andrew Trick via swift-evolution

> On Sep 7, 2017, at 11:39 AM, Jordan Rose  wrote:
> 
>> This discussion needs to be grounded by reiterating role of the API. 
>> UnsafePointer specifies the memory model without extraneous functionality or 
>> convenience.
>> 
>> The UnsafePointer.deallocate() API *is not*:
>> 
>> - a common, expected, or encouraged way to deallocate
>> 
>> - the simplest, safest, or most convenient way to deallocate
>> 
>> - necessarilly the most optimal path for deallocation
> 
> I don't think this is correct. UnsafePointer.deallocate is the API you must 
> use to deallocate memory allocated with UnsafePointer.allocate.

No, all of Swift’s APIs for manual allocation/deallocation need to be 
compatible. UnsafeBufferPointer is highly preferable to UnsafePointer today. In 
the future we will have a safe API for manual allocation, still based on the 
underlying model specified by UnsafePointer.

UnsafePointer.allocate() is *not*

- a common, expected, or encouraged way to allocate

- the simplest, safest, or most convenient way to allocate

- necessarily the most optimal path for allocation

Even though high-level APIs are specified in terms of this model, they can be 
implemented via their own fast-paths.

>  Myquestion is whether it's acceptable to break all the people who didn't 
> know this and are using it to deallocate memory allocated with malloc or new 
> on Apple platforms. It sounds like the answer to that is "no, we want to be 
> malloc-compatible", and therefore the 'capacity' parameter isn't currently 
> serving a purpose today. We will always need to check if the memory is 
> actually in the Swift pool before even believing the 'capacity' parameter.

We don’t need to claim that manually allocated Swift memory is malloc 
compatible on every platform that happens to have malloc. We do want the Swift 
memory model to be consistent with the reality that on most platforms, we need 
the runtime to track block size.

> (It is definitely true that the intent was for this to be the allocation 
> capacity, and I'm surprised you interpreted it as supporting partial 
> deallocation. But we probably can't fix that at this point.)

I never misinterpreted the meaning of the API, but apparently multiple people 
on the evolution list did. Regardless, that is not valid reason for changing 
the API. It’s only a valid reason for improving documentation and encouraging 
the use of safer APIs.

If our memory model states that the runtime tracks capacity of manually 
allocated blocks, then the deallocation capacity should be optional to reflect 
that.

Still waiting to hear any arguments that something about that memory model is 
bad.

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

>
> Le 7 sept. 2017 à 19:53, Tony Allevato  a écrit :
>
> Again, this is not the issue that Haravikk is describing in this thread.
>
>
> Yes, I better understand now. Please forgive the pollution.
>
> Gwendal
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

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

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

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

Gwendal

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


Re: [swift-evolution] [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-07 Thread Taylor Swift via swift-evolution
On Thu, Sep 7, 2017 at 1:39 PM, Jordan Rose  wrote:

>
>
> On Sep 7, 2017, at 10:31, Andrew Trick via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> On Sep 7, 2017, at 8:06 AM, Taylor Swift  wrote:
>
> I don’t see any source for this claim in the documentation
> ,
> or the source code
> .
> As far as I can tell the expected behavior is that partial deallocation
> “should” work.
>
> On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff  wrote:
>>
>>
>> The segfaulting example is an incorrect usage. The only valid parameters
>> to deallocate(capacity:) are the base address of an allocation, and the
>> original capacity passed into allocate(); it has never been intended to
>> support partial deallocation of allocated blocks. It seems to me like this
>> proposal is based on a misunderstanding of how the API works. The
>> documentation and/or name should be clarified.
>>
>> -Joe
>>
>> > “fixing” this bug will cause programs that once operated on previously
>> valid assumptions of “free()” semantics to behave differently, without any
>> warnings ever being generated. Conversely incorrect code will suddenly
>> become “correct” though this is less of a problem.
>> >
>> >> 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
>>
>
> This discussion needs to be grounded by reiterating role of the API.
> UnsafePointer specifies the memory model without extraneous functionality
> or convenience.
>
> The UnsafePointer.deallocate() API *is not*:
>
> - a common, expected, or encouraged way to deallocate
>
> - the simplest, safest, or most convenient way to deallocate
>
> - necessarilly the most optimal path for deallocation
>
>
> I don't think this is correct. UnsafePointer.deallocate is the API you
> must use to deallocate memory allocated with UnsafePointer.allocate. *My* 
> question
> is whether it's acceptable to break all the people who *didn't* know this
> and are using it to deallocate memory allocated with malloc or new on Apple
> platforms. It sounds like the answer to that is "no, we want to be
> malloc-compatible", and therefore the 'capacity' parameter isn't currently
> serving a purpose today. We will *always* need to check if the memory is
> actually in the Swift pool before even believing the 'capacity' parameter.
>
> (It is definitely true that the *intent* was for this to be the
> allocation capacity, and I'm surprised you interpreted it as supporting
> partial deallocation. But we probably can't fix that at this point.)
>
> Jordan
>
>
> There is only one decision that needs to be made here. Does the Swift
> runtime track allocation size for manually allocated blocks? I think the
> answer should be "yes", or at least haven't heard a strong argument against
> it. UnsafePointer.deallocate() needs to direcly reflect that model by
> making `allocatedCapacity` an *optional* argument.
>
> Discussion about whether this API is unsafe, misleading, suboptimal or
> incorrectly implemented are secondary. Those are all deficiencies in the
> current documentation, current implementation, and availability of
> higher-level APIs.
>
> Note that yesterday I argued that an optional argument wasn't worth the
> potential for confusion. That's true from a practical perspective, but I
> had lost sight of need to clearly specify the memory model. We want the
> Swift runtime to both have the functionality for tracking block size and
> also allow user code to track it more efficiently. Both those intentions
> need to be reflected in this API.
>
> -Andy
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
I mean I would have thought it’s reasonable to expect that if the method
asks for a capacity parameter, it will actually use it
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-09-07 Thread Taylor Swift via swift-evolution
On Thu, Sep 7, 2017 at 1:33 PM, Jordan Rose  wrote:

>
>
> On Sep 5, 2017, at 14:50, Andrew Trick via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> We don't have a consensus, but I think the suggestion to distinguish
> between single value vs. multiple semantics was good. Otherwise,
> adding the default count could be very misleading. Normally, we try to
> minimize surface area, but adding two methods for the single-value case
> avoids ambiguity between the buffer and pointer semantics:
>
> UMP (pointer)
> --- func initialize(to:count:(=1))
> +++ func initialize(to:)
> +++ func initialize(repeating:count:) // no default count
> +++ func assign(to:)
> +++ func assign(repeating:count:) // no default count
>
> UMRP (raw pointer):
> --- func initializeMemory(as:at:(=0)count:(1)to:)
> +++ func initializeMemory(as:repeating:count:) // remove default count
>
>
> I am *mostly* in favor of this two-method approach, but 'to' may not be
> the right label. Today we have both initialize(to:…) and
> initialize(from:…), which are not opposites. I think we can live with that,
> but we *definitely* can't use assign(to:). "x.assign(to: y)" means some
> form of "y = x".
>
> That said, we don't actually *need* a single-element 'assign' variant,
> because you can also write it "x.pointee = y". But I agree that symmetry is
> nice, if we can get it.
>

assign(to:) was never part of the original proposal, now that you mention
it, it’s stupid and should be left out
___
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-07 Thread Taylor Swift via swift-evolution
On Thu, Sep 7, 2017 at 12:31 PM, Andrew Trick  wrote:

>
> On Sep 7, 2017, at 8:06 AM, Taylor Swift  wrote:
>
> I don’t see any source for this claim in the documentation
> ,
> or the source code
> .
> As far as I can tell the expected behavior is that partial deallocation
> “should” work.
>
> On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff  wrote:
>>
>>
>> The segfaulting example is an incorrect usage. The only valid parameters
>> to deallocate(capacity:) are the base address of an allocation, and the
>> original capacity passed into allocate(); it has never been intended to
>> support partial deallocation of allocated blocks. It seems to me like this
>> proposal is based on a misunderstanding of how the API works. The
>> documentation and/or name should be clarified.
>>
>> -Joe
>>
>> > “fixing” this bug will cause programs that once operated on previously
>> valid assumptions of “free()” semantics to behave differently, without any
>> warnings ever being generated. Conversely incorrect code will suddenly
>> become “correct” though this is less of a problem.
>> >
>> >> 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
>>
>
> This discussion needs to be grounded by reiterating role of the API.
> UnsafePointer specifies the memory model without extraneous functionality
> or convenience.
>
> The UnsafePointer.deallocate() API *is not*:
>
> - a common, expected, or encouraged way to deallocate
>
> - the simplest, safest, or most convenient way to deallocate
>
> - necessarilly the most optimal path for deallocation
>
> There is only one decision that needs to be made here. Does the Swift
> runtime track allocation size for manually allocated blocks? I think the
> answer should be "yes", or at least haven't heard a strong argument against
> it. UnsafePointer.deallocate() needs to direcly reflect that model by
> making `allocatedCapacity` an *optional* argument.
>
> Discussion about whether this API is unsafe, misleading, suboptimal or
> incorrectly implemented are secondary. Those are all deficiencies in the
> current documentation, current implementation, and availability of
> higher-level APIs.
>
> Note that yesterday I argued that an optional argument wasn't worth the
> potential for confusion. That's true from a practical perspective, but I
> had lost sight of need to clearly specify the memory model. We want the
> Swift runtime to both have the functionality for tracking block size and
> also allow user code to track it more efficiently. Both those intentions
> need to be reflected in this API.
>
> -Andy
>

idk how the swift heap is planned to be implemented, but why is passing the
capacity to deallocate considered the fast path anyway? i thought the block
size was stored in a header right before the block pointer
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

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

> Le 7 sept. 2017 à 14:45, Tony Allevato  a écrit :
>
> Right, let's make sure we're talking about the right thing here. Gwendal,
> your issue isn't with synthesis in the form of Codable or the new additions
> to Equatable/Hashable which are opt-in-by-conformance, it's with the
> specific case of raw value enums or enums without associated values where
> the synthesis is implicit with no way to opt-out. That's a big difference.
>
>
> Yes.
>
> I can definitely see the latter being an issue if it were more widespread,
> and I'd be supportive of those enums being required to declare their
> conformance for consistency (though it would be source breaking).
>
>
> Yes, unfortunately.
>
>
> However, I still haven't seen a real issue that has come up because of the
> distinction being drawn here between default implementations vs.
> implementations that can access other parts of the concrete type. It sounds
> like this discussion is trying to protect against a hypothetical problem
> that hasn't happened yet and may not happen; it would be helpful to show
> some motivating real-world cases where this is indeed a severe problem.
>
>
> Yes. I'm not talking about implementation itself. I know this has been the
> main topic until I have tried to bring in the topic of the consequences of
> non-avoidable synthesis (extra methods that may conflict with userland
> methods).
>
> If you ask me for a real-world case, then I think I gave one. Let me
> rephrase it:
>
> it's impossible to define a value-backed enum without getting free
> Equatable conformance. This free conformance is sometimes unwanted, and I
> gave the example of DSLs. Now this problem is not *severe*. It's more a
> blind spot in the language, and finally just an unwanted side-effect of a
> compiler convenience,
>

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

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

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


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


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

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


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

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


As opposed to

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

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


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


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

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


I don't understand what this has to do with synthesized Equatable.  
Wouldn't manually implemented Equatable have the same impact?  The 
design of a DSL should be able to accommodate conformance to basic 
protocols without ambiguity.



I'll explain you:

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


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


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

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

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


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

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


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


We generally want as many types to be Equatable and Hashable as 
possible.  Synthesized conformance means more types will have these 
conformance and that's a good thing in all cases (so long as the 
implementation is correct).


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


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


Gwendal Roué




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


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

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

> Le 7 sept. 2017 à 14:45, Tony Allevato  a écrit :
> 
> Right, let's make sure we're talking about the right thing here. Gwendal, 
> your issue isn't with synthesis in the form of Codable or the new additions 
> to Equatable/Hashable which are opt-in-by-conformance, it's with the specific 
> case of raw value enums or enums without associated values where the 
> synthesis is implicit with no way to opt-out. That's a big difference.

Yes.

> I can definitely see the latter being an issue if it were more widespread, 
> and I'd be supportive of those enums being required to declare their 
> conformance for consistency (though it would be source breaking).

Yes, unfortunately.

> However, I still haven't seen a real issue that has come up because of the 
> distinction being drawn here between default implementations vs. 
> implementations that can access other parts of the concrete type. It sounds 
> like this discussion is trying to protect against a hypothetical problem that 
> hasn't happened yet and may not happen; it would be helpful to show some 
> motivating real-world cases where this is indeed a severe problem.

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

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

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

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

Gwendal Roué

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


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

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

> Le 7 sept. 2017 à 14:37, Matthew Johnson  a écrit :
> 
> I don't understand what this has to do with synthesized Equatable.  Wouldn't 
> manually implemented Equatable have the same impact?  The design of a DSL 
> should be able to accommodate conformance to basic protocols without 
> ambiguity.


I'll explain you:

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

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

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

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

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

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

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

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

> We generally want as many types to be Equatable and Hashable as possible.  
> Synthesized conformance means more types will have these conformance and 
> that's a good thing in all cases (so long as the implementation is correct).  

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

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

Gwendal Roué

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


Re: [swift-evolution] [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-07 Thread Andrew Trick via swift-evolution

> On Sep 7, 2017, at 8:06 AM, Taylor Swift  wrote:
> 
> I don’t see any source for this claim in the documentation 
> ,
>  or the source code 
> .
>  As far as I can tell the expected behavior is that partial deallocation 
> “should” work.
> 
> On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff  > wrote:
> 
> The segfaulting example is an incorrect usage. The only valid parameters to 
> deallocate(capacity:) are the base address of an allocation, and the original 
> capacity passed into allocate(); it has never been intended to support 
> partial deallocation of allocated blocks. It seems to me like this proposal 
> is based on a misunderstanding of how the API works. The documentation and/or 
> name should be clarified.
> 
> -Joe
> 
> > “fixing” this bug will cause programs that once operated on previously 
> > valid assumptions of “free()” semantics to behave differently, without any 
> > warnings ever being generated. Conversely incorrect code will suddenly 
> > become “correct” though this is less of a problem.
> >
> >> 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

This discussion needs to be grounded by reiterating role of the API. 
UnsafePointer specifies the memory model without extraneous functionality or 
convenience.

The UnsafePointer.deallocate() API *is not*:

- a common, expected, or encouraged way to deallocate

- the simplest, safest, or most convenient way to deallocate

- necessarilly the most optimal path for deallocation

There is only one decision that needs to be made here. Does the Swift runtime 
track allocation size for manually allocated blocks? I think the answer should 
be "yes", or at least haven't heard a strong argument against it. 
UnsafePointer.deallocate() needs to direcly reflect that model by making 
`allocatedCapacity` an *optional* argument.

Discussion about whether this API is unsafe, misleading, suboptimal or 
incorrectly implemented are secondary. Those are all deficiencies in the 
current documentation, current implementation, and availability of higher-level 
APIs.

Note that yesterday I argued that an optional argument wasn't worth the 
potential for confusion. That's true from a practical perspective, but I had 
lost sight of need to clearly specify the memory model. We want the Swift 
runtime to both have the functionality for tracking block size and also allow 
user code to track it more efficiently. Both those intentions need to be 
reflected in this API.

-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-07 Thread Andrew Trick via swift-evolution

> On Sep 6, 2017, at 10:15 PM, Taylor Swift  wrote:
> 
> 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. 

Yay for all 5.
-Andy___
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-07 Thread Vladimir.S via swift-evolution

On 07.09.2017 18:23, Rod Brown wrote:




On 8 Sep 2017, at 12:24 am, Vladimir.S  wrote:



On 07.09.2017 16:03, Rod Brown wrote:

On 7 Sep 2017, at 9:26 pm, Vladimir.S via swift-evolution
> wrote: Just
small note. As I understand, this is a source breaking suggestion, no? I
mean any client code for 'public enum' coming from another module, will have
to add 'default' case in 'switch'. So, the previously correct code will not
compile. Or do you suggest to raise a warning only for the first time and
raise an error in next version of Swift?

Yes. By defaulting to “non fragile” we add a source incompatibility, because
Swift is currently assuming fragility. In Jordan’s proposal, it is assuming
fragility/exhaustive by default, and therefore would be source compatible.
Good point. I keep wavering back and forth on the importance of Source
Compatibility with this one. Defaulting to “exhaustive” seems dangerous to me.
It makes your framework (and future versions of it) fragile without ever
having to think about it. At least if the keyword of “exhaustive” or “fragile”
or “sealed” meant that you actively chose the fragility that will handcuff you
later down the road.


Yes, probably(still thinking about this) I agree that 'open'('exhaustive') enum
should be the default for public enum; and only if author is really sure enum
will not change in future and to provide a space for compiler's optimizations
and suggest client to switch exhaustive, he/she can mark such enum as
exhaustive/fragile/sealed/closed/fixed. And seems like the right direction is
raise warnings fist, and errors in next version of Swift.

The only question I can't find strong answer for, what my code(as a client of
'open' enum) will do in 'default' case? Will it be in 95% cases the
fatalError().. If so, what is the difference with current situation? If my
switch is already exhaustive regarding some public(imported) enum, so I'm
processing all the possible *at the compilation time* cases - most likely I'll
have just fatalError() in 'default'. If my switch already contains 'default' -
the proposed change will not affect me at all…


This was discussed earlier. As I mentioned, we should be realistic: it’s rarely 
a
truly fatal error when you get an unknown enum. Unless you really can’t find a
reasonable default, then there are almost always reasonable logical ways to 
handle
it (perhaps just breaking out?). And in cases where you really need to handle 
each
case, this would (almost?) always be an exhaustive enum. I can’t even imagine 
the
case where it would be so critical you couldn’t handle it with reasonable 
control
flow. There are always solutions like returning early, breaking out, default
details. I see Swift code littered with fatalError() not because its needed, but
because the developer often didn’t care enough to think it through.



Thank you for replies, Rod!

Thinking about this, if "in cases where you really need to handle each case, this 
would (almost?) always be an exhaustive enum", then I tend to agree with you.


So, currently my point of view is that we need to move the way suggested by Chris, 
when we need to mark public 'closed' enum, so 'open' is default, and with warning for 
first time and with error in next version of Swift for switches on 'open' enum 
without 'default' case. Not the way described in the proposal itself.




But probably it is better to have a choice what to do with future cases, than
have just one direction - crash at run time if new case in external enum is
added.

But the same I can say for proposed 'future' case : it is better to have a
choice what to use - 'default', if we don't need to be exhaustive on 'open'
enum,  or 'future', if we need to be exhaustive on 'open' enum in compile-time
but separately process all future cases.


“Future” might be a decent idea, but I think we’re overcomplicating it. Just use
“default” as we always have? “Future” as a word doesn’t seem to apply, as I have
mentioned earlier: there are cases where your framework has a private case on an
enum. This isn’t necessarily a future case - it could be “current”. If we were 
to
do this, it would make more sense to call this case word “other” instead. Again,
though, we’re adding complexity to a switch for a very rare case and a little 
bit
of developer convenience in that case.


Well... yes, seems like this. I didn't get current but private cases into account. 
But I was more focused on Swift's enums, not on C's.


What do you(and others) think about such idea: if we have an exhaustive switch on 
_open_ enum _without_ 'default' case, and there are *no* more known available cases 
for this enum currently - compiler generates error/warning like "you have exhaustive 
switch but this is an open enum new cases can be added later, so add 'default' case 
to process them". But, if such(exhaustive on _open_ enum _without_ 'default' case) 
switch contains not all 

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-07 Thread Taylor Swift via swift-evolution
not a fan of this. A lot of data structures including buffer pointers
already store their capacity in a property, storing an allocation token
would be redundant and waste space. It also forces allocate(capacity:) to
return a tuple which is a big turn off for me.

On Thu, Sep 7, 2017 at 10:56 AM, Joe Groff  wrote:

>
> On Sep 7, 2017, at 8:06 AM, Taylor Swift  wrote:
>
> I don’t see any source for this claim in the documentation
> ,
> or the source code
> .
> As far as I can tell the expected behavior is that partial deallocation
> “should” work.
>
>
> We should fix the documentation bug then.
>
> Another way we could make these APIs easier to use correctly is to
> leverage the type system. allocate could return the allocation size wrapped
> up in an opaque AllocationToken type, and deallocate could take an
> AllocationToken:
>
> static func allocate(capacity: Int) -> (UnsafeMutableBufferPointer,
> AllocationToken)
>
> func deallocate(token: AllocationToken)
>
> That would make it harder for user code to pass an arbitrary size in, and
> make the relationship between the allocate and deallocate calls more
> explicit in their signatures. If we get an ABI break and a bold new idea
> for an allocator design with different context needs in the future, it'd
> also insulate source code from the exact contents of the information that
> needs to be carried from allocation to deallocation.
>
> -Joe
>
> On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff  wrote:
>
>>
>> > On Sep 6, 2017, at 4:46 PM, Taylor Swift  wrote:
>> >
>> >
>> >
>> >> 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 <
>> swift-evolution@swift.org> 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 <
>> 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 

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-07 Thread Joe Groff via swift-evolution

> On Sep 7, 2017, at 8:06 AM, Taylor Swift  wrote:
> 
> I don’t see any source for this claim in the documentation 
> ,
>  or the source code 
> .
>  As far as I can tell the expected behavior is that partial deallocation 
> “should” work.

We should fix the documentation bug then.

Another way we could make these APIs easier to use correctly is to leverage the 
type system. allocate could return the allocation size wrapped up in an opaque 
AllocationToken type, and deallocate could take an AllocationToken:

static func allocate(capacity: Int) -> (UnsafeMutableBufferPointer, 
AllocationToken)

func deallocate(token: AllocationToken)

That would make it harder for user code to pass an arbitrary size in, and make 
the relationship between the allocate and deallocate calls more explicit in 
their signatures. If we get an ABI break and a bold new idea for an allocator 
design with different context needs in the future, it'd also insulate source 
code from the exact contents of the information that needs to be carried from 
allocation to deallocation.

-Joe

> On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff  > wrote:
> 
> > On Sep 6, 2017, at 4:46 PM, Taylor Swift  > > wrote:
> >
> >
> >
> >> 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 

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

2017-09-07 Thread Pierre Habouzit via swift-evolution
> On Sep 7, 2017, at 1:04 AM, Howard Lovatt via swift-evolution 
>  wrote:
> 
> I would argue that given:
> 
> foo()
> await bar()
> baz()
> 
> That foo and baz should run on the same queue (using queue in the GCD sense) 
> but bar should determine which queue it runs on. I say this because:
> foo and baz are running synchronously with respect to each other (though they 
> could be running asynchronously with respect to some other process if all the 
> lines shown are inside an async function).
> bar is running asynchronously relative to foo and baz, potentially on a 
> different queue.

This isn't true, in the code above, foo() bar() and baz() all execute serially 
(synchronously is a weird word to use here IMO).
Serial code that you write with or without async/await in the middle will run 
serially independently from where it physically executes.

And for the record I do agree with Chris that by default foo() and baz() should 
execute on the same context. This is quite tricky if the caller is a pthread 
though, and the three possibilities I see for this on a manually made thread 
are:
- we assert at runtime
- await synchronously blocks in that case
- baz() doesn't execute on the thread

I think the 3rd one is a non starter, that (1) would be nice but may prove 
impractical. a (4) would be to require for people making manual threads and 
using async/await to drain some thing themselves from that thread through an 
event loop of theirs. But the danger or (4) is that if the client doesn't do 
it, then the failure mode is silent.

> I say bar is potentially on a different queue because the user of bar, the 
> person who wrote these 3 lines above, cannot be presumed to be the writer of 
> foo, baz, and particularly not bar and therefore have no detailed knowledge 
> about which queue is appropriate.
> 
> Therefore I would suggest either using a Future or expanding async so that 
> you can say:
> 
> func bar() async(qos: .userInitiated) { ... }
> 
> You also probably need the ability to specify a timeout and queue type, e.g.:
> 
>func bar() async(type: .serial, qos: .utility, timeout: .seconds(10)) 
> throws { ... }
> 
> If a timeout is specified then await would have to throw to enable the 
> timeout, i.e. call would become:
> 
>try await bar()
> 
> Defaults could be provided for qos (.default works well), timeout (1 second 
> works well), and type (.concurrent works well).
> 
> However a Future does all this already :).
> 
>   -- Howard.
> 
> On 7 September 2017 at 15:13, David Hart via swift-evolution 
> > wrote:
> 
> 
> > 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 

Re: [swift-evolution] Enums and Source Compatibility

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


> On 8 Sep 2017, at 12:24 am, Vladimir.S  wrote:
> 
> 
> 
> On 07.09.2017 16:03, Rod Brown wrote:
>>> On 7 Sep 2017, at 9:26 pm, Vladimir.S via swift-evolution 
>>> > wrote:
>>> Just small note. As I understand, this is a source breaking suggestion, no?
>>> I mean any client code for 'public enum' coming from another module, will 
>>> have to add 'default' case in 'switch'. So, the previously correct code 
>>> will not compile. Or do you suggest to raise a warning only for the first 
>>> time and raise an error in next version of Swift?
>> Yes. By defaulting to “non fragile” we add a source incompatibility, because 
>> Swift is currently assuming fragility. In Jordan’s proposal, it is assuming 
>> fragility/exhaustive by default, and therefore would be source compatible. 
>> Good point.
>> I keep wavering back and forth on the importance of Source Compatibility 
>> with this one. Defaulting to “exhaustive” seems dangerous to me. It makes 
>> your framework (and future versions of it) fragile without ever having to 
>> think about it. At least if the keyword of “exhaustive” or “fragile” or 
>> “sealed” meant that you actively chose the fragility that will handcuff you 
>> later down the road.
> 
> Yes, probably(still thinking about this) I agree that 'open'('exhaustive') 
> enum should be the default for public enum; and only if author is really sure 
> enum will not change in future and to provide a space for compiler's 
> optimizations and suggest client to switch exhaustive, he/she can mark such 
> enum as exhaustive/fragile/sealed/closed/fixed. And seems like the right 
> direction is raise warnings fist, and errors in next version of Swift.
> 
> The only question I can't find strong answer for, what my code(as a client of 
> 'open' enum) will do in 'default' case? Will it be in 95% cases the 
> fatalError().. If so, what is the difference with current situation?
> If my switch is already exhaustive regarding some public(imported) enum, so 
> I'm processing all the possible *at the compilation time* cases - most likely 
> I'll have just fatalError() in 'default'.
> If my switch already contains 'default' - the proposed change will not affect 
> me at all…

This was discussed earlier. As I mentioned, we should be realistic: it’s rarely 
a truly fatal error when you get an unknown enum. Unless you really can’t find 
a reasonable default, then there are almost always reasonable logical ways to 
handle it (perhaps just breaking out?). And in cases where you really need to 
handle each case, this would (almost?) always be an exhaustive enum. I can’t 
even imagine the case where it would be so critical you couldn’t handle it with 
reasonable control flow. There are always solutions like returning early, 
breaking out, default details. I see Swift code littered with fatalError() not 
because its needed, but because the developer often didn’t care enough to think 
it through.

> 
> But probably it is better to have a choice what to do with future cases, than 
> have just one direction - crash at run time if new case in external enum is 
> added.
> 
> But the same I can say for proposed 'future' case : it is better to have a 
> choice what to use - 'default', if we don't need to be exhaustive on 'open' 
> enum,  or 'future', if we need to be exhaustive on 'open' enum in 
> compile-time but separately process all future cases.

“Future” might be a decent idea, but I think we’re overcomplicating it. Just 
use “default” as we always have? “Future” as a word doesn’t seem to apply, as I 
have mentioned earlier: there are cases where your framework has a private case 
on an enum. This isn’t necessarily a future case - it could be “current”. If we 
were to do this, it would make more sense to call this case word “other” 
instead. Again, though, we’re adding complexity to a switch for a very rare 
case and a little bit of developer convenience in that case.

> 
> Yes, in this case we have a problem with testability, but the same is true 
> for exhaustive switch with 'defailt' case - how this 'default' code can be 
> tested? Probably, we need to provide a solution for this in any case, not 
> because of 'future' but also for 'default' in exhaustive switch on 'open' 
> enum. (Don't know how this could be implemented, probably by somehow be able 
> to extend the imported open enum with 'fake' case when compile in special 
> mode for testing and be able to send this fake case into tested code)

Yes, testing this is a concern. I agree: have an ability to add an “other" case 
in tests.

> 
> Vladimir.
> 
>>> 
 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.
>>> 
>>> I think 'fragile' word does not reflect what is guaranteed for this enum. 
>>> The author guaranteed that this enum 

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-07 Thread Taylor Swift via swift-evolution
I don’t see any source for this claim in the documentation
,
or the source code
.
As far as I can tell the expected behavior is that partial deallocation
“should” work.

On Thu, Sep 7, 2017 at 8:59 AM, Joe Groff  wrote:

>
> > On Sep 6, 2017, at 4:46 PM, Taylor Swift  wrote:
> >
> >
> >
> >> 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 <
> swift-evolution@swift.org> 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 <
> 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.
> >>
> >> 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
> 

Re: [swift-evolution] Enums and Source Compatibility

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



On 07.09.2017 16:03, Rod Brown wrote:



On 7 Sep 2017, at 9:26 pm, Vladimir.S via swift-evolution 
> wrote:


On 07.09.2017 7:33, 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.


Just small note. As I understand, this is a source breaking suggestion, no?
I mean any client code for 'public enum' coming from another module, will have to 
add 'default' case in 'switch'. So, the previously correct code will not compile. 
Or do you suggest to raise a warning only for the first time and raise an error in 
next version of Swift?


Yes. By defaulting to “non fragile” we add a source incompatibility, because Swift is 
currently assuming fragility. In Jordan’s proposal, it is assuming 
fragility/exhaustive by default, and therefore would be source compatible. Good point.


I keep wavering back and forth on the importance of Source Compatibility with this 
one. Defaulting to “exhaustive” seems dangerous to me. It makes your framework (and 
future versions of it) fragile without ever having to think about it. At least if the 
keyword of “exhaustive” or “fragile” or “sealed” meant that you actively chose the 
fragility that will handcuff you later down the road.




Yes, probably(still thinking about this) I agree that 'open'('exhaustive') enum 
should be the default for public enum; and only if author is really sure enum will 
not change in future and to provide a space for compiler's optimizations and suggest 
client to switch exhaustive, he/she can mark such enum as 
exhaustive/fragile/sealed/closed/fixed. And seems like the right direction is raise 
warnings fist, and errors in next version of Swift.


The only question I can't find strong answer for, what my code(as a client of 'open' 
enum) will do in 'default' case? Will it be in 95% cases the fatalError().. If so, 
what is the difference with current situation?
If my switch is already exhaustive regarding some public(imported) enum, so I'm 
processing all the possible *at the compilation time* cases - most likely I'll have 
just fatalError() in 'default'.
If my switch already contains 'default' - the proposed change will not affect me at 
all...


But probably it is better to have a choice what to do with future cases, than have 
just one direction - crash at run time if new case in external enum is added.


But the same I can say for proposed 'future' case : it is better to have a choice 
what to use - 'default', if we don't need to be exhaustive on 'open' enum,  or 
'future', if we need to be exhaustive on 'open' enum in compile-time but separately 
process all future cases.


Yes, in this case we have a problem with testability, but the same is true for 
exhaustive switch with 'defailt' case - how this 'default' code can be tested? 
Probably, we need to provide a solution for this in any case, not because of 'future' 
but also for 'default' in exhaustive switch on 'open' enum. (Don't know how this 
could be implemented, probably by somehow be able to extend the imported open enum 
with 'fake' case when compile in special mode for testing and be able to send this 
fake case into tested code)


Vladimir.



3. fragile public enum: cases may not be added, because that would break the 
fragility guarantee.  As 

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-07 Thread Joe Groff via swift-evolution

> On Sep 6, 2017, at 4:46 PM, Taylor Swift  wrote:
> 
> 
> 
>> 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 
> 

Re: [swift-evolution] Contextualizing async coroutines

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

> On Sep 2, 2017, at 12:07 PM, Chris Lattner  wrote:
> 
> On Aug 31, 2017, at 11:35 AM, Joe Groff via swift-evolution 
>  wrote:
>> The coroutine proposal as it stands essentially exposes raw delimited 
>> continuations. While this is a flexible and expressive feature in the 
>> abstract, for the concrete purpose of representing asynchronous coroutines, 
>> it provides weak user-level guarantees about where their code might be 
>> running after being resumed from suspension, and puts a lot of pressure on 
>> APIs to be well-behaved in this respect. And if we're building toward 
>> actors, where async actor methods should be guaranteed to run "in the 
>> actor", I think we'll *need* something more than the bare-bones delimited 
>> continuation approach to get there. I think the proposal's desire to keep 
>> coroutines independent of a specific runtime model is a good idea, but I 
>> also think there are a couple possible modifications we could add to the 
>> design to make it easier to reason about what context things run in for any 
>> runtime model that benefits from async/await:
>> 
>> # Coroutine context
>> 
>> Associating a context value with a coroutine would let us thread useful 
>> information through the execution of the coroutine. This is particularly 
>> useful for GCD, so you could attach a queue, QoS, and other attributes to 
>> the coroutine, since these aren't reliably available from the global 
>> environment. It could be a performance improvement even for things like 
>> per-pthread queues, since coroutine context should be cheaper to access than 
>> pthread_self. 
>> 
>> For example, a coroutine-aware `dispatch_async` could spawn a coroutine with 
>> the queue object and other interesting attributes as its context:
>> 
>> extension DispatchQueue {
>> func `async`(_ body: () async -> ()) {
>>  dispatch_async(self, {
>>beginAsync(context: self) { await body() }
>>  })
>> }
>> }
> 
> I think it makes perfect sense to add a magically available context to async 
> functions, and something like the above is a good way to populate it.  
> Because is is a magic value that is only available in async functions, giving 
> it a keyword like asyncContext might make sense.  That said, I don’t 
> understand how (by itself) this helps the queue hopping problem.

By itself, it doesn't, but the context can carry information from when the 
coroutine was spawned to functions that yield control from the coroutine, so 
that there's an opportunity to use the context information to schedule the 
continuation properly up-front, avoiding the need

>> # `onResume` hooks
>> 
>> Relying on coroutine context alone still leaves responsibility wholly on 
>> suspending APIs to pay attention to the coroutine context and schedule the 
>> continuation correctly. You'd still have the expression problem when 
>> coroutine-spawning APIs from one framework interact with suspending APIs 
>> from another framework that doesn't understand the spawning framework's 
>> desired scheduling policy. We could provide some defense against this by 
>> letting the coroutine control its own resumption with an "onResume" hook, 
>> which would run when a suspended continuation is invoked instead of 
>> immediately resuming the coroutine. That would let the coroutine-aware 
>> dispatch_async example from above do something like this, to ensure the 
>> continuation always ends up back on the correct queue:
> 
> Yes, we need something like this, though I’m not sure how your proposal works:
> 
>> extension DispatchQueue {
>> func `async`(_ body: () async -> ()) {
>>  dispatch_async(self, {
>>beginAsync(
>>  context: self,
>>  body: { await body() },
>>  onResume: { continuation in
>>// Defensively hop to the right queue
>>dispatch_async(self, continuation)
> 
> If I’m running on a pthread, and use "someQueue.async {…}”, I don’t see how 
> DispatchQueue.async can know how to take me back to a pthread.  If I 
> understand your example code above, it looks like the call will run the 
> continuation on someQueue instead.

That's the intended behavior. `someQueue.async` never "runs on a pthread", it 
spawns a new coroutine that always runs on `someQueue`, just like the 
closure-based form always runs a synchronous block of code on `someQueue` 
today. You would need some other API to spawn a coroutine that schedules onto a 
specific thread using something other than dispatch.

> That said, I think that your idea of context pretty much covers it: a 
> non-async function cannot have any idea whether it is run on a queue or 
> thread, but there is also no language way to call an async function from a 
> non-async function.  I think this means that beginAsync and 
> DispatchQueue.async will have to define some policy: for example, the 
> implementation of DispatchQueue.async could use its own internal data 
> structures to decide if the current task is being run on some 

Re: [swift-evolution] Enums and Source Compatibility

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


> On 7 Sep 2017, at 9:26 pm, Vladimir.S via swift-evolution 
>  wrote:
> 
> On 07.09.2017 7:33, 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.
> 
> Just small note. As I understand, this is a source breaking suggestion, no?
> I mean any client code for 'public enum' coming from another module, will 
> have to add 'default' case in 'switch'. So, the previously correct code will 
> not compile. Or do you suggest to raise a warning only for the first time and 
> raise an error in next version of Swift?

Yes. By defaulting to “non fragile” we add a source incompatibility, because 
Swift is currently assuming fragility. In Jordan’s proposal, it is assuming 
fragility/exhaustive by default, and therefore would be source compatible. Good 
point.

I keep wavering back and forth on the importance of Source Compatibility with 
this one. Defaulting to “exhaustive” seems dangerous to me. It makes your 
framework (and future versions of it) fragile without ever having to think 
about it. At least if the keyword of “exhaustive” or “fragile” or “sealed” 
meant that you actively chose the fragility that will handcuff you later down 
the road.

> 
>> 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.
> 
> I think 'fragile' word does not reflect what is guaranteed for this enum. The 
> author guaranteed that this enum will not be changed, not "this enum can 
> broke your code". Can't we use 'sealed'/'closed'/'fixed' here?
> 
> Vladimir.
> 
>> 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
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

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


Sent from my iPad

> On Sep 7, 2017, at 7:45 AM, Tony Allevato  wrote:
> 
> Right, let's make sure we're talking about the right thing here. Gwendal, 
> your issue isn't with synthesis in the form of Codable or the new additions 
> to Equatable/Hashable which are opt-in-by-conformance, it's with the specific 
> case of raw value enums or enums without associated values where the 
> synthesis is implicit with no way to opt-out. That's a big difference.
> 
> I can definitely see the latter being an issue if it were more widespread, 
> and I'd be supportive of those enums being required to declare their 
> conformance for consistency (though it would be source breaking).

Ahh, thanks for clearing that up Tony.  I missed this.  I agree that this could 
be problematic in some cases (as Gwendal found) and should be fixed.  Now that 
we have a well established model for synthesis we should follow it consistently.

> 
> However, I still haven't seen a real issue that has come up because of the 
> distinction being drawn here between default implementations vs. 
> implementations that can access other parts of the concrete type. It sounds 
> like this discussion is trying to protect against a hypothetical problem that 
> hasn't happened yet and may not happen; it would be helpful to show some 
> motivating real-world cases where this is indeed a severe problem.
>> On Thu, Sep 7, 2017 at 5:37 AM Matthew Johnson via swift-evolution 
>>  wrote:
>> 
>> 
>> Sent from my iPad
>> 
>>> On Sep 7, 2017, at 7:07 AM, Gwendal Roué via swift-evolution 
>>>  wrote:
>>> 
>>> Hello,
>>> 
>>> I'm interested in this debate because I've been bitten by automatic 
>>> synthesis recently.
>>> 
>>> I'm reading your discussion, but I don't have a strong opinion. I only have 
>>> an anecdote: implicit, automatic, and unavoidable code synthesis code can 
>>> make it difficult to write some DSLs (aka Domain-Specific Languages).
>>> 
>>> I did stumble against undesired Equatable synthesis while developping a 
>>> library[1] that generates SQL snippets. In this library, the `==` operator 
>>> does not return a Bool: it returns an SQL expression:
>>> 
>>> // SELECT * FROM players WHERE bestScore = 1000
>>> Player.filter(bestScore == 1000)
>>> 
>>> Since the library is free to define == as an operator that returns an SQL 
>>> expression, this works quite well. Even when both operands have the same 
>>> type:
>>> 
>>> // SELECT * FROM players WHERE lastScore = bestScore
>>> Player.filter(lastScore == bestScore)
>>> 
>>> However, as soon as the type is (also) Equatable, an ambiguity occurs, and 
>>> the DSL is basically broken:
>>> 
>>> Player.filter(lastScore == bestScore) // which == please?
>>> 
>>> In this case, the == from synthesized Equatable conformance is not welcome 
>>> at all. It prevents the library from controlling the return type of the == 
>>> operator. Equatable conformance is unavoidable for enums based on String or 
>>> generally any raw value type that adopts Equatable. The consequence is that 
>>> my library can't allow its users to define an enum of table columns.
>>> 
>>> This is not a deal breaker. Everybody can live with this little caveat, and 
>>> I guess I'm the only one who wishes things had been more *consistent*. But 
>>> still: this story helps realizing that code synthesis can bite in plenty of 
>>> unexpected ways.
>> 
>> I don't understand what this has to do with synthesized Equatable.  Wouldn't 
>> manually implemented Equatable have the same impact?  The design of a DSL 
>> should be able to accommodate conformance to basic protocols without 
>> ambiguity.
>> 
>> We generally want as many types to be Equatable and Hashable as possible.  
>> Synthesized conformance means more types will have these conformance and 
>> that's a good thing in all cases (so long as the implementation is correct). 
>>  
>> 
>>> 
>>> Thanks for reading,
>>> Gwendal Roué
>>> [1] http://github.com/groue/GRDB.swift
>>> 
> Le 7 sept. 2017 à 12:20, Haravikk via swift-evolution 
>  a écrit :
> 
> 
>> On 7 Sep 2017, at 00:11, Brent Royal-Gordon  
>> wrote:
>> 
>> On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
>>  wrote:
>> 
>> This proposal idea is essentially for a new attribute @synthetic (name 
>> is up for debate). This attribute is required for any default 
>> implementation that includes reflective type compiler magic, use of the 
>> reflection API against `self` or, in future, any native Swift macros 
>> within the method (possibly limited to specific features, will depend on 
>> the macro language and its capabilities).
> 
> 
> "Use of the reflection API against `self`"? `String(describing:)` and 
> `String(reflecting:)` sometimes do that.
> 
> I see zero 

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

2017-09-07 Thread Tony Allevato via swift-evolution
Right, let's make sure we're talking about the right thing here. Gwendal,
your issue isn't with synthesis in the form of Codable or the new additions
to Equatable/Hashable which are opt-in-by-conformance, it's with the
specific case of raw value enums or enums without associated values where
the synthesis is implicit with no way to opt-out. That's a big difference.

I can definitely see the latter being an issue if it were more widespread,
and I'd be supportive of those enums being required to declare their
conformance for consistency (though it would be source breaking).

However, I still haven't seen a real issue that has come up because of the
distinction being drawn here between default implementations vs.
implementations that can access other parts of the concrete type. It sounds
like this discussion is trying to protect against a hypothetical problem
that hasn't happened yet and may not happen; it would be helpful to show
some motivating real-world cases where this is indeed a severe problem.
On Thu, Sep 7, 2017 at 5:37 AM Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> Sent from my iPad
>
> On Sep 7, 2017, at 7:07 AM, Gwendal Roué via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Hello,
>
> I'm interested in this debate because I've been bitten by automatic
> synthesis recently.
>
> I'm reading your discussion, but I don't have a strong opinion. I only
> have an anecdote: implicit, automatic, and unavoidable code synthesis code
> can make it difficult to write some DSLs (aka Domain-Specific Languages).
>
> I did stumble against undesired Equatable synthesis while developping a
> library[1] that generates SQL snippets. In this library, the `==` operator
> does not return a Bool: it returns an SQL expression:
>
> // SELECT * FROM players WHERE bestScore = 1000
> Player.filter(bestScore == 1000)
>
> Since the library is free to define == as an operator that returns an SQL
> expression, this works quite well. Even when both operands have the same
> type:
>
> // SELECT * FROM players WHERE lastScore = bestScore
> Player.filter(lastScore == bestScore)
>
> However, as soon as the type is (also) Equatable, an ambiguity occurs, and
> the DSL is basically broken:
>
> Player.filter(lastScore == bestScore) // which == please?
>
> In this case, the == from synthesized Equatable conformance is not welcome
> at all. It prevents the library from controlling the return type of the ==
> operator. Equatable conformance is unavoidable for enums based on String or
> generally any raw value type that adopts Equatable. The consequence is that
> my library can't allow its users to define an enum of table columns.
>
> This is not a deal breaker. Everybody can live with this little caveat,
> and I guess I'm the only one who wishes things had been more *consistent*.
> But still: this story helps realizing that code synthesis can bite in
> plenty of unexpected ways.
>
>
> I don't understand what this has to do with synthesized Equatable.
> Wouldn't manually implemented Equatable have the same impact?  The design
> of a DSL should be able to accommodate conformance to basic protocols
> without ambiguity.
>
> We generally want as many types to be Equatable and Hashable as possible.
> Synthesized conformance means more types will have these conformance and
> that's a good thing in all cases (so long as the implementation is
> correct).
>
>
> Thanks for reading,
> Gwendal Roué
> [1] http://github.com/groue/GRDB.swift
>
> Le 7 sept. 2017 à 12:20, Haravikk via swift-evolution <
> swift-evolution@swift.org> a écrit :
>
>
> On 7 Sep 2017, at 00:11, Brent Royal-Gordon 
> wrote:
>
> On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> This proposal idea is essentially for a new attribute @synthetic (name is
> up for debate). This attribute is required for any default implementation
> that includes reflective type compiler magic, use of the reflection API
> against `self` or, in future, any native Swift macros within the method
> (possibly limited to specific features, will depend on the macro language
> and its capabilities).
>
>
> "Use of the reflection API against `self`"? `String(describing:)` and
> `String(reflecting:)` sometimes do that.
>
> I see zero justification for having @synthetic cover all of these random
> things, but not ordinary default implementations—they have the same amount
> of dangerous implicitness.
>
>
> Actually they don't; the problem here is that through reflection you are
> accessing and manipulating concrete types. A non-reflective default
> implementation *only* has access to what the protocol itself has defined.
> The synthetic alternatives are instead diving into parts of a concrete type
> that may have nothing to do with the protocol at all, and must therefore
> make assumptions that cannot be guaranteed to be correct, this is what
> makes them dangerous.
>
> On 6 Sep 2017, at 23:43, Nevin 

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

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


Sent from my iPad

> On Sep 7, 2017, at 7:07 AM, Gwendal Roué via swift-evolution 
>  wrote:
> 
> Hello,
> 
> I'm interested in this debate because I've been bitten by automatic synthesis 
> recently.
> 
> I'm reading your discussion, but I don't have a strong opinion. I only have 
> an anecdote: implicit, automatic, and unavoidable code synthesis code can 
> make it difficult to write some DSLs (aka Domain-Specific Languages).
> 
> I did stumble against undesired Equatable synthesis while developping a 
> library[1] that generates SQL snippets. In this library, the `==` operator 
> does not return a Bool: it returns an SQL expression:
> 
>   // SELECT * FROM players WHERE bestScore = 1000
>   Player.filter(bestScore == 1000)
> 
> Since the library is free to define == as an operator that returns an SQL 
> expression, this works quite well. Even when both operands have the same type:
> 
>   // SELECT * FROM players WHERE lastScore = bestScore
>   Player.filter(lastScore == bestScore)
> 
> However, as soon as the type is (also) Equatable, an ambiguity occurs, and 
> the DSL is basically broken:
> 
>   Player.filter(lastScore == bestScore) // which == please?
> 
> In this case, the == from synthesized Equatable conformance is not welcome at 
> all. It prevents the library from controlling the return type of the == 
> operator. Equatable conformance is unavoidable for enums based on String or 
> generally any raw value type that adopts Equatable. The consequence is that 
> my library can't allow its users to define an enum of table columns.
> 
> This is not a deal breaker. Everybody can live with this little caveat, and I 
> guess I'm the only one who wishes things had been more *consistent*. But 
> still: this story helps realizing that code synthesis can bite in plenty of 
> unexpected ways.

I don't understand what this has to do with synthesized Equatable.  Wouldn't 
manually implemented Equatable have the same impact?  The design of a DSL 
should be able to accommodate conformance to basic protocols without ambiguity.

We generally want as many types to be Equatable and Hashable as possible.  
Synthesized conformance means more types will have these conformance and that's 
a good thing in all cases (so long as the implementation is correct).  

> 
> Thanks for reading,
> Gwendal Roué
> [1] http://github.com/groue/GRDB.swift
> 
>>> Le 7 sept. 2017 à 12:20, Haravikk via swift-evolution 
>>>  a écrit :
>>> 
>>> 
 On 7 Sep 2017, at 00:11, Brent Royal-Gordon  wrote:
 
 On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
  wrote:
 
 This proposal idea is essentially for a new attribute @synthetic (name is 
 up for debate). This attribute is required for any default implementation 
 that includes reflective type compiler magic, use of the reflection API 
 against `self` or, in future, any native Swift macros within the method 
 (possibly limited to specific features, will depend on the macro language 
 and its capabilities).
>>> 
>>> 
>>> "Use of the reflection API against `self`"? `String(describing:)` and 
>>> `String(reflecting:)` sometimes do that.
>>> 
>>> I see zero justification for having @synthetic cover all of these random 
>>> things, but not ordinary default implementations—they have the same amount 
>>> of dangerous implicitness.
>> 
>> Actually they don't; the problem here is that through reflection you are 
>> accessing and manipulating concrete types. A non-reflective default 
>> implementation only has access to what the protocol itself has defined. The 
>> synthetic alternatives are instead diving into parts of a concrete type that 
>> may have nothing to do with the protocol at all, and must therefore make 
>> assumptions that cannot be guaranteed to be correct, this is what makes them 
>> dangerous.
>> 
 On 6 Sep 2017, at 23:43, Nevin Brackett-Rozinsky 
  wrote:
> On Wed, Sep 6, 2017 at 5:42 PM, Haravikk via swift-evolution 
>  wrote:
> the issue I'm trying to raise is that when those, and similar features, 
> are used in synthesised behaviour (default implementations based upon the 
> concrete type), that these behaviours should be opted into explicitly, 
> otherwise they open up potential for all kinds of bugs, even when the 
> assumptions being made about the concrete type are simple such as in the 
> case for Equatable/Hashable. There's just too much potential for this 
> kind of reflective protocol implementation to overreach; to me it feels 
> very much like going into a restaurant and the waiter coming across and 
> force-feeding me something I don't want instead of taking my order.
>>> 
>>> I might suggest that instead it is like you have gone into a pizza shop and 
>>> said, “I’d like a large 

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

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

I'm interested in this debate because I've been bitten by automatic synthesis 
recently.

I'm reading your discussion, but I don't have a strong opinion. I only have an 
anecdote: implicit, automatic, and unavoidable code synthesis code can make it 
difficult to write some DSLs (aka Domain-Specific Languages).

I did stumble against undesired Equatable synthesis while developping a 
library[1] that generates SQL snippets. In this library, the `==` operator does 
not return a Bool: it returns an SQL expression:

// SELECT * FROM players WHERE bestScore = 1000
Player.filter(bestScore == 1000)

Since the library is free to define == as an operator that returns an SQL 
expression, this works quite well. Even when both operands have the same type:

// SELECT * FROM players WHERE lastScore = bestScore
Player.filter(lastScore == bestScore)

However, as soon as the type is (also) Equatable, an ambiguity occurs, and the 
DSL is basically broken:

Player.filter(lastScore == bestScore) // which == please?

In this case, the == from synthesized Equatable conformance is not welcome at 
all. It prevents the library from controlling the return type of the == 
operator. Equatable conformance is unavoidable for enums based on String or 
generally any raw value type that adopts Equatable. The consequence is that my 
library can't allow its users to define an enum of table columns.

This is not a deal breaker. Everybody can live with this little caveat, and I 
guess I'm the only one who wishes things had been more *consistent*. But still: 
this story helps realizing that code synthesis can bite in plenty of unexpected 
ways.

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

> Le 7 sept. 2017 à 12:20, Haravikk via swift-evolution 
>  a écrit :
> 
>> 
>> On 7 Sep 2017, at 00:11, Brent Royal-Gordon > > wrote:
>> 
>>> On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
>>> > wrote:
>>> 
>>> This proposal idea is essentially for a new attribute @synthetic (name is 
>>> up for debate). This attribute is required for any default implementation 
>>> that includes reflective type compiler magic, use of the reflection API 
>>> against `self` or, in future, any native Swift macros within the method 
>>> (possibly limited to specific features, will depend on the macro language 
>>> and its capabilities).
>> 
>> 
>> "Use of the reflection API against `self`"? `String(describing:)` and 
>> `String(reflecting:)` sometimes do that.
>> 
>> I see zero justification for having @synthetic cover all of these random 
>> things, but not ordinary default implementations—they have the same amount 
>> of dangerous implicitness.
> 
> Actually they don't; the problem here is that through reflection you are 
> accessing and manipulating concrete types. A non-reflective default 
> implementation only has access to what the protocol itself has defined. The 
> synthetic alternatives are instead diving into parts of a concrete type that 
> may have nothing to do with the protocol at all, and must therefore make 
> assumptions that cannot be guaranteed to be correct, this is what makes them 
> dangerous.
> 
>> On 6 Sep 2017, at 23:43, Nevin Brackett-Rozinsky 
>> > 
>> wrote:
>>> On Wed, Sep 6, 2017 at 5:42 PM, Haravikk via swift-evolution 
>>> > wrote:
>>> the issue I'm trying to raise is that when those, and similar features, are 
>>> used in synthesised behaviour (default implementations based upon the 
>>> concrete type), that these behaviours should be opted into explicitly, 
>>> otherwise they open up potential for all kinds of bugs, even when the 
>>> assumptions being made about the concrete type are simple such as in the 
>>> case for Equatable/Hashable. There's just too much potential for this kind 
>>> of reflective protocol implementation to overreach; to me it feels very 
>>> much like going into a restaurant and the waiter coming across and 
>>> force-feeding me something I don't want instead of taking my order.
>> 
>> I might suggest that instead it is like you have gone into a pizza shop and 
>> said, “I’d like a large veggie pizza please.” And they made you a pizza with 
>> their standard dough and their standard sauce and their standard cheese and 
>> their standard selection of vegetables.
> 
> Actually I don't think that's quite it either; to strain the analogy even 
> further, I'd say it's more like going into a pizza shop and saying "I'd like 
> a pizza" and the staff looking at you and deciding you look like a vegetarian 
> and giving you a vegetarian pizza.
> 
> The crux of the issue here are the assumptions that are being made; for a 
> standard default implementation there are no 

Re: [swift-evolution] Enums and Source Compatibility

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

On 07.09.2017 7:33, 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.


Just small note. As I understand, this is a source breaking suggestion, no?
I mean any client code for 'public enum' coming from another module, will have to add 
'default' case in 'switch'. So, the previously correct code will not compile. Or do 
you suggest to raise a warning only for the first time and raise an error in next 
version of Swift?




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.




I think 'fragile' word does not reflect what is guaranteed for this enum. The author 
guaranteed that this enum will not be changed, not "this enum can broke your code". 
Can't we use 'sealed'/'closed'/'fixed' here?


Vladimir.



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


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


Re: [swift-evolution] Retain cycles in closures

2017-09-07 Thread Alejandro Martinez via swift-evolution
FWIW I wouldn't be oposed to have [guard self] for closures. These
retain cycles are so common that is one the corners that I would like
to have the language helping. Usually people uses weak because that's
what they have been told, and sometimes they risk to use unowned
without fully understanding the consequences just because is more
convenient. In any case I feel that the guard `self` = self trick is
used quite a lot so it may be worth providing language help for it to
make the default case safe and convenient at the same time.

On Thu, Aug 31, 2017 at 12:25 AM, John McCall via swift-evolution
 wrote:
>
> On Aug 30, 2017, at 7:02 PM, Yvo van Beek  wrote:
>
> Hi John,
>
> I see that I've used DispatchQueue.main in my example which is probably a
> poor choice to demonstrate the issue:
>
>   class MyClass {
> let queue = DispatchQueue(label: "MyApp.MyQueue")
>
> func start() {
>   queue.async {
> otherClass.doSomethingThatTakesAWhile()
>   }
>
>   ...
>
>   queue.async {
> self.doSomething()
>   }
> }
>   }
>
> This would create a retain cycle wouldn't it?
>
>
> You're correct that there's a temporary cycle which lasts until the queue
> executes the closure.  However, temporary cycles like this rarely cause
> memory leaks for the same reason that local variables rarely cause memory
> leaks: eventually the closure will be executed or the function will return.
> The only way that a closure on a dispatch queue can cause a memory leak is
> if it constantly enqueues new closures that recreate the same cycle.
>
> If you're doing a dispatch with a very substantial delay (in the hundreds of
> milliseconds), it can still be a good idea to use a weak reference just so
> objects can be collected faster.  But it's not strictly necessary just to
> avoid leaks.
>
> John.
>
>
> - Yvo
>
>
> On Wed, Aug 30, 2017 at 6:48 PM, John McCall  wrote:
>>
>>
>> On Aug 30, 2017, at 6:45 PM, Yvo van Beek via swift-evolution
>>  wrote:
>>
>> When I'm writing code I like it to be free from any distractions that
>> aren't really relevant to the problem that I'm trying to solve. One of these
>> distractions is having to pay a lot of attention to retain cycles. As my
>> code grows, I start making extensions to simplify my code.
>>
>> I've created the following helper for DispatchQueues:
>>
>>   extension DispatchQueue {
>> func async(weak arg: T, execute: @escaping (T) -> Void)
>> {
>>   async { [weak arg] in
>> if let argRef = arg { execute(argRef) }
>>   }
>> }
>>   }
>>
>> It allows you to do this:
>>
>>DispatchQueue.main.async(weak: self) { me in
>> me.updateSomePartOfUI()
>>   }
>>
>>
>> Closures handed off to dispatch queues will not cause retain cycles.
>>
>> John.
>>
>> When functions are passed as a closure, the compiler won't warn about a
>> possible retain cycle (there is no need to prefix with self). That's why
>> I've also created helpers for calling instance functions:
>>
>> func blockFor(_ target: Target, method: @escaping
>> (Target) -> () -> Void) -> () -> Void {
>> return { [weak target] in
>>   if let targetRef = target { method(targetRef)() }
>> }
>>   }
>>
>>   func blockFor(_ target: Target, method:
>> @escaping (Target) -> (Args) -> Void, args: Args) -> () -> Void {
>> return { [weak target] in
>>   if let targetRef = target { method(targetRef)(args) }
>> }
>>   }
>>
>> Calls look like this:
>>
>>   class MyClass {
>> func start() {
>>   performAction(completion: blockFor(self, method: MyClass.done))
>> }
>>
>> func done() {
>>   ...
>> }
>>   }
>>
>> When you look at code samples online or when I'm reviewing code of
>> colleagues this seems a real issue. A lot of people probably aren't aware of
>> the vast amounts of memory that will never be released (until their apps
>> start crashing). I see people just adding self. to silence the complier :(
>>
>> I'm wondering what can be done to make this easier for developers. Maybe
>> introduce a 'guard' keyword for closures which skips the whole closure if
>> the instances aren't around anymore. Since guard is a new keyword in this
>> context it shouldn't break any code?
>>
>>DispatchQueue.main.async { [guard self] in
>> self.updateSomePartOfUI()
>>   }
>>
>> I don't have any ideas yet for a better way to pass functions as closures.
>>
>> - Yvo
>> ___
>> 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
>



-- 
Alejandro Martinez
http://alejandromp.com
___
swift-evolution mailing list
swift-evolution@swift.org

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

2017-09-07 Thread Haravikk via swift-evolution

> On 7 Sep 2017, at 00:11, Brent Royal-Gordon  wrote:
> 
>> On Sep 5, 2017, at 1:02 PM, Haravikk via swift-evolution 
>> > wrote:
>> 
>> This proposal idea is essentially for a new attribute @synthetic (name is up 
>> for debate). This attribute is required for any default implementation that 
>> includes reflective type compiler magic, use of the reflection API against 
>> `self` or, in future, any native Swift macros within the method (possibly 
>> limited to specific features, will depend on the macro language and its 
>> capabilities).
> 
> 
> "Use of the reflection API against `self`"? `String(describing:)` and 
> `String(reflecting:)` sometimes do that.
> 
> I see zero justification for having @synthetic cover all of these random 
> things, but not ordinary default implementations—they have the same amount of 
> dangerous implicitness.

Actually they don't; the problem here is that through reflection you are 
accessing and manipulating concrete types. A non-reflective default 
implementation only has access to what the protocol itself has defined. The 
synthetic alternatives are instead diving into parts of a concrete type that 
may have nothing to do with the protocol at all, and must therefore make 
assumptions that cannot be guaranteed to be correct, this is what makes them 
dangerous.

> On 6 Sep 2017, at 23:43, Nevin Brackett-Rozinsky 
>  wrote:
>> On Wed, Sep 6, 2017 at 5:42 PM, Haravikk via swift-evolution 
>> > wrote:
>> the issue I'm trying to raise is that when those, and similar features, are 
>> used in synthesised behaviour (default implementations based upon the 
>> concrete type), that these behaviours should be opted into explicitly, 
>> otherwise they open up potential for all kinds of bugs, even when the 
>> assumptions being made about the concrete type are simple such as in the 
>> case for Equatable/Hashable. There's just too much potential for this kind 
>> of reflective protocol implementation to overreach; to me it feels very much 
>> like going into a restaurant and the waiter coming across and force-feeding 
>> me something I don't want instead of taking my order.
> 
> I might suggest that instead it is like you have gone into a pizza shop and 
> said, “I’d like a large veggie pizza please.” And they made you a pizza with 
> their standard dough and their standard sauce and their standard cheese and 
> their standard selection of vegetables.

Actually I don't think that's quite it either; to strain the analogy even 
further, I'd say it's more like going into a pizza shop and saying "I'd like a 
pizza" and the staff looking at you and deciding you look like a vegetarian and 
giving you a vegetarian pizza.

The crux of the issue here are the assumptions that are being made; for a 
standard default implementation there are no assumptions, because you're 
operating on the basis of methods and properties that you yourself have defined 
as the protocol creator that, where properly implemented, have precisely 
defined requirements, behaviours etc. When you're doing it with some form of 
compile-time or run-time reflection however you're messing around with parts of 
a concrete type that the protocol itself doesn't actually know anything about 
with any certainty.

It's the same reason that run-time reflection isn't something you should ever 
want to do, because while it might work with all of the types you test 
directly, if it supports arbitrary types (which it'd need to, or there'd be no 
point to reflecting) then there's always the risk of encountering a type where 
some part of it doesn't match the assumptions that you've made. Of course there 
are use-cases where this may not matter, e.g- if you're just dumping data from 
a type and don't really care if you're storing stuff that isn't important, but 
in other cases such as Equatable and Hashable it can make a difference, as it 
can drastically affect behaviour when those assumptions fail.

> On 7 Sep 2017, at 05:00, Andrew Thompson  wrote:
> Perhaps we could find a solution by meeting in the middle. Introduce a 
> compiler flag that will disable the automatic synthesis and revert to the old 
> behaviour (i.e. swiftc main.swift —disable-automatic-synthesis )

Thanks for the suggestion, but that's a bit too all-or-nothing; I realise I 
might seem very negative but to be clear, I do want these synthesised features, 
I just don't want them in their current form. What I want is for them to be 
explicitly opted into where I, as the developer, need them to be, so that I'm 
in absolute, unambiguous control of when and where they are used.

I do absolutely support features that eliminate tedious boiler-plate, I just 
think that doing so implicitly in invasive ways is not the right way to do it.

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

2017-09-07 Thread Howard Lovatt via swift-evolution
I would argue that given:

foo()
await bar()
baz()

That foo and baz should run on the same queue (using queue in the GCD
sense) but bar should determine which queue it runs on. I say this because:

   1. foo and baz are running synchronously with respect to each other
   (though they could be running asynchronously with respect to some other
   process if all the lines shown are inside an async function).
   2. bar is running asynchronously relative to foo and baz, potentially on
   a different queue.

I say bar is potentially on a different queue because the user of bar, the
person who wrote these 3 lines above, cannot be presumed to be the writer
of foo, baz, and particularly not bar and therefore have no detailed
knowledge about which queue is appropriate.

Therefore I would suggest either using a Future or expanding async so that
you can say:

func bar() async(qos: .userInitiated) { ... }

You also probably need the ability to specify a timeout and queue type,
e.g.:

   func bar() async(type: .serial, qos: .utility, timeout: .seconds(10))
throws { ... }

If a timeout is specified then await would have to throw to enable the
timeout, i.e. call would become:

   try await bar()

Defaults could be provided for qos (.default works well), timeout (1 second
works well), and type (.concurrent works well).

However a Future does all this already :).

  -- Howard.

On 7 September 2017 at 15:13, David Hart via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> > On 7 Sep 2017, at 07:05, Chris Lattner via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> >
> >> On Sep 5, 2017, at 7:31 PM, Eagle Offshore via swift-evolution <
> swift-evolution@swift.org> 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
>
___
swift-evolution mailing list
swift-evolution@swift.org

[swift-evolution] Find/split on sub-string/sequence

2017-09-07 Thread Daryle Walker via swift-evolution
There are sequence/collection/string methods to find an element/character or 
split a container on an element or one of a set of elements. But I haven't 
noticed methods that split on a sub-string, like wanting to split a string on 
exactly CR-LF and not on either individually. 

Shouldn't we add that? And a general version for sequences/collections. (I 
don't know if either the searched object and/or the match sub-object need to be 
a sequence or a collection.)

Sent from my iPhone
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution