Skip to content

Commit 284c15d

Browse files
committed
Clarify safety of layout_for_ptr
1 parent 90fdc1f commit 284c15d

File tree

2 files changed

+68
-61
lines changed

2 files changed

+68
-61
lines changed

library/core/src/alloc/layout.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -172,27 +172,33 @@ impl Layout {
172172
/// allocate backing structure for `T` (which could be a trait
173173
/// or other unsized type like a slice).
174174
///
175+
/// This is an unchecked version of [`for_value`][Self::for_value]
176+
/// which takes a raw pointer instead of a reference.
177+
///
175178
/// # Safety
176179
///
177-
/// This function is only safe to call if the following conditions hold:
178-
///
179-
/// - If `T` is `Sized`, this function is always safe to call.
180-
/// - If the unsized tail of `T` is:
181-
/// - a [slice], then the length of the slice tail must be an initialized
182-
/// integer, and the size of the *entire value*
183-
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
184-
/// - a [trait object], then the vtable part of the pointer must point
185-
/// to a valid vtable for the type `T` acquired by an unsizing coercion,
186-
/// and the size of the *entire value*
187-
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
188-
/// - an (unstable) [extern type], then this function is always safe to
189-
/// call, but may panic or otherwise return the wrong value, as the
190-
/// extern type's layout is not known. This is the same behavior as
191-
/// [`Layout::for_value`] on a reference to an extern type tail.
192-
/// - otherwise, it is conservatively not allowed to call this function.
180+
/// The provided (possibly wide) pointer must describe a valid value layout.
181+
/// Specifically:
182+
///
183+
/// - If `T` is a `Sized` type, this function is always safe to call and is
184+
/// equivalent to [`size_of::<T>()`][size_of]. The pointer is unused.
185+
/// - If the unsized tail of `T` is a [slice], then the size of the *entire
186+
/// value* (statically sized prefix plus dynamic tail) must fit in `isize`.
187+
/// The pointer may be dangling or null; only the slice length is used.
188+
/// - If the unsized tail of `T` is a [trait object], then the wide pointer
189+
/// metadata (the vtable reference) must originate from an unsizing coercion,
190+
/// and the size of the *entire value* (statically sized prefix plus dynamic
191+
/// tail) must fit in `isize`. The pointer may be dangling or null; only the
192+
/// wide pointer metadata is used.
193+
/// - For any other unsized tail kind (for example, unstable [extern types]),
194+
/// it is currently *not permitted* to call this function. Unknown unsized
195+
/// tail kinds may impose arbitrary requirements unknowable to current code.
193196
///
194197
/// [trait object]: ../../book/ch17-02-trait-objects.html
195-
/// [extern type]: ../../unstable-book/language-features/extern-types.html
198+
/// [extern types]: ../../unstable-book/language-features/extern-types.html
199+
///
200+
/// It is important to note that the last point means that it would be *unsound*
201+
/// to implement `for_value` as an unconditional call to `for_value_raw`.
196202
#[unstable(feature = "layout_for_ptr", issue = "69835")]
197203
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
198204
#[must_use]

library/core/src/mem/mod.rs

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -346,43 +346,42 @@ 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 may be dangling or null; only the slice length is used.
362+
/// - If the unsized tail of `T` is a [trait object], then the wide pointer
363+
/// metadata (the vtable reference) must originate from an unsizing coercion,
364+
/// and the size of the *entire value* (statically sized prefix plus dynamic
365+
/// tail) must fit in `isize`. The pointer may be dangling or null; only the
366+
/// wide pointer metadata is used.
367+
/// - For any other unsized tail kind (for example, unstable [extern types]),
368+
/// it is currently *not permitted* to call this function. Unknown unsized
369+
/// tail kinds may impose arbitrary requirements unknowable to current code.
371370
///
372-
/// [`size_of::<T>()`]: size_of
373371
/// [trait object]: ../../book/ch17-02-trait-objects.html
374-
/// [extern type]: ../../unstable-book/language-features/extern-types.html
372+
/// [extern types]: ../../unstable-book/language-features/extern-types.html
373+
///
374+
/// It is important to note that the last point means that it would be *unsound*
375+
/// to implement `size_of_val` as an unconditional call to `size_of_val_raw`.
375376
///
376377
/// # Examples
377378
///
378379
/// ```
379380
/// #![feature(layout_for_ptr)]
380381
/// use std::mem;
381382
///
382-
/// assert_eq!(4, mem::size_of_val(&5i32));
383-
///
384383
/// let x: [u8; 13] = [0; 13];
385-
/// let y: &[u8] = &x;
384+
/// let y: *const [u8] = &x;
386385
/// assert_eq!(13, unsafe { mem::size_of_val_raw(y) });
387386
/// ```
388387
#[inline]
@@ -493,31 +492,33 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
493492
/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in
494493
/// bytes.
495494
///
496-
/// Every reference to a value of the type `T` must be a multiple of this number.
497-
///
498-
/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
495+
/// This is an unchecked version of [`align_of_val`] which takes a raw pointer
496+
/// instead of a reference.
499497
///
500498
/// # Safety
501499
///
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.
500+
/// The provided (possibly wide) pointer must describe a valid value layout.
501+
/// Specifically:
502+
///
503+
/// - If `T` is a `Sized` type, this function is always safe to call and is
504+
/// equivalent to [`size_of::<T>()`][size_of]. The pointer is unused.
505+
/// - If the unsized tail of `T` is a [slice], then the size of the *entire
506+
/// value* (statically sized prefix plus dynamic tail) must fit in `isize`.
507+
/// The pointer may be dangling or null; only the slice length is used.
508+
/// - If the unsized tail of `T` is a [trait object], then the wide pointer
509+
/// metadata (the vtable reference) must originate from an unsizing coercion,
510+
/// and the size of the *entire value* (statically sized prefix plus dynamic
511+
/// tail) must fit in `isize`. The pointer may be dangling or null; only the
512+
/// wide pointer metadata is used.
513+
/// - For any other unsized tail kind (for example, unstable [extern types]),
514+
/// it is currently *not permitted* to call this function. Unknown unsized
515+
/// tail kinds may impose arbitrary requirements unknowable to current code.
518516
///
519517
/// [trait object]: ../../book/ch17-02-trait-objects.html
520-
/// [extern type]: ../../unstable-book/language-features/extern-types.html
518+
/// [extern types]: ../../unstable-book/language-features/extern-types.html
519+
///
520+
/// It is important to note that the last point means that it would be *unsound*
521+
/// to implement `size_of_val` as an unconditional call to `size_of_val_raw`.
521522
///
522523
/// # Examples
523524
///

0 commit comments

Comments
 (0)