Expand description
Various verbose shorthand types related to PhantomData.
§Variance
Variance can be very confusing to beginners. Generally, when one talks about “subtype” and “supertype” in Rust, it is specifically about lifetimes in the current version.
Specifically, any reference type &'any T is a subtype of
the static reference type &'static T. A reference with a
shorter lifetime is a subtype of another reference with a
longer lifetime.
§Covariant
When a Foo<T> is “covariant” over T, it shares the
same subtyping rules with T, i.e. Foo<&'a T> is a subtype
of Foo<&'static T>.
When a lifetime parameter is covariant, it suggests that a
shorter lifetime parameter is a subtype of a longer lifetime
parameter, i.e. Foo<'a> is a subtype of Foo<'static>.
§Contravariant
Contravariant is rare, it reverses the normal subtyping
rules. Foo<'static> is a subtype of Foo<'a> if the lifetimes
are contravariant. It is the property of argument types of
functions. fn(&'static ()) is the most strict and would be
the super type for all fn(&'a ()).
§Invariant
If a parameter is invariant, it cannot be changed. Only equal
arguments are sub/super types of themselves. T is invariant
in &mut T because you can perform both read and write
operations on it, and you cannot write a T2 with a shorter
lifetime than T, nor read a T3 with a longer lifetime.
T is invariant in fn(T) -> T for similar reasons.
§Drop Check
A difference between the CovariantOver type offered in this
crate and the Owns type is that Owns will cause the compiler
to use “drop check”. Drop checking prevents use of dropped values
in another type’s destructor. The examples below are taken and
adapted from the respective Rustonomicon chapter:
Imagine a custom Box type defined like this:
use std::ptr::NonNull;
struct MyBox<T> {
inner: NonNull<T>,
}
impl<T> Drop for MyBox<T> {
fn drop(&mut self) { /* free memory.. */ }
}Although NonNull is covariant over T,
MyBox must use PhantomData to signify that it owns T,
otherwise it could allow access to dropped data in a destructor:
struct Inspector<'a>(&'a u8);
impl<'a> Drop for Inspector<'a> {
fn drop(&mut self) {
println!("I was only {} days from retirement!", self.0);
}
}
struct World<'a> {
inspector: Option<MyBox<Inspector<'a>>>,
days: Box<u8>,
}
fn main() {
let mut world = World {
inspector: None,
days: Box::new(1),
};
world.inspector = Some(MyBox::new(Inspector(&world.days)));
// Let's say `days` happens to get dropped first.
// Then when Inspector is dropped, it will try to read free'd memory!
}In this example, marking MyBox with a PhantomData<T> or Owns<T>
resolves the unsoundness issue:
struct MyBox<T> {
inner: NonNull<T>,
_owns_t: Owns<T>,
}
fn main() {
let mut world = World {
inspector: None,
days: Box::new(1),
};
world.inspector = Some(MyBox::new(Inspector(&world.days)));
// ^ now fails to compile!
}§Markers
The Send and Sync markers can be controlled by adding
NotSendOrSync or NotSync to your type and/or writing
unsafe impls of the markers to your type. The markers control
what types can be sent between threads safely. The non-atomic
reference counted type Rc cannot be sent
between threads because there might be two threads holding the
same object and could increase the reference counter
non-atomically, causing a data race.
Usually your type is automatically not Send when there are
fields of pointers or single-threaded containers such as Rc,
but there could be benefits of explicitly defining a type as not
Send or not Sync.
Doing so can prevent semver hazards when a public type suddenly stops implementing any of these marker types, causing a breaking change, while explicitly adding the marker types allows future possibilities of having single-threaded containers without bumping the major version.
Re-exports§
pub use core::marker::PhantomData;pub use core::marker::PhantomPinned;
Type Aliases§
- Contra
Variant Over Lt - Marks a lifetime as contravariant.
- Contravariant
Over - Marks a type as contravariant.
- Covariant
Over - Mark a type as covariant.
- Covariant
Over Lt - Marks a lifetime as covariant.
- HasImm
PtrTo - Marks the containing type as having mutable pointers to
T. - HasMut
PtrTo - Marks the containing type as having mutable pointers to
T. - Immutably
References - Alias for phantom
&'a T. Both parameters are covariant. - Invariant
Over - Marks a type as invariant.
- Invariant
Over Lt - Marks a lifetime as invariant.
- Mutably
References - Alias for
PhantomData<&'a mut T>.'ais covariant whileTis invariant. - NotSend
OrSync - Marks the containing type as not
Sendand notSync. - NotSync
- Marks the containing type as not
Sync. - Owns
- Verbose version of
PhantomData.