Struct std::marker::PhantomData
[−]
[src]
pub struct PhantomData<T> where T: ?Sized;
PhantomData<T>
`PhantomDataallows you to describe that a type acts as if it stores a value of type
` allows you to describe that a type acts as if it stores a value of type T
`T`,
even though it does not. This allows you to inform the compiler about certain safety properties
of your code.
Though they both have scary names, PhantomData<T>
`PhantomData
Examples
Unused lifetime parameter
Perhaps the most common time that PhantomData
`PhantomDatais required is with a struct that has an unused lifetime parameter, typically as part of some unsafe code. For example, here is a struct
` 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
`Slicethat has two pointers of type
`
that has two pointers of type *const T
`*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
`'a, so
`, so Slice
`Sliceshould not outlive
` should not outlive 'a
`'a. However, this intent is not expressed in the code, since there are no uses of the lifetime
`. However, this
intent is not expressed in the code, since there are no uses of
the lifetime 'a
`'aand hence it is not clear what data it applies to. We can correct this by telling the compiler to act *as if* the
` 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
`Slicestruct contained a borrowed reference
` struct contained a borrowed reference &'a T
`&'a T`:
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
`T:'a, indicating that
`, indicating
that T
`Tis a type that can be borrowed for the lifetime
` is a type that can be borrowed for the lifetime 'a
`'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>
`PhantomData
use std::marker::PhantomData; use std::mem; struct ExternalResource<R> { resource_handle: *mut (), resource_type: PhantomData<R>, } impl<R: ResType> ExternalResource<R> { fn new() -> ExternalResource<R> { let size_of_res = mem::size_of::<R>(); ExternalResource { resource_handle: foreign_lib::new(size_of_res), resource_type: PhantomData, } } fn do_stuff(&self, param: ParamType) { let foreign_params = convert_params(param); foreign_lib::do_stuff(self.resource_handle, foreign_params); } }
Indicating ownership
Adding a field of type PhantomData<T>
`PhantomDataalso indicates that your struct owns data of type
` also indicates that your
struct owns data of type T
`T. This in turn implies that when your struct is dropped, it may in turn drop one or more instances of the type
`. This in turn implies that when your
struct is dropped, it may in turn drop one or more instances of
the type T
`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
`, 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
`*mut Twhose referent may be dropped when the type is dropped, as a
` whose referent
may be dropped when the type is dropped, as a *mut T
`*mut T` is
otherwise not treated as owned.
If your struct does not in fact own the data of type T
`T, it is better to use a reference type, like
`, it is
better to use a reference type, like PhantomData<&'a T>
`PhantomData<&'a T>(ideally) or
`
(ideally) or PhantomData<*const T>
`PhantomData<*const T>` (if no lifetime applies), so
as not to indicate ownership.