特殊类型和 trait
标准库(Standard Library)中存在的某些类型和 trait 是 Rust 编译器已知的。本章记录了这些类型和 trait 的特殊功能。
Box<T>
Box<T> 具有一些 Rust 目前不允许用户定义类型具有的特殊功能。
- 方法可以将
Box<Self>作为接收者。
- 可以在与
T相同的 crate 中为Box<T>实现 trait,而孤立规则阻止为其他泛型类型这样做。
Rc<T>
Arc<T>
Pin<P>
UnsafeCell<T>
std::cell::UnsafeCell<T> 用于内部可变性。它确保编译器不会执行对此类类型不正确的优化。
它还确保具有内部可变性类型的 [static 项]不会被放置在标记为只读的内存中。
PhantomData<T>
std::marker::PhantomData<T> 是一个零大小、最小对齐的类型,在型变、丢弃检查和自动 trait 方面被视为拥有一个 T。
运算符 trait
std::ops 和 std::cmp 中的 trait 用于重载运算符、索引表达式和调用表达式。
Deref 和 DerefMut
除了重载一元 * 运算符外,Deref 和 DerefMut 还用于方法解析和解引用强制转换。
Drop
Drop trait 提供了析构器,在该类型的值即将被销毁时运行。
Copy
Copy trait 改变了实现它的类型的语义。
实现 Copy 的类型的值在赋值时被复制而不是移动。
Copy 只能为未实现 Drop 且其字段全部为 Copy 的类型实现。对于枚举,这意味着所有变体的所有字段都必须是 Copy。对于联合体,这意味着所有变体都必须是 Copy。
Copy 由编译器为以下类型实现:
Copy类型的元组
- 不捕获值或只捕获
Copy类型值的闭包
Clone
Clone trait 是 Copy 的超级 trait,因此也需要编译器生成的实现。
编译器为以下类型实现了它:
- 具有内置
Copy实现的类型(见上文)
Clone类型的元组
- 只捕获
Clone类型值或不从环境捕获值的闭包
Send
Send trait 表示该类型的值可以安全地从一个线程发送到另一个线程。
Sync
Sync trait 表示该类型的值可以安全地在多个线程之间共享。
所有用于不可变 [static 项]的类型都必须实现此 trait。
Termination
Termination trait 表示 main 函数和测试函数的可接受返回类型。
自动 trait
Send、Sync、Unpin、UnwindSafe 和 RefUnwindSafe trait 是_自动 trait_。自动 trait 具有特殊属性。
如果没有为给定类型的自动 trait 编写出显式实现或否定实现,则编译器根据以下规则自动实现它:
- 如果
T实现了该 trait,则&T、&mut T、*const T、*mut T、[T; n]和[T]也实现该 trait。
- 函数项类型和函数指针自动实现该 trait。
- 如果所有字段都实现了该 trait,则结构体、枚举、联合体和元组也实现该 trait。
- 如果所有捕获的类型都实现了该 trait,则闭包也实现该 trait。通过共享引用捕获
T并按值捕获U的闭包实现了&T和U都实现的所有自动 trait。
对于泛型类型(将上面的内置类型视为对 T 泛型),如果泛型实现可用,则编译器不会为可以使用该实现但不满足必需 trait 约束的类型自动实现它。例如,标准库为所有 T 是 Sync 的 &T 实现了 Send;这意味着如果 T 是 Send 但不是 Sync,编译器将不会为 &T 实现 Send。
自动 trait 也可以有否定实现,在标准库文档中显示为 impl !AutoTrait for T,它们覆盖自动实现。例如 *mut T 有 Send 的否定实现,因此 *mut T 不是 Send,即使 T 是。目前没有稳定的方式来指定额外的否定实现;它们只存在于标准库中。
自动 trait 可以作为额外的约束添加到任何 trait 对象,即使通常只允许一个 trait。例如,Box<dyn Debug + Send + UnwindSafe> 是有效的类型。
Sized
Sized trait 表示该类型的大小在编译时已知;即它不是动态大小类型。
类型参数(trait 中的 Self 除外)默认是 Sized 的,关联类型也是如此。
Sized 始终由编译器自动实现,而不是由实现项实现。
这些隐式 Sized 约束可以通过使用特殊的 ?Sized 约束来放宽。