mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Allow calculating the layout behind a pointer
Let align/size_of_of_val intrinsics work on ptrs
This commit is contained in:
parent
564758c4c3
commit
dd973d1b12
@ -140,6 +140,42 @@ impl Layout {
|
||||
unsafe { Layout::from_size_align_unchecked(size, align) }
|
||||
}
|
||||
|
||||
/// Produces layout describing a record that could be used to
|
||||
/// allocate backing structure for `T` (which could be a trait
|
||||
/// or other unsized type like a slice).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is only safe to call if the following conditions hold:
|
||||
///
|
||||
/// - If `T` is `Sized`, this function is always safe to call.
|
||||
/// - If the unsized tail of `T` is:
|
||||
/// - a [slice], then the length of the slice tail must be an intialized
|
||||
/// integer, and the size of the *entire value*
|
||||
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
|
||||
/// - a [trait object], then the vtable part of the pointer must point
|
||||
/// to a valid vtable acquired by an unsizing coersion, and the size
|
||||
/// of the *entire value* (dynamic tail length + statically sized prefix)
|
||||
/// must fit in `isize`.
|
||||
/// - an (unstable) [extern type], then this function is always safe to
|
||||
/// call, but may panic or otherwise return the wrong value, as the
|
||||
/// extern type's layout is not known. This is the same behavior as
|
||||
/// [`Layout::for_value`] on a reference to an extern type tail.
|
||||
/// - otherwise, it is conservatively not allowed to call this function.
|
||||
///
|
||||
/// [slice]: ../../std/primitive.slice.html
|
||||
/// [trait object]: ../../book/ch17-02-trait-objects.html
|
||||
/// [extern type]: ../../unstable-book/language-features/extern-types.html
|
||||
#[inline]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "layout_for_ptr", issue = "69835")]
|
||||
pub unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
|
||||
let (size, align) = (mem::size_of_val_raw(t), mem::align_of_val_raw(t));
|
||||
// See rationale in `new` for why this is using an unsafe variant below
|
||||
debug_assert!(Layout::from_size_align(size, align).is_ok());
|
||||
Layout::from_size_align_unchecked(size, align)
|
||||
}
|
||||
|
||||
/// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
|
||||
///
|
||||
/// Note that the pointer value may potentially represent a valid pointer,
|
||||
|
@ -980,13 +980,24 @@ extern "rust-intrinsic" {
|
||||
///
|
||||
/// The stabilized version of this intrinsic is
|
||||
/// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html).
|
||||
#[cfg(bootstrap)]
|
||||
pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
|
||||
/// The minimum alignment of the type of the value that `val` points to.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is
|
||||
/// [`std::mem::min_align_of_val`](../../std/mem/fn.min_align_of_val.html).
|
||||
#[cfg(bootstrap)]
|
||||
pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
|
||||
|
||||
/// The size of the referenced value in bytes.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is
|
||||
/// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html).
|
||||
#[cfg(not(bootstrap))]
|
||||
pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
|
||||
#[cfg(not(bootstrap))]
|
||||
pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
|
||||
|
||||
/// Gets a static string slice containing the name of a type.
|
||||
///
|
||||
/// The stabilized version of this intrinsic is
|
||||
|
@ -303,6 +303,54 @@ pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
|
||||
intrinsics::size_of_val(val)
|
||||
}
|
||||
|
||||
/// Returns the size of the pointed-to value in bytes.
|
||||
///
|
||||
/// This is usually the same as `size_of::<T>()`. However, when `T` *has* no
|
||||
/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object],
|
||||
/// then `size_of_val_raw` can be used to get the dynamically-known size.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is only safe to call if the following conditions hold:
|
||||
///
|
||||
/// - If `T` is `Sized`, this function is always safe to call.
|
||||
/// - If the unsized tail of `T` is:
|
||||
/// - a [slice], then the length of the slice tail must be an intialized
|
||||
/// integer, and the size of the *entire value*
|
||||
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
|
||||
/// - a [trait object], then the vtable part of the pointer must point
|
||||
/// to a valid vtable acquired by an unsizing coersion, and the size
|
||||
/// of the *entire value* (dynamic tail length + statically sized prefix)
|
||||
/// must fit in `isize`.
|
||||
/// - an (unstable) [extern type], then this function is always safe to
|
||||
/// call, but may panic or otherwise return the wrong value, as the
|
||||
/// extern type's layout is not known. This is the same behavior as
|
||||
/// [`size_of_val`] on a reference to an extern type tail.
|
||||
/// - otherwise, it is conservatively not allowed to call this function.
|
||||
///
|
||||
/// [slice]: ../../std/primitive.slice.html
|
||||
/// [trait object]: ../../book/ch17-02-trait-objects.html
|
||||
/// [extern type]: ../../unstable-book/language-features/extern-types.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(layout_for_ptr)]
|
||||
/// use std::mem;
|
||||
///
|
||||
/// assert_eq!(4, mem::size_of_val(&5i32));
|
||||
///
|
||||
/// let x: [u8; 13] = [0; 13];
|
||||
/// let y: &[u8] = &x;
|
||||
/// assert_eq!(13, unsafe { mem::size_of_val_raw(y) });
|
||||
/// ```
|
||||
#[inline]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "layout_for_ptr", issue = "69835")]
|
||||
pub unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
|
||||
intrinsics::size_of_val(val)
|
||||
}
|
||||
|
||||
/// Returns the [ABI]-required minimum alignment of a type.
|
||||
///
|
||||
/// Every reference to a value of the type `T` must be a multiple of this number.
|
||||
@ -390,6 +438,50 @@ pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
|
||||
min_align_of_val(val)
|
||||
}
|
||||
|
||||
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
|
||||
///
|
||||
/// Every reference to a value of the type `T` must be a multiple of this number.
|
||||
///
|
||||
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is only safe to call if the following conditions hold:
|
||||
///
|
||||
/// - If `T` is `Sized`, this function is always safe to call.
|
||||
/// - If the unsized tail of `T` is:
|
||||
/// - a [slice], then the length of the slice tail must be an intialized
|
||||
/// integer, and the size of the *entire value*
|
||||
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
|
||||
/// - a [trait object], then the vtable part of the pointer must point
|
||||
/// to a valid vtable acquired by an unsizing coersion, and the size
|
||||
/// of the *entire value* (dynamic tail length + statically sized prefix)
|
||||
/// must fit in `isize`.
|
||||
/// - an (unstable) [extern type], then this function is always safe to
|
||||
/// call, but may panic or otherwise return the wrong value, as the
|
||||
/// extern type's layout is not known. This is the same behavior as
|
||||
/// [`align_of_val`] on a reference to an extern type tail.
|
||||
/// - otherwise, it is conservatively not allowed to call this function.
|
||||
///
|
||||
/// [slice]: ../../std/primitive.slice.html
|
||||
/// [trait object]: ../../book/ch17-02-trait-objects.html
|
||||
/// [extern type]: ../../unstable-book/language-features/extern-types.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(layout_for_ptr)]
|
||||
/// use std::mem;
|
||||
///
|
||||
/// assert_eq!(4, unsafe { mem::align_of_val_raw(&5i32) });
|
||||
/// ```
|
||||
#[inline]
|
||||
#[cfg(not(bootstrap))]
|
||||
#[unstable(feature = "layout_for_ptr", issue = "69835")]
|
||||
pub unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
|
||||
intrinsics::min_align_of_val(val)
|
||||
}
|
||||
|
||||
/// Returns `true` if dropping values of type `T` matters.
|
||||
///
|
||||
/// This is purely an optimization hint, and may be implemented conservatively:
|
||||
|
@ -137,14 +137,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||
let (n_tps, inputs, output) = match &name[..] {
|
||||
"breakpoint" => (0, Vec::new(), tcx.mk_unit()),
|
||||
"size_of" | "pref_align_of" | "min_align_of" => (1, Vec::new(), tcx.types.usize),
|
||||
"size_of_val" | "min_align_of_val" => (
|
||||
1,
|
||||
vec![tcx.mk_imm_ref(
|
||||
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BrAnon(0))),
|
||||
param(0),
|
||||
)],
|
||||
tcx.types.usize,
|
||||
),
|
||||
"size_of_val" | "min_align_of_val" => {
|
||||
(1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize)
|
||||
}
|
||||
"rustc_peek" => (1, vec![param(0)], param(0)),
|
||||
"caller_location" => (0, vec![], tcx.caller_location_ty()),
|
||||
"panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()),
|
||||
|
Loading…
Reference in New Issue
Block a user