Skip to main content

Command Palette

Search for a command to run...

理解rustc_middle中的adjustment.rs

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

  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, TypeVisitable 和 Lift,这些 trait 提供了诸如克隆、编码/解码、稳定哈希、类型折叠、类型访问和提升等功能。

More from this blog

c_void到u8 - laertes-2023

为什么把c_void重命名为u8? 类型大小: u8通常代表一个单字节(8位)的无符号整数。c_void作为一个“空”类型,通常也被当作一个单字节进行处理(尽管这取决于具体的实现)。因此,这两者在大小上是匹配的。 类型转换简便: u8是一个非常基础的类型,与之进行类型转换通常比较方便。 操作简单: u8类型上可用的操作相对简单,可能更容易进行后续的代码分析或转换。 为什么不把其他东西重命名为u8? 类型语义: 其他类型可能具有其自己的语义和操作,这些可能不适用或不等价于u8。 数据...

Sep 5, 20231 min read

Retriever's blog

48 posts