/// // clone the vector as we will reuse them later
/// let v_clone = v_orig.clone();
///
- /// // Using transmute: this is Undefined Behavior, and a bad idea.
+ /// // Using transmute: this relies on the unspecified data layout of `Vec`, which is a
+ /// // bad idea and could cause Undefined Behavior.
/// // However, it is no-copy.
/// let v_transmuted = unsafe {
/// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
///
/// let v_clone = v_orig.clone();
///
- /// // The no-copy, unsafe way, still using transmute, but not UB.
- /// // This is equivalent to the original, but safer, and reuses the
- /// // same `Vec` internals. Therefore, the new inner type must have the
- /// // exact same size, and the same alignment, as the old type.
+ /// // The no-copy, unsafe way, still using transmute, but not relying on the data layout.
+ /// // Like the first approach, this reuses the `Vec` internals.
+ /// // Therefore, the new inner type must have the
+ /// // exact same size, *and the same alignment*, as the old type.
/// // The same caveats exist for this method as transmute, for
/// // the original inner type (`&i32`) to the converted inner type
- /// // (`Option<&i32>`), so read the nomicon pages linked above.
+ /// // (`Option<&i32>`), so read the nomicon pages linked above and also
+ /// // consult the [`from_raw_parts`] documentation.
/// let v_from_raw = unsafe {
// FIXME Update this when vec_into_raw_parts is stabilized
/// // Ensure the original vector is not dropped.
/// };
/// ```
///
+ /// [`from_raw_parts`]: ../../std/vec/struct.Vec.html#method.from_raw_parts
+ ///
/// Implementing `split_at_mut`:
///
/// ```
}
/// Checks whether the regions of memory starting at `src` and `dst` of size
-/// `count * size_of::<T>()` overlap.
-fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
+/// `count * size_of::<T>()` do *not* overlap.
+pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
let src_usize = src as usize;
let dst_usize = dst as usize;
let size = mem::size_of::<T>().checked_mul(count).unwrap();
let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
- size > diff
+ // If the absolute distance between the ptrs is at least as big as the size of the buffer,
+ // they do not overlap.
+ diff >= size
}
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
- debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory");
+ debug_assert!(is_nonoverlapping(src, dst, count), "attempt to copy to overlapping memory");
copy_nonoverlapping(src, dst, count)
}