I’m not @Andrew_Trick and won’t speak for him, but I’ll add a voice here: ideally, you never alias. The moment you allow aliasing pointers you greatly hamstring the compiler’s ability to make optimizations: in particular, loads and stores cannot be arbitrarily omitted or re-ordered because the compiler has no idea if they affect each other. In practice you create a zone of the program within which all loads/stores must be maximally pessimistic and assume that any operation that touches any other memory may have affected the load/store that you’re about to do.
So in general, much better than aliasing is…well…not aliasing. You can almost always avoid aliasing by performing bytewise copies and then binding the new memory location. That allows you to spill to the stack, for example, to create appropriately typed temporaries. While the copy is a mild performance penalty, it unlocks substantial optimization possibility within the compiler that will almost certainly pay itself back.
So, to clarify: if Swift seems to have the ability to say “let me alias”, that is an unfortunate confusion. Swift’s aliasing rules are very simple: you may never alias typed pointers with other typed pointers. If you have a typed memory region, you may only access it either as that type or as a raw pointer. You may never alias it. From this, the rules of the Swift operations follow:
bindMemory(to:)
establishes a new binding. If the new binding matches other bound pointers in the program no alias has been established and those other pointers may be used freely. If the new binding is to a different type, all other bound pointers are invalidated and using them invokes undefined behaviour, i.e. aliasing is forbidden.assumingMemoryBound
isbindMemory
but you invoke undefined behaviour earlier in the process, at the point of making the assumption. In principle Swift could have a runtime memory aliasing checker that would validate this assumption for you. It’s only safe to use when you know where the pointer came from: otherwise it’s unsafe.withMemoryRebound
is the union of twobind
operations:bind
to the new pointer type, followed bybind
back to the original type. As it’s a composition of twobind
operations the semantics should follow from (1): during the block it is a undefined behaviour to access this memory as its original type.
So I agree with @Andrew_Trick and @Karl: we do not want to make it easy to alias memory, we want to make it easier to perform type punning, and easier to interoperate with C. Andy has marked this out above with the most obvious missing piece: temporarily binding a raw pointer, which would ease C interop enormously. Other than that, the advice for type punning is usually to use raw memory and load
/store
: those should be enhanced to allow unaligned loads/stores.