From 3ea7f1504c43dbc5e139c393b41427323e1c5f45 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 18 Jan 2021 19:45:32 +0100 Subject: [PATCH] More doc-comments for pointer metadata APIs --- library/core/src/ptr/metadata.rs | 90 ++++++++++++++++++++++++++++++-- library/core/src/ptr/non_null.rs | 2 + 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 0661ccc0200..f89e891cb86 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -3,7 +3,52 @@ use crate::fmt; use crate::hash::{Hash, Hasher}; -/// FIXME docs +/// Provides the pointer metadata type of any pointed-to type. +/// +/// # Pointer metadata +/// +/// Raw pointer types and reference types in Rust can be thought of as made of two parts: +/// a data pointer that contains the memory address of the value, and some metadata. +/// +/// For statically-sized types (that implement the `Sized` traits) +/// as well as for `extern` types, +/// pointers are said to be “thin”: metadata is zero-sized and its type is `()`. +/// +/// Pointers to [dynamically-sized types][dst] are said to be “wide” or “fat”, +/// they have non-zero-sized metadata: +/// +/// * For structs whose last field is a DST, metadata is the metadata for the last field +/// * For the `str` type, metadata is the length in bytes as `usize` +/// * For slice types like `[T]`, metadata is the length in items as `usize` +/// * For trait objects like `dyn SomeTrait`, metadata is [`DynMetadata`][DynMetadata] +/// (e.g. `DynMetadata`) +/// +/// In the future, the Rust language may gain new kinds of types +/// that have different pointer metadata. +/// +/// [dst]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts +/// +/// +/// # The `Pointee` trait +/// +/// The point of this trait is its `Metadata` associated type, +/// which is `()` or `usize` or `DynMetadata<_>` as described above. +/// It is automatically implemented for every type. +/// It can be assumed to be implemented in a generic context, even without a corresponding bound. +/// +/// +/// # Usage +/// +/// Raw pointers can be decomposed into the data address and metadata components +/// with their [`to_raw_parts`] method. +/// +/// Alternatively, metadata alone can be extracted with the [`metadata`] function. +/// A reference can be passed to [`metadata`] and implicitly coerced. +/// +/// A (possibly-wide) pointer can be put back together from its address and metadata +/// with [`from_raw_parts`] or [`from_raw_parts_mut`]. +/// +/// [`to_raw_parts`]: <*const _>::to_raw_parts #[lang = "pointee_trait"] pub trait Pointee { /// The type for metadata in pointers and references to `Self`. @@ -14,7 +59,11 @@ pub trait Pointee { type Metadata: Copy + Send + Sync + Ord + Hash + Unpin; } -/// Pointers to types implementing this trait alias are “thin” +/// Pointers to types implementing this trait alias are “thin”. +/// +/// This includes statically-`Sized` types and `extern` types. +/// +/// # Example /// /// ```rust /// #![feature(ptr_metadata)] @@ -28,6 +77,17 @@ pub trait Pointee { pub trait Thin = Pointee; /// Extract the metadata component of a pointer. +/// +/// Values of type `*mut T`, `&T`, or `&mut T` can be passed directly to this function +/// as they implicitly coerce to `*const T`. +/// +/// # Example +/// +/// ``` +/// #![feature(ptr_metadata)] +/// +/// assert_eq!(std::ptr::metadata("foo"), 3_usize); +/// ``` #[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")] #[inline] pub const fn metadata(ptr: *const T) -> ::Metadata { @@ -37,7 +97,13 @@ pub const fn metadata(ptr: *const T) -> ::Metadata { unsafe { PtrRepr { const_ptr: ptr }.components.metadata } } -/// Forms a raw pointer from a data address and metadata. +/// Forms a (possibly-wide) raw pointer from a data address and metadata. +/// +/// This function is safe but the returned pointer is not necessarily safe to dereference. +/// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements. +/// For trait objects, the metadata must come from a pointer to the same underlying ereased type. +/// +/// [`slice::from_raw_parts`]: crate::slice::from_raw_parts #[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")] #[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")] #[inline] @@ -91,7 +157,23 @@ fn clone(&self) -> Self { } } -/// The metadata for a `dyn SomeTrait` trait object type. +/// The metadata for a `Dyn = dyn SomeTrait` trait object type. +/// +/// It is a pointer to a vtable (virtual call table) +/// that represents all the necessary information +/// to manipulate the concrete type stored inside a trait object. +/// The vtable notably it contains: +/// +/// * type size +/// * type alignment +/// * a pointer to the type’s `drop_in_place` impl (may be a no-op for plain-old-data) +/// * pointers to all the methods for the type’s implementation of the trait +/// +/// Note that the first three are special because they’re necessary to allocate, drop, +/// and deallocate any trait object. +/// +/// It is possible to name this struct with a type parameter that is not a `dyn` trait object +/// (for example `DynMetadata`) but not to obtain a meaningful value of that struct. #[lang = "dyn_metadata"] pub struct DynMetadata { vtable_ptr: &'static VTable, diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 00cb1e1b271..3de5b097f5e 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -179,6 +179,8 @@ pub fn new(ptr: *mut T) -> Option { /// `NonNull` pointer is returned, as opposed to a raw `*const` pointer. /// /// See the documentation of [`std::ptr::from_raw_parts`] for more details. + /// + /// [`std::ptr::from_raw_parts`]: crate::ptr::from_raw_parts #[cfg(not(bootstrap))] #[unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")] #[rustc_const_unstable(feature = "ptr_metadata", issue = /* FIXME */ "none")] -- 2.44.0