Skip to content

Commit 2d708b0

Browse files
committed
Try to improve PhantomData docs with more examples
1 parent 82dcec7 commit 2d708b0

File tree

1 file changed

+57
-9
lines changed

1 file changed

+57
-9
lines changed

src/libcore/marker.rs

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,48 @@ pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
356356
///
357357
/// # Examples
358358
///
359-
/// When handling external resources over a foreign function interface, `PhantomData<T>` can
360-
/// prevent mismatches by enforcing types in the method implementations:
359+
/// ## Unused lifetime parameter
360+
///
361+
/// Perhaps the most common time that `PhantomData` is required is
362+
/// with a struct that has an unused lifetime parameter, typically as
363+
/// part of some unsafe code. For example, here is a struct `Slice`
364+
/// that has two pointers of type `*mut T`, presumably pointing into
365+
/// an array somewhere:
366+
///
367+
/// ```
368+
/// struct Slice<'a, T> {
369+
/// start: *mut T,
370+
/// end: *mut T,
371+
/// }
372+
/// ```
373+
///
374+
/// The intention is that the underlying data is only valid for the
375+
/// lifetime `'a`, so `Slice` should not outlive `'a`. However, this
376+
/// intent is not expressed in the code, since there are no uses of
377+
/// the lifetime `'a` and hence it is not clear what data it applies
378+
/// to. We can correct this by telling the compiler to act *as if* the
379+
/// `Slice` struct contained a borrowed reference `&'a T`:
380+
///
381+
/// ```
382+
/// # use std::marker::PhantomData;
383+
/// struct Slice<'a, T:'a> {
384+
/// start: *mut T,
385+
/// end: *mut T,
386+
/// phantom: PhantomData<&'a T>
387+
/// }
388+
/// ```
389+
///
390+
/// This also in turn requires that we annotate `T:'a`, indicating
391+
/// that `T` is a type that can be borrowed for the lifetime `'a`.
392+
///
393+
/// ## Unused type parameters
394+
///
395+
/// It sometimes happens that there are unused type parameters that
396+
/// indicate what type of data a struct is "tied" to, even though that
397+
/// data is not actually found in the struct itself. Here is an
398+
/// example where this arises when handling external resources over a
399+
/// foreign function interface. `PhantomData<T>` can prevent
400+
/// mismatches by enforcing types in the method implementations:
361401
///
362402
/// ```
363403
/// # trait ResType { fn foo(&self); };
@@ -391,13 +431,21 @@ pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
391431
/// }
392432
/// ```
393433
///
394-
/// Another example: embedding a `PhantomData<T>` will inform the compiler
395-
/// that one or more instances of the type `T` could be dropped when
396-
/// instances of the type itself is dropped, though that may not be
397-
/// apparent from the other structure of the type itself. This is
398-
/// commonly necessary if the structure is using an unsafe pointer
399-
/// like `*mut T` whose referent may be dropped when the type is
400-
/// dropped, as a `*mut T` is otherwise not treated as owned.
434+
/// ## Indicating ownership
435+
///
436+
/// Adding a field of type `PhantomData<T>` also indicates that your
437+
/// struct owns data of type `T` and hence may drop one or more
438+
/// instances of the type `T` could be dropped when instances of the
439+
/// type itself is dropped, though that may not be apparent from the
440+
/// other structure of the type itself. This is commonly necessary if
441+
/// the structure is using an unsafe pointer like `*mut T` whose
442+
/// referent may be dropped when the type is dropped, as a `*mut T` is
443+
/// otherwise not treated as owned.
444+
///
445+
/// If your struct does not in fact *own* the data of type `T`, it is
446+
/// better to use a reference type, like `PhantomData<&'a T>`
447+
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
448+
/// as not to indicate ownership.
401449
#[lang="phantom_data"]
402450
#[stable(feature = "rust1", since = "1.0.0")]
403451
pub struct PhantomData<T:?Sized>;

0 commit comments

Comments
 (0)