There is a lot of value in these being mutating functions when working with C 
APIs that need a buffer for it to write to.

If you have a collection and ensure it had allocated it's memory, you can then 
have the C API write directly into the collection's storage avoiding extra copy 
operations.

I personally take advantage of this a lot. Because I'm wrapping a C library in 
Swift as part of my work.

If this was changed to only non mutating functions, it still wouldn't be able 
to guarantee that the buffer isn't mutating the collection without always doing 
a deep copy. It is very easy to go from an UnsafeBufferPointer -> 
UnsafeMutableBufferPointer and have people change things.

> On Oct 14, 2017, at 7:11 AM, Martin R via swift-users <swift-users@swift.org> 
> wrote:
> 
> 
>> On 14. Oct 2017, at 13:15, Geordie Jay via swift-users 
>> <swift-users@swift.org> wrote:
>> 
>> Chris Lattner <clatt...@nondot.org> schrieb am Sa. 14. Okt. 2017 um 05:18:
>> 
>>> On Oct 13, 2017, at 7:40 PM, Andrew Trick via swift-users 
>>> <swift-users@swift.org> wrote:
>>> 
>>> 
>>> 
>>>> On Oct 12, 2017, at 3:52 AM, Geordie Jay via swift-users 
>>>> <swift-users@swift.org> wrote:
>>>> 
>>>> 
>>>> Guillaume Lessard via swift-users <swift-users@swift.org> schrieb am Mi. 
>>>> 11. Okt. 2017 um 23:49:
>>>> A lot of the MutableCollection implementation is in protocol extensions 
>>>> (swapAt, for example.)
>>>> 
>>>> Should an additional version be written just for the Unsafe*BufferPointer 
>>>> types?
>>>> 
>>>> Makes sense to me, given the examples above. It doesn’t seem to be a high 
>>>> priority task though, and one one suited to a contributor pull request 
>>>> rather than taking resources away from the core team.
>>>> 
>>>> Would this kind of change need to go through swift evolution or is it a 
>>>> “no brainer”?
>>>> 
>>>> Geordie
>>> 
>>> I’ll just point out that it’s already the case that methods defined in 
>>> Unsafe*BufferPointer that write to memory are “nonmutating”. So I think 
>>> it’s both a “no brainer” and needs to go through evolution.
>> 
>> I’m not familiar with the specifics of this “proposal” but if it really is 
>> just moving something obvious from being a mutating member to a nonmutating 
>> member, then I’m sure the core team can find a fast-path way to accept it 
>> without a formal review period.
>> 
>> I’m not 100% sure either tbh, although I can imagine putting in a PR for it 
>> once i understand it.
>> 
>> The issue with changing .swapTo (et al.?) to nonmutating is that 
>> semantically it really is a mutation. But pointers as collections have 
>> different mutation semantics to other collections: Mutating an Array’s 
>> storage is the same as mutating its value, whereas a pointer’s value is its 
>> address, not its storage.
>> 
>> Making the Unsafe*Pointer MutableCollection methods themselves nonmutating 
>> probably wouldn’t be a source-breaking change (it’d just lower the “bar of 
>> entry” to include let constant instances too). I imagine this is 
>> noncontroversial.
>> 
>> The original question though was about why .withUnsafeMutableBufferPointer 
>> takes a closure whose first argument is an *inout* 
>> UnsafeMutableBufferPointer, implying that its base address could legally be 
>> mutated. This was probably done to ease use of MutableCollection methods 
>> given the var parameter. That would no longer be necessary given the first 
>> change.
>> 
>> But removing the inout attribute would be source-breaking. And maybe people 
>> really are moving around the array storage’s base address? This seems like a 
>> very bad idea to me but it’s currently part of that API contract. In any 
>> case this change would need to go through evolution, right?
> 
> At present, the withUnsafeMutableBufferPointer() method verifies that the 
> base address has not been modified upon return from the closure: 
> 
>    
> https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb#L1750
> 
>    // Put the working array back before returning.
>    defer {
>      _precondition(
>        inoutBufferPointer.baseAddress == pointer &&
>        inoutBufferPointer.count == count,
>        "${Self} withUnsafeMutableBufferPointer: replacing the buffer is not 
> allowed")
> 
>      (work, self) = (self, work)
>    }
> 
> That check would become obsolete if the buffer pointer is a constant.
> 
> As far as I can see, MutableCollection defines four mutating methods: 
> swapAt(), sort(), reverse(), and partition(). Implementing those as 
> non-mutating methods of UnsafeMutableBufferPointer seems natural to me.
> 
> In addition, it would allow to make the closure parameter in 
> withUnsafeMutableBufferPointer() a constant. Mutating that pointer in the 
> closure is not allowed anyway. 
> 
> Btw, I came up with these questions because I noticed that this compiles:
> 
>    func foo(bufptr: UnsafeMutableBufferPointer<Int>) { }
>    var a = [1, 2, 3, 4, 5]
>    a.withUnsafeMutableBufferPointer { foo(bufptr: $0) }
> 
> but this does not compile:
> 
>    a.withUnsafeMutableBufferPointer(foo)
>    // error: cannot convert value of type '(UnsafeMutableBufferPointer<Int>) 
> -> ()'
>    // to expected argument type '(inout UnsafeMutableBufferPointer<Int>) -> _'
> 
> which looks strange at first sight. With a constant closure parameter, the 
> second version would compile as well.
> 
> Any advice how to proceed with this "issue" would be appreciated: File a bug 
> report? Post on swift-evolution? Make a proposal? ... However, I am not 
> familiar with those evolution procedures. I won't mind to sidestep if someone 
> else want to jump in. 
> 
> Martin
> 
>> 
>> - Geordie
>> 
>> 
>> -Chris
>> 
>> 
>> _______________________________________________
>> swift-users mailing list
>> swift-users@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
> 
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to