Skip to content

Commit d166772

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

File tree

1 file changed

+58
-9
lines changed

1 file changed

+58
-9
lines changed

src/libcore/marker.rs

+58-9
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,49 @@ 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 `*const T`, presumably pointing into
365+
/// an array somewhere:
366+
///
367+
/// ```
368+
/// struct Slice<'a, T> {
369+
/// start: *const T,
370+
/// end: *const 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+
///
384+
/// struct Slice<'a, T:'a> {
385+
/// start: *const T,
386+
/// end: *const T,
387+
/// phantom: PhantomData<&'a T>
388+
/// }
389+
/// ```
390+
///
391+
/// This also in turn requires that we annotate `T:'a`, indicating
392+
/// that `T` is a type that can be borrowed for the lifetime `'a`.
393+
///
394+
/// ## Unused type parameters
395+
///
396+
/// It sometimes happens that there are unused type parameters that
397+
/// indicate what type of data a struct is "tied" to, even though that
398+
/// data is not actually found in the struct itself. Here is an
399+
/// example where this arises when handling external resources over a
400+
/// foreign function interface. `PhantomData<T>` can prevent
401+
/// mismatches by enforcing types in the method implementations:
361402
///
362403
/// ```
363404
/// # trait ResType { fn foo(&self); };
@@ -391,13 +432,21 @@ pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
391432
/// }
392433
/// ```
393434
///
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.
435+
/// ## Indicating ownership
436+
///
437+
/// Adding a field of type `PhantomData<T>` also indicates that your
438+
/// struct owns data of type `T`. This in turn implies that when your
439+
/// struct is dropped, it may in turn drop one or more instances of
440+
/// the type `T`, though that may not be apparent from the other
441+
/// structure of the type itself. This is commonly necessary if the
442+
/// structure is using an unsafe pointer like `*mut T` whose referent
443+
/// may be dropped when the type is dropped, as a `*mut T` is
444+
/// otherwise not treated as owned.
445+
///
446+
/// If your struct does not in fact *own* the data of type `T`, it is
447+
/// better to use a reference type, like `PhantomData<&'a T>`
448+
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
449+
/// as not to indicate ownership.
401450
#[lang="phantom_data"]
402451
#[stable(feature = "rust1", since = "1.0.0")]
403452
pub struct PhantomData<T:?Sized>;

0 commit comments

Comments
 (0)