PhantomData

  • 日期: 2022-03-08 11:58
  • 版本: Rust 1.58.1

简介

struct 类型,没有大小。


#![allow(unused)]

fn main() {
pub struct PhantomData<T>
 where
    T: ?Sized;
}

主要用来解决两个问题

  • 生命周期
  • 数据回收

生命周期

对于一些标记了生命周期,但是其内部没有使用的类型来说,此生命周期由于没有使用,从而导致没有边界,无法进行编译。例如:


#![allow(unused)]
fn main() {
struct Iter<'a, T: 'a> {
    ptr: *const T,
    end: *const T,
}
}

所以需要修改为:


#![allow(unused)]
fn main() {
use std::marker;

struct Iter<'a, T: 'a> {
    ptr: *const T,
    end: *const T,
    _marker: marker::PhantomData<&'a T>,
}
}

数据回收

比如对于Vec类型来说


#![allow(unused)]
fn main() {
struct Vec<T> {
    data: *const T, // *const for variance!
    len: usize,
    cap: usize,
}
}

删除检查器确定Vec<T>没有拥有任何T类型的任何值。

为了让删除检查器确定我们拥有T类型的值,可以做如下修改


#![allow(unused)]
fn main() {
use std::marker;

struct Vec<T> {
    data: *const T, // *const for variance!
    len: usize,
    cap: usize,
    _marker: marker::PhantomData<T>,
}
}

使用场景

Phantom type'aT
PhantomData-covariant (with drop check)
PhantomData<&'a T>covariantcovariant
PhantomData<&'a mut T>covariantinvariant
PhantomData<*const T>-covariant
PhantomData<*mut T>-invariant
PhantomData<fn(T)>-contravariant
PhantomData<fn() -> T>-covariant
PhantomData<fn(T) -> T>-invariant
PhantomData<Cell<&'a ()>>invariant-