主要观点:
- 在 Rust 中,解决复杂所有权问题的方法是使用新类型索引,可将其视为关于引用对象的证明。
- 新类型索引不仅是绕过所有权约束的方式,还能组合成具有合理意义的复合索引类型,其语义可继承子组件的语义。
- 以编译器中的类型定义为例,通过新类型索引来准确表示和操作不同的声明及相关数据。
关键信息:
- 2015 年 Niko Matsakis 发布关于在 Rust 中使用向量索引建模图的最早帖子,2018 年 Matklad 指出
std::ops::Index特质可提供此模式的统一接口。 - 以环境结构体
Env为例,包含FunId、TypeId等,不同类型声明有多种子类型。 - 指针和引用的概念,引用不能为 null,是存在的证明。
FunId类似引用,能证明FunDecl的存在及读取权限。 - 定义
DeclId、DeclRef来处理不同声明类型,通过匹配实现获取声明的方法,DeclId对应逻辑或。 - 用
(TypeId, FunId)表示逻辑与,可组合新类型索引。 - 对于
ConstrId,需确定其父TypeDecl为AdtDecl,创建AdtId类型来证明,从而正确实现获取ConstrDecl的方法。
重要细节:
- 所有关于新类型索引的讨论基于一个隐含假设,即任何时候最多只有一个
Env,若有多个Env可能导致错误。 - 示例代码中
get_fun、get_type等方法使用Option::unwrap,若访问器方法出错则创建TypeId或FunId时已出错。 - 在处理
ConstrId时,由于TypeId不能确定TypeDecl的变体,需创建AdtId来证明是AdtDecl。 - 提及
[salsa](https://crates.io/crates/salsa)crate 是此技术的较大实现示例,其文档有相关概述。 - 注释中对一些观点进行补充说明,如关于
Option::unwrap与Option::unwrap_unchecked的选择,以及(TypeId, FunId)顺序无关等。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。