rune_alloc/ptr.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
//! This module contains (hopefully sound) re-implementations of unstable
//! `core::ptr` APIs.
pub(crate) use self::unique::Unique;
mod unique;
use core::mem;
pub(crate) use core::ptr::NonNull;
// Stable re-exports.
pub(crate) use core::ptr::{
addr_of, addr_of_mut, copy, copy_nonoverlapping, drop_in_place, read, slice_from_raw_parts_mut,
write,
};
pub(crate) const unsafe fn nonnull_add<T>(this: NonNull<T>, delta: usize) -> NonNull<T>
where
T: Sized,
{
// SAFETY: We require that the delta stays in-bounds of the object, and
// thus it cannot become null, as that would require wrapping the
// address space, which no legal objects are allowed to do.
// And the caller promised the `delta` is sound to add.
let pointer = this.as_ptr();
unsafe { NonNull::new_unchecked(pointer.add(delta)) }
}
pub(crate) const unsafe fn nonnull_sub<T>(this: NonNull<T>, delta: usize) -> NonNull<T>
where
T: Sized,
{
// SAFETY: We require that the delta stays in-bounds of the object, and
// thus it cannot become null, as that would require wrapping the
// address space, which no legal objects are allowed to do.
// And the caller promised the `delta` is sound to add.
let pointer = this.as_ptr();
unsafe { NonNull::new_unchecked(pointer.sub(delta)) }
}
#[inline(always)]
#[allow(clippy::useless_transmute)]
pub const fn invalid<T>(addr: usize) -> *const T {
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
// We use transmute rather than a cast so tools like Miri can tell that this
// is *not* the same as from_exposed_addr.
// SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
// pointer).
unsafe { mem::transmute(addr) }
}
#[inline(always)]
#[allow(clippy::useless_transmute)]
pub const fn invalid_mut<T>(addr: usize) -> *mut T {
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
// We use transmute rather than a cast so tools like Miri can tell that this
// is *not* the same as from_exposed_addr.
// SAFETY: every valid integer is also a valid pointer (as long as you don't dereference that
// pointer).
unsafe { mem::transmute(addr) }
}
cfg_if! {
if #[cfg(rune_nightly)] {
#[inline(always)]
pub(crate) unsafe fn sub_ptr<T>(from: *const T, to: *const T) -> usize {
from.sub_ptr(to)
}
} else {
#[inline(always)]
pub(crate) unsafe fn sub_ptr<T>(from: *const T, to: *const T) -> usize {
const {
let pointee_size = mem::size_of::<T>();
assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
}
debug_assert!(addr(from) >= addr(to));
addr(from).wrapping_sub(addr(to)).saturating_div(mem::size_of::<T>())
}
}
}
cfg_if! {
if #[cfg(rune_nightly)] {
#[inline(always)]
pub(crate) fn addr<T>(from: *const T) -> usize {
from.addr()
}
} else {
#[inline(always)]
pub(crate) fn addr<T>(from: *const T) -> usize {
from as usize
}
}
}
cfg_if! {
if #[cfg(rune_nightly)] {
#[inline(always)]
pub(crate) fn slice_len<T>(from: *const [T]) -> usize {
from.len()
}
} else {
#[inline(always)]
pub(crate) fn slice_len<T>(from: *const [T]) -> usize {
// SAFETY: This is *a bit* tricky, but the raw pointer contains the
// length and *should* be safe to dereference like this. However,
// walking through the dereferenced `[T]` is not necessarily
// correct.
unsafe { (*from).len() }
}
}
}