Skip to content

Try to improve PhantomData docs with more examples #24059

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 7, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 58 additions & 9 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,49 @@ pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
///
/// # Examples
///
/// When handling external resources over a foreign function interface, `PhantomData<T>` can
/// prevent mismatches by enforcing types in the method implementations:
/// ## Unused lifetime parameter
///
/// Perhaps the most common time that `PhantomData` is required is
/// with a struct that has an unused lifetime parameter, typically as
/// part of some unsafe code. For example, here is a struct `Slice`
/// that has two pointers of type `*const T`, presumably pointing into
/// an array somewhere:
///
/// ```
/// struct Slice<'a, T> {
/// start: *const T,
/// end: *const T,
/// }
/// ```
///
/// The intention is that the underlying data is only valid for the
/// lifetime `'a`, so `Slice` should not outlive `'a`. However, this
/// intent is not expressed in the code, since there are no uses of
/// the lifetime `'a` and hence it is not clear what data it applies
/// to. We can correct this by telling the compiler to act *as if* the
/// `Slice` struct contained a borrowed reference `&'a T`:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using *mut T and then acting as if it were a &T (the mut vs. not, specifically) is mildly disconcerting.

///
/// ```
/// use std::marker::PhantomData;
///
/// struct Slice<'a, T:'a> {
/// start: *const T,
/// end: *const T,
/// phantom: PhantomData<&'a T>
/// }
/// ```
///
/// This also in turn requires that we annotate `T:'a`, indicating
/// that `T` is a type that can be borrowed for the lifetime `'a`.
///
/// ## Unused type parameters
///
/// It sometimes happens that there are unused type parameters that
/// indicate what type of data a struct is "tied" to, even though that
/// data is not actually found in the struct itself. Here is an
/// example where this arises when handling external resources over a
/// foreign function interface. `PhantomData<T>` can prevent
/// mismatches by enforcing types in the method implementations:
///
/// ```
/// # trait ResType { fn foo(&self); };
Expand Down Expand Up @@ -391,13 +432,21 @@ pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
/// }
/// ```
///
/// Another example: embedding a `PhantomData<T>` will inform the compiler
/// that one or more instances of the type `T` could be dropped when
/// instances of the type itself is dropped, though that may not be
/// apparent from the other structure of the type itself. This is
/// commonly necessary if the structure is using an unsafe pointer
/// like `*mut T` whose referent may be dropped when the type is
/// dropped, as a `*mut T` is otherwise not treated as owned.
/// ## Indicating ownership
///
/// Adding a field of type `PhantomData<T>` also indicates that your
/// struct owns data of type `T`. This in turn implies that when your
/// struct is dropped, it may in turn drop one or more instances of
/// the type `T`, though that may not be apparent from the other
/// structure of the type itself. This is commonly necessary if the
/// structure is using an unsafe pointer like `*mut T` whose referent
/// may be dropped when the type is dropped, as a `*mut T` is
/// otherwise not treated as owned.
///
/// If your struct does not in fact *own* the data of type `T`, it is
/// better to use a reference type, like `PhantomData<&'a T>`
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
/// as not to indicate ownership.
#[lang="phantom_data"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PhantomData<T:?Sized>;
Expand Down