Skip to content

Commit 5c63cec

Browse files
committed
Clarify safety of layout_for_ptr
1 parent 44701e0 commit 5c63cec

File tree

2 files changed

+74
-59
lines changed

2 files changed

+74
-59
lines changed

library/core/src/alloc/layout.rs

+25-17
Original file line numberDiff line numberDiff line change
@@ -174,27 +174,35 @@ impl Layout {
174174
/// allocate backing structure for `T` (which could be a trait
175175
/// or other unsized type like a slice).
176176
///
177+
/// This is an unchecked version of [`for_value`][Self::for_value]
178+
/// which takes a raw pointer instead of a reference.
179+
///
177180
/// # Safety
178181
///
179-
/// This function is only safe to call if the following conditions hold:
180-
///
181-
/// - If `T` is `Sized`, this function is always safe to call.
182-
/// - If the unsized tail of `T` is:
183-
/// - a [slice], then the length of the slice tail must be an initialized
184-
/// integer, and the size of the *entire value*
185-
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
186-
/// - a [trait object], then the vtable part of the pointer must point
187-
/// to a valid vtable for the type `T` acquired by an unsizing coercion,
188-
/// and the size of the *entire value*
189-
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
190-
/// - an (unstable) [extern type], then this function is always safe to
191-
/// call, but may panic or otherwise return the wrong value, as the
192-
/// extern type's layout is not known. This is the same behavior as
193-
/// [`Layout::for_value`] on a reference to an extern type tail.
194-
/// - otherwise, it is conservatively not allowed to call this function.
182+
/// The provided (possibly wide) pointer must describe a valid value layout.
183+
/// Specifically:
184+
///
185+
/// - If `T` is a `Sized` type, this function is always safe to call and is
186+
/// equivalent to [`new::<T>()`][Self::new]. The pointer is unused.
187+
/// - If the unsized tail of `T` is a [slice], then the size of the *entire
188+
/// value* (statically sized prefix plus dynamic tail) must fit in `isize`.
189+
/// The pointer does not need to be [valid](crate::ptr#safety) for access,
190+
/// as only the pointer metadata is used.
191+
/// - If the unsized tail of `T` is a [trait object], then the wide pointer
192+
/// metadata (the vtable reference) must originate from an unsizing or trait
193+
/// upcasting coercion to this trait object tail, and the size of the *entire
194+
/// value* (statically sized prefix plus dynamic tail) must fit in `isize`.
195+
/// The pointer does not need to be [valid](crate::ptr#safety) for access,
196+
/// as only the pointer metadata is used.
197+
/// - For any other unsized tail kind (for example, unstable [extern types]),
198+
/// it is *undefined behavior* to call this function. Unknown unsized tail
199+
/// kinds may impose arbitrary requirements unknowable to current code.
195200
///
196201
/// [trait object]: ../../book/ch17-02-trait-objects.html
197-
/// [extern type]: ../../unstable-book/language-features/extern-types.html
202+
/// [extern types]: ../../unstable-book/language-features/extern-types.html
203+
///
204+
/// It is important to note that the last point means that it would be *unsound*
205+
/// to implement `for_value` as an unconditional call to `for_value_raw`.
198206
#[unstable(feature = "layout_for_ptr", issue = "69835")]
199207
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
200208
#[must_use]

library/core/src/mem/mod.rs

+49-42
Original file line numberDiff line numberDiff line change
@@ -346,43 +346,44 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
346346

347347
/// Returns the size of the pointed-to value in bytes.
348348
///
349-
/// This is usually the same as [`size_of::<T>()`]. However, when `T` *has* no
350-
/// statically-known size, e.g., a slice [`[T]`][slice] or a [trait object],
351-
/// then `size_of_val_raw` can be used to get the dynamically-known size.
349+
/// This is an unchecked version of [`size_of_val`] which takes a raw pointer
350+
/// instead of a reference.
352351
///
353352
/// # Safety
354353
///
355-
/// This function is only safe to call if the following conditions hold:
356-
///
357-
/// - If `T` is `Sized`, this function is always safe to call.
358-
/// - If the unsized tail of `T` is:
359-
/// - a [slice], then the length of the slice tail must be an initialized
360-
/// integer, and the size of the *entire value*
361-
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
362-
/// - a [trait object], then the vtable part of the pointer must point
363-
/// to a valid vtable acquired by an unsizing coercion, and the size
364-
/// of the *entire value* (dynamic tail length + statically sized prefix)
365-
/// must fit in `isize`.
366-
/// - an (unstable) [extern type], then this function is always safe to
367-
/// call, but may panic or otherwise return the wrong value, as the
368-
/// extern type's layout is not known. This is the same behavior as
369-
/// [`size_of_val`] on a reference to a type with an extern type tail.
370-
/// - otherwise, it is conservatively not allowed to call this function.
354+
/// The provided (possibly wide) pointer must describe a valid value layout.
355+
/// Specifically:
356+
///
357+
/// - If `T` is a `Sized` type, this function is always safe to call and is
358+
/// equivalent to [`size_of::<T>()`][size_of]. The pointer is unused.
359+
/// - If the unsized tail of `T` is a [slice], then the size of the *entire
360+
/// value* (statically sized prefix plus dynamic tail) must fit in `isize`.
361+
/// The pointer does not need to be [valid](crate::ptr#safety) for access,
362+
/// as only the pointer metadata is used.
363+
/// - If the unsized tail of `T` is a [trait object], then the wide pointer
364+
/// metadata (the vtable reference) must originate from an unsizing or trait
365+
/// upcasting coercion to this trait object tail, and the size of the *entire
366+
/// value* (statically sized prefix plus dynamic tail) must fit in `isize`.
367+
/// The pointer does not need to be [valid](crate::ptr#safety) for access,
368+
/// as only the pointer metadata is used.
369+
/// - For any other unsized tail kind (for example, unstable [extern types]),
370+
/// it is *undefined behavior* to call this function. Unknown unsized tail
371+
/// kinds may impose arbitrary requirements unknowable to current code.
371372
///
372-
/// [`size_of::<T>()`]: size_of
373373
/// [trait object]: ../../book/ch17-02-trait-objects.html
374-
/// [extern type]: ../../unstable-book/language-features/extern-types.html
374+
/// [extern types]: ../../unstable-book/language-features/extern-types.html
375+
///
376+
/// It is important to note that the last point means that it would be *unsound*
377+
/// to implement `size_of_val` as an unconditional call to `size_of_val_raw`.
375378
///
376379
/// # Examples
377380
///
378381
/// ```
379382
/// #![feature(layout_for_ptr)]
380383
/// use std::mem;
381384
///
382-
/// assert_eq!(4, mem::size_of_val(&5i32));
383-
///
384385
/// let x: [u8; 13] = [0; 13];
385-
/// let y: &[u8] = &x;
386+
/// let y: *const [u8] = &x;
386387
/// assert_eq!(13, unsafe { mem::size_of_val_raw(y) });
387388
/// ```
388389
#[inline]
@@ -493,31 +494,37 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
493494
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in
494495
/// bytes.
495496
///
496-
/// Every reference to a value of the type `T` must be a multiple of this number.
497+
/// This is an unchecked version of [`align_of_val`] which takes a raw pointer
498+
/// instead of a reference.
497499
///
498500
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
499501
///
500502
/// # Safety
501503
///
502-
/// This function is only safe to call if the following conditions hold:
503-
///
504-
/// - If `T` is `Sized`, this function is always safe to call.
505-
/// - If the unsized tail of `T` is:
506-
/// - a [slice], then the length of the slice tail must be an initialized
507-
/// integer, and the size of the *entire value*
508-
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
509-
/// - a [trait object], then the vtable part of the pointer must point
510-
/// to a valid vtable acquired by an unsizing coercion, and the size
511-
/// of the *entire value* (dynamic tail length + statically sized prefix)
512-
/// must fit in `isize`.
513-
/// - an (unstable) [extern type], then this function is always safe to
514-
/// call, but may panic or otherwise return the wrong value, as the
515-
/// extern type's layout is not known. This is the same behavior as
516-
/// [`align_of_val`] on a reference to a type with an extern type tail.
517-
/// - otherwise, it is conservatively not allowed to call this function.
504+
/// The provided (possibly wide) pointer must describe a valid value layout.
505+
/// Specifically:
506+
///
507+
/// - If `T` is a `Sized` type, this function is always safe to call and is
508+
/// equivalent to [`size_of::<T>()`][size_of]. The pointer is unused.
509+
/// - If the unsized tail of `T` is a [slice], then the size of the *entire
510+
/// value* (statically sized prefix plus dynamic tail) must fit in `isize`.
511+
/// The pointer does not need to be [valid](crate::ptr#safety) for access,
512+
/// as only the pointer metadata is used.
513+
/// - If the unsized tail of `T` is a [trait object], then the wide pointer
514+
/// metadata (the vtable reference) must originate from an unsizing or trait
515+
/// upcasting coercion to this trait object tail, and the size of the *entire
516+
/// value* (statically sized prefix plus dynamic tail) must fit in `isize`.
517+
/// The pointer does not need to be [valid](crate::ptr#safety) for access,
518+
/// as only the pointer metadata is used.
519+
/// - For any other unsized tail kind (for example, unstable [extern types]),
520+
/// it is *undefined behavior* to call this function. Unknown unsized tail
521+
/// kinds may impose arbitrary requirements unknowable to current code.
518522
///
519523
/// [trait object]: ../../book/ch17-02-trait-objects.html
520-
/// [extern type]: ../../unstable-book/language-features/extern-types.html
524+
/// [extern types]: ../../unstable-book/language-features/extern-types.html
525+
///
526+
/// It is important to note that the last point means that it would be *unsound*
527+
/// to implement `align_of_val` as an unconditional call to `align_of_val_raw`.
521528
///
522529
/// # Examples
523530
///

0 commit comments

Comments
 (0)