> 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