> On Jul 12, 2017, at 12:16 PM, Taylor Swift via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> Hi all, I’ve written up a proposal to modify the unsafe pointer API for 
> greater consistency, safety, and ease of use.
> 
> ~~~
> 
> Swift currently offers two sets of pointer types — singular pointers such as 
> UnsafeMutablePointer, and vector (buffer) pointers such as 
> UnsafeMutableBufferPointer. This implies a natural separation of tasks the 
> two kinds of pointers are meant to do. For example, buffer pointers implement 
> Collection conformance, while singular pointers do not.
> 
> However, some aspects of the pointer design contradict these implied roles. 
> It is possible to allocate an arbitrary number of instances from a type 
> method on a singular pointer, but not from a buffer pointer. The result of 
> such an operation returns a singular pointer, even though a buffer pointer 
> would be more appropriate to capture the information about the number of 
> instances allocated. It’s possible to subscript into a singular pointer, even 
> though they are not real Collections. Some parts of the current design turn 
> UnsafePointers into downright DangerousPointers, leading users to believe 
> that they have allocated or freed memory when in fact, they have not.
> 
> This proposal seeks to iron out these inconsistencies, and offer a more 
> convenient, more sensible, and less bug-prone API for Swift pointers.
> 
> <https://gist.github.com/kelvin13/a9c033193a28b1d4960a89b25fbffb06 
> <https://gist.github.com/kelvin13/a9c033193a28b1d4960a89b25fbffb06>>
> 
> ~~~
> 

Thanks for taking time to write this up.

General comments:

UnsafeBufferPointer is an API layer on top of UnsafePointer. The role
of UnsafeBufferPointer is direct memory access sans lifetime
management with Collection semantics. The role of UnsafePointer is
primarily C interop. Those C APIs should be wrapped in Swift APIs that
take UnsafeBufferPointer whenever the pointer represents a C array. I
suppose making UnsafePointer less convenient would push developers
toward UnsafeBufferPointer. I don't think that's worth outright
breaking source, but gradual deprecation of convenience methods, like
`susbscript` might be acceptable.

I have mixed feelings about stripping UnsafePointer of basic
functionality. Besides breaking source, doing that would be
inconsistent with its role as a lower API layer. The advantage would
just be descreasing API surface area and forcing developers to use a
higher-level API.

The additive changes you propose are fairly obvious. See [SR-3088]
UnsafeMutableBufferPointer doesn't have an allocating init.

I haven't wanted to waste review cycles on small additive
changes. It may make sense to batch them up into one coherent
proposal. Here are a few more to consider.

- [SR-3929] UnsafeBufferPointer should have init from mutable
- [SR-4340] UnsafeBufferPointer needs a withMemoryRebound method
- [SR-3087] No way to arbitrarily initialise an Array's storage

Point by point:

> drop the capacity parameter from UnsafeMutablePointer.allocate() and 
> deallocate().

I do not agree with removing the capacity parameter and adding a
single-instance allocation API. UnsafePointer was not designed for
single instances, it was primarily designed for C-style arrays. I
don't see the value in providing a different unsafe API for single
vs. multiple values.

I agree the primary allocation API should be
UnsafeMutableBufferPointer.allocate(capacity:). There is an argument
to be made for removing UnsafeMutablePointer.allocate(capacity:)
entirely. But, as Michael Ilseman pointed out, that would involve
reevaluating several other members of the UnsafePointer API. I think
it's reasonable for UnsafePointer to retain all its functionality as a
lower level API.

I don't understand what is misleading about
UnsafePointer.deallocate(capacity:). It *is* inconvenienent for the
user to keep track of memory capacity. Presumably that was done so
either the implementation can move away from malloc/free or some sort
of memory tracking can be implemented on the standard library
side. Obviously, UnsafeBufferPointer.deallocate() would be cleaner in
most cases.

> add an allocate(count:) type method to UnsafeMutableBufferPointer

`capacity` should be used for allocating uninitialized memory not
`count`. `count` should only refer to a number of initialized objects!

> add a deallocate() instance method to UnsafeMutableBufferPointer

Yes, of course! I added a mention of that in SR-3088.

> remove subscripts from UnsafePointer and UnsafeMutablePointer

It's often more clear to perform arithmetic on C array indices rather
than pointers. That said, I'm happy to push developers to use
UnsafeBufferPointer whenever that have a known capacity. To me, this
is a question of whether the benefit of making a dangerous thing less
convenient is worth breaking source compatibility.

-Andy

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

Reply via email to