理解rustc_middle中的adjustment.rs

·

1 min read

  1. 最简单的情况是指针在 "fat"(胖)和 "thin"(瘦)之间没有进行调整。在这种情况下,指针将被解引用 N 次(解引用可以发生在原始指针或借用的指针,或者实现了 Deref 的任何智能指针,包括 Box<_>)。解引用的类型由 autoderefs 给出。然后,它可以被自动引用零次或一次,由 autoref 表示,引用的结果可以是原始指针或借用的指针。在这些情况下,unsizefalse

  2. 从 "thin" 到 "fat" 的转换涉及到对底层数据的 "unsizing" 操作。我们从一个 "thin" 指针开始,解引用若干次,然后 "unsize" 底层数据,最后进行自动引用。"unsize" 阶段可能会把一个固定长度的数组转变为一个动态大小的数组,或者一个具体的对象转变为一个 trait 对象,或者一个静态大小的结构体转变为一个动态大小的结构体。例如,&[i32; 4] -> &[i32] 的转换过程可以表示为:

Deref(None) -> [i32; 4],
Borrow(AutoBorrow::Ref) -> &[i32; 4],
Unsize -> &[i32],
  1. 注意,对于一个结构体,结构体的 'deep' "unsizing" 并未被记录下来。例如,对于 struct Foo<T> { x: T },我们可以强制将 &Foo<[i32; 4]> 转换为 &Foo<[i32]>。在这种情况下,自动解引用和引用的过程与上面的例子相同,但是在 unsize 中存储的类型是 Foo<[i32]>,并没有存储 [i32; 4][i32] 的底层转换过程。
  1. Box<T> 强制转换为 Box<dyn Trait> 是一个特别有趣的案例。在这种情况下,我们已经拥有了所需的指针,所以没有自动解引用,也没有自动引用。我们只需要做 Unsize 转换。当然,在某一点上,Box 应该从编译器中移出,在这种情况下,这个过程与转换结构体类似。例如,Box<[i32; 4]> -> Box<[i32]> 就是一个 Adjust::Unsize 操作,目标类型是 Box<[i32]>

Adjustment<'tcx> 结构体具有以下字段:

  • kind: Adjust<'tcx>:指示进行的调整种类。

  • target: Ty<'tcx>:指示调整的目标类型。

这个结构体有很多派生的 trait,如 Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitableLift,这些 trait 提供了诸如克隆、编码/解码、稳定哈希、类型折叠、类型访问和提升等功能。