> 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