Skip to content

Commit 6f852f5

Browse files
committed
Rollup merge of rust-lang#24059 - nikomatsakis:issue-22914-phantomdata-docs, r=huon
This probably needs a bit more work, but I wanted to try and capture some common use cases and be a bit more helpful. r? @huonw cc @steveklabnik
2 parents daf2e36 + d166772 commit 6f852f5

File tree

1 file changed

+58
-9
lines changed

1 file changed

+58
-9
lines changed

src/libcore/marker.rs

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,49 @@ impl<A:?Sized,R:?Sized,T:?Sized> PhantomFn<A,R> for T { }
316316
///
317317
/// # Examples
318318
///
319-
/// When handling external resources over a foreign function interface, `PhantomData<T>` can
320-
/// prevent mismatches by enforcing types in the method implementations:
319+
/// ## Unused lifetime parameter
320+
///
321+
/// Perhaps the most common time that `PhantomData` is required is
322+
/// with a struct that has an unused lifetime parameter, typically as
323+
/// part of some unsafe code. For example, here is a struct `Slice`
324+
/// that has two pointers of type `*const T`, presumably pointing into
325+
/// an array somewhere:
326+
///
327+
/// ```
328+
/// struct Slice<'a, T> {
329+
/// start: *const T,
330+
/// end: *const T,
331+
/// }
332+
/// ```
333+
///
334+
/// The intention is that the underlying data is only valid for the
335+
/// lifetime `'a`, so `Slice` should not outlive `'a`. However, this
336+
/// intent is not expressed in the code, since there are no uses of
337+
/// the lifetime `'a` and hence it is not clear what data it applies
338+
/// to. We can correct this by telling the compiler to act *as if* the
339+
/// `Slice` struct contained a borrowed reference `&'a T`:
340+
///
341+
/// ```
342+
/// use std::marker::PhantomData;
343+
///
344+
/// struct Slice<'a, T:'a> {
345+
/// start: *const T,
346+
/// end: *const T,
347+
/// phantom: PhantomData<&'a T>
348+
/// }
349+
/// ```
350+
///
351+
/// This also in turn requires that we annotate `T:'a`, indicating
352+
/// that `T` is a type that can be borrowed for the lifetime `'a`.
353+
///
354+
/// ## Unused type parameters
355+
///
356+
/// It sometimes happens that there are unused type parameters that
357+
/// indicate what type of data a struct is "tied" to, even though that
358+
/// data is not actually found in the struct itself. Here is an
359+
/// example where this arises when handling external resources over a
360+
/// foreign function interface. `PhantomData<T>` can prevent
361+
/// mismatches by enforcing types in the method implementations:
321362
///
322363
/// ```
323364
/// # trait ResType { fn foo(&self); };
@@ -351,13 +392,21 @@ impl<A:?Sized,R:?Sized,T:?Sized> PhantomFn<A,R> for T { }
351392
/// }
352393
/// ```
353394
///
354-
/// Another example: embedding a `PhantomData<T>` will inform the compiler
355-
/// that one or more instances of the type `T` could be dropped when
356-
/// instances of the type itself is dropped, though that may not be
357-
/// apparent from the other structure of the type itself. This is
358-
/// commonly necessary if the structure is using an unsafe pointer
359-
/// like `*mut T` whose referent may be dropped when the type is
360-
/// dropped, as a `*mut T` is otherwise not treated as owned.
395+
/// ## Indicating ownership
396+
///
397+
/// Adding a field of type `PhantomData<T>` also indicates that your
398+
/// struct owns data of type `T`. This in turn implies that when your
399+
/// struct is dropped, it may in turn drop one or more instances of
400+
/// the type `T`, though that may not be apparent from the other
401+
/// structure of the type itself. This is commonly necessary if the
402+
/// structure is using an unsafe pointer like `*mut T` whose referent
403+
/// may be dropped when the type is dropped, as a `*mut T` is
404+
/// otherwise not treated as owned.
405+
///
406+
/// If your struct does not in fact *own* the data of type `T`, it is
407+
/// better to use a reference type, like `PhantomData<&'a T>`
408+
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
409+
/// as not to indicate ownership.
361410
#[lang="phantom_data"]
362411
#[stable(feature = "rust1", since = "1.0.0")]
363412
pub struct PhantomData<T:?Sized>;

0 commit comments

Comments
 (0)