Currently, these functions do not say anything about whether the raw pointer has to be aligned. They are also currently implemented with copy_nonoverlapping, which means they are safe to use with unaligned data. However, @ubsan tells me that this is an implementation detail that cannot be relied on.
In any case, these functions should explicitly specify their alignment requirements. Similarly, ptr::copy{,_nonoverlapping} also should do that, since right now they do not explicitly state that in their contract either. (They do reference C's memcpy and memmove, but I don't think that a C reference is a good way to define normative semantics.)
ping @Amanieu
Also keep in mind that copy(_nonoverlapping) _does_ have alignment requirements: it's based on the type of the pointer. So if you pass a *mut u32 to copy_nonoverlapping then LLVM will assume that the pointer is aligned to 4 bytes.
That then should be explicitly specified also, because it is _definitely_ not a part of the C memcpy semantics.
Maybe it's obvious in this discussion, but *ptr (copy to value from raw pointer) requires ptr to be aligned, of course. With that as the baseline, I think it would have to be assumed that read/write use that rule if nothing else is documented -- but why not document it explicitly.
@bluss That's also never documented, to be clear, except in the not-right-places in the nomicon.
Seems to be fixed, the documentation says:
The pointer must be aligned; use
write_unalignedif that is not the case.
and similarly for ptr::read.
Recommend closing as fixed.
copy{,_nonoverlapping} don't have mention of alignment in the documentation still.
@whitequark
That's because it has none.
Also keep in mind that copy(_nonoverlapping) does have alignment requirements: it's based on the type of the pointer. So if you pass a *mut u32 to copy_nonoverlapping then LLVM will assume that the pointer is aligned to 4 bytes.
@Amanieu above disagrees...
The linked RFC (by @Amanieu) states that it uses copy_nonoverlapping for {read,write}_unaligned.
@whitequark
I had the mistaken impression that copy_nonoverlapping took a u8 parameter.
Okay, so this appears to be a documentation issue -- we need to update ptr::copy{,_nonoverlapping} to state something about alignment.
The docs team discussed this today. Here's the current state of the ptr module, with respect to alignment:
<ubsan> because anything in the standard library which takes a raw pointer assumes validity of the
raw pointer, unless it's explicitly denoted `_unaligned`, in which case size must be valid,
but alignment might not be
(...)
<ubsan> copy{_nonoverlapping}, read_volatile, probably replace, probably swap (uses "valid",
probably could be more wordy), write_volatile, swap_nonoverlapping
<ubsan> we should also standardize this documentation across all of the functions
(...)
<ubsan> (some put their requirements under "Safety", some put it under "Undefined Behavior", etc.)
Basically, to really close this issue it would be prudent to go over every function in ptr and leave a note about the assumed alignment requirements of it.
Since https://github.com/rust-lang/rust/issues/29371 is still open, i'm considering this issue part of that one.
@steveklabnik. This was completed in #53783. All functions in std::ptr now state their alignment requirements in the "Safety" section.
Thank you!
Most helpful comment
Maybe it's obvious in this discussion, but
*ptr(copy to value from raw pointer) requires ptr to be aligned, of course. With that as the baseline, I think it would have to be assumed that read/write use that rule if nothing else is documented -- but why not document it explicitly.