[swift-evolution] SE-184 Improved Pointers

Taylor Swift kelvin13ma at gmail.com
Tue Aug 22 00:59:46 CDT 2017

On Mon, Aug 21, 2017 at 11:09 PM, Andrew Trick <atrick at apple.com> wrote:

> On Aug 20, 2017, at 6:03 PM, Taylor Swift <kelvin13ma at gmail.com> wrote:
> New draft of the proposal is up here: <https://github.com/kelvin13/
> swift-evolution/blob/patch-3/proposals/0184-improved-pointers.md>
> Important changes start here
> <https://github.com/kelvin13/swift-evolution/blob/patch-3/proposals/0184-improved-pointers.md#proposed-solution>
> .
> I have more feedback for you after discussing with Ben and Michael.
> Under the section "Background". The retaining/releasing counts are
> confusing because we normally talk about "+0/+1" with respect to a single
> value. Here you're summing the reference count effect across different
> source and destination values. I think you can drop the -1/+0/+1 from the
> cell labels and just label the headers as "Source-Copy(+1) vs.
> Source-Move(+0)" and "Dest-Initializing(+0)" vs. "Dest-Destroying(-1)".

I got rid of the total counts, but I used “retaining” and “releasing”
because the word “initialize” is already way overloaded in the document and
using it as a category in addition to referring to the actual method family
`initialize` and `initializeMemory` and Swift’s `init` initializers would
just get too confusing.

> Ben noticed that we still don't have `UnsafeMutableBufferPointer.deallocate()`.
> Please add that as well.

This is in the implementation and 2/3 of the API mocks; idk why it was lost
in the detailed changes section. That was a typo I just fixed it

> I think you should also add the default `alignedTo:Int =
> MemoryLayout<UInt>.alignment` to `UnsafeRawMutablePointer`. It is
> effectively part of Swift's memory model... [Background: We're providing a
> language level default guarantee of word-aligned storage. We don't want to
> expose the platform's default alignment. There is no such thing as a
> "maximal" alignment for all imported primitive types. We expect allocators
> to typically provide 16-byte alignment, but when developers are relying on
> that for correctness, we want it to be explicit. Developers usually rely on
> word alignment so there's no value in making that explicit.]

done and committed

> The source breaking changes can be marked deprecated for now, but can only
> be marked unavailable in Swift 5 mode or later.

done and committed

> We anticipate adding a ContiguouslyStored protocol "soon", which could be
> used to reduce the amount of overloading on the buffer
> `initialize`/`assign` APIs. But we need a lot more time to iterate on that
> design and it doesn't appear that migrating to it would be source breaking
> w.r.t. your proposal.
> I think we would be receptive to a "non-Optional baseAddress" proposal now
> if you or anyone else wants to pitch that. I know Dave Abrahams had a
> working implementation at some point. That would weaken some of the
> incentive to continue adding more convenience to buffer slices.

Really early versions of this proposal pitched that but it didn’t go so
well. also making baseAddress nonnillable means you don’t always have
access to `count` when `count == 0`

> Sorry to bring this up again, but I was not able to defend the addition of
> `UnsafeMutableBufferPointer.deinitialize()`. It is incorrect for the
> typical use case and doesn't appear to solve any important use case. The
> *only* fully initializing method is `initialize(repeating:)`, but that will
> usually be used for trivial values, which should not be deinitialized. It's
> preferable for the user to explicitly deinitialize just the segments that
> they know were initialized, which can be done on the base pointer. The only
> benefit in having a `deinitialize` on the buffer is to communicate to users
> who see the `initialize` API for the first time that it is their
> responsibility to deinitialize if the type requires it. To that end, we
> could add a `deinitialize(at:count:)` method, communicating the symmetry
> with `initialize(at:from:). Naturally `index + count <= self.count`.
> -Andy

I don’t agree with this. If `deinitialize()` is a problem because it
deinitializes the entire buffer, so are `moveAssign` and `moveInitialize`.
They all assume the released buffer operand is fully initialized. `
deinitialize()` has just as much use as the other full-buffer releasing
methods. Just take the image buffer example there

let pixels:Int = scanlines.map{ $0.count }.reduce(0, +)var image =
UnsafeMutableBufferPointer<Pixel>.allocate(capacity: pixels)
var filled:Int = 0for scanline:UnsafeMutableBufferPointer<Pixel> in scanlines
    image.moveInitialize(at: filled, from: scanline)
    filled += scanline.count


and replace `Pixel` with a class type like `UIButton`.

And `deinitialize(at:count:)` is bad because you’re asking for a count on a
buffer method. `moveAssign` and `moveInitialize` can take range parameters
because they each have a second operand that supplies the count number. `
deinitialize` doesn’t. That means calls could end up looking like

buffer.deinitialize(at: 0, count: buffer.count)

which is exactly what we were trying to avoid in the first place.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170822/9675a29d/attachment.html>

More information about the swift-evolution mailing list