> 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

Reply via email to