diff options
| author | bors <bors@rust-lang.org> | 2020-03-22 18:37:19 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-03-22 18:37:19 +0000 |
| commit | d1e81ef234ff5c2e0e3a69cb4e8e5f5b0fe1fd83 (patch) | |
| tree | ca5c3aa589727e4c1845fa6865015841f1d62db9 /src/libcore/mem | |
| parent | 1902d1e0de179498d0cb7fd4856d1e0ffcd52095 (diff) | |
| parent | dd973d1b1235813c5e38a092272f2231800b1e53 (diff) | |
Auto merge of #69079 - CAD97:layout-of-ptr, r=RalfJung
Allow calculating the layout behind a pointer There was some discussion around allowing this previously. This does make the requirement for raw pointers to have valid metadata exposed as part of the std API (as a safety invariant, not validity invariant), though I think this is not strictly necessarily required as of current. cc @rust-lang/wg-unsafe-code-guidelines Naming is hard; I picked the best "obvious" name I could come up with. If it's agreed that this is actually a desired API surface, I'll file a tracking issue and update the attributes.
Diffstat (limited to 'src/libcore/mem')
| -rw-r--r-- | src/libcore/mem/mod.rs | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index dac9ee6a5d9..07f7d28bb75 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -336,6 +336,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. @@ -423,6 +471,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: |
