> On May 19, 2016, at 10:35 PM, Russ Bishop <[email protected]> wrote: > > >> >> UnsafeBytePointer API for In-Memory Layout >> >> UnsafePointer and UnsafeMutable refer to a typed region of memory, and the >> compiler must be able to assume that UnsafePointer element (Pointee) type is >> consistent with other access to the same memory. See proposed Type Safe >> Memory Access documentation >> <https://github.com/atrick/swift/blob/type-safe-mem-docs/docs/TypeSafeMemory.rst>. >> Consequently, conversion between UnsafePointer element types exposes an >> easy way to abuse the type system. >> > > I don’t necessarily disagree with the proposal but I think we should clearly > answer the following question:
I think these are two questions: > Why doesn’t UnsafePointer<T>(_: UnsafePointer<U>) read as UnsafePointer<T>(_: > UnsafePointer<Void>). That is to say you can only “type pun” through a Void > pointer. That’s a reasonable request and would definitely ease migration. However, it still communicates to the user that type punning is a normal, expected use of UnsafePointer. Also, it doesn’t allow all uses of potentially type punning to be identified through code inspection. I know how helpful that feature is because I’ve been auditing code for potential undefined behavior. > A convenience method could be offered, something like > UnsafePointer.reinterpretBytes<U>(_ ptr: UnsafePointer<U>, as: U.Type) -> U > so all valid cases of type punning can be explicit. Maybe you mean UnsafePointer.reinterpretBytes<U>(as: U.Type) -> U That’s a possibility. It’s slightly reminiscent of my first attempt to deal with this problem. However, simply as a convenience it’s too similar to unsafeBitCast(p[0], to: U.self) assuming you know the types are layout compatible. With my proposal you could now do UnsafeBytePointer(p).load(U.self), which is overall a much more clear, safer design. >> As motivation for such an API, consider that an UnsafePointer<Void> or >> OpaquePointer may be currently be obtained from an external API. However, >> the developer may know the memory layout and may want to read or write >> elements whose types are compatible with that layout. This a reasonable use >> case, but unless the developer can guarantee that all accesses to the same >> memory location have the same type, then they cannot use UnsafePointer to >> access the memory without risking undefined behavior. >> > IMHO if we had a @packed attribute a lot of this nonsense could be made > explicit by defining a Swift struct that had the appropriate memory layout. > This is how a lot of “PInvoke” stuff was done in the C# world. It also gives > you an “out” if you need a very specific layout in memory for some other > reason. I think think that’s complementary and addresses the usability of doing manual layout. >> Just as with unsafeBitCast, although the destination of the cast can usually >> be inferred, we want the developer to explicitly state the intended >> destination type, both because type inferrence can be surprising, and >> because it's important to the reader for code comprehension. >> > I’d definitely prefer a labelled initializer, especially one with an uncommon > name. IMHO It should immediately stand out in code reviews. Well, I agree with that sentiment. I would even be fine with a freestanding function to make it really clear, but that defies convention. I’m looking for people to weigh in. Once of the reasons I finished migrating the stdlib (multiple times), is so that proposal reviewers can look at my branch see the real effects of the proposal. My first implementation was something like UnsafePointer.init(unsafePointerCast: p). I’ve actually gotten strong feedback to force the destination type to be spelled, and shorten the label. I could probably dig up an earlier version of the changes. I have to admit though that the UnsafePointer(p, to: U.self) syntax tends to read better and at least there’s an easy regex that can pick up on it. >> Note: For API clarity we could consider a typealias for VoidPointer. A >> separate VoidPointer type would not be very useful--there's no danger that >> UnsafeBytePointer will be casually dereferenced, and no danger in allowing >> pointer arithmetic since the only reasonable interpretation is that of a >> byte-addressable memory. >> > Agreed; even today messing with UnsafeMutablePointer<Void> requires you to > understand that the size corresponds to bytes which is not intuitive. Ah, that’s good feedback in favor of replacing UnsafePointer<Void> and its status as imported type! >> Loading from and storing to memory via an Unsafe[Mutable]BytePointer is safe >> independent of the type of value being loaded or stored and independent of >> the memory's allocated type as long as layout guarantees are met (per the >> ABI). This allows legal type punning within Swift and allows Swift code to >> access a common region of memory that may be shared across an external >> interface that does not provide type safety guarantees. Accessing type >> punned memory directly through a designated Unsafe[Mutable]BytePointer type >> provides sound basis for compiler implementation of strict aliasing. This is >> in contrast with the approach of simply providing a special unsafe pointer >> cast operation for bypassing type safety, which cannot be reliably >> implemented. >> > > I’m not sure how to word it but I feel like some of this might help if it > were included at the very beginning so people understand why this is a > problem. I also think the stdlib docs should have a lot more to say about the > rules, undefined behavior, and the consequences thereof. That will be all > that a lot of developers ever bother to learn on the subject (a shame but out > of scope for a swift evolution proposal :) ) I thought that including the link to proposed Type Safe Memory Access documentation <https://github.com/atrick/swift/blob/type-safe-mem-docs/docs/TypeSafeMemory.rst> in the first paragraph was sufficient. But reviewers seem to be skipping over it! Andy
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
