主要观点:
- 在 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) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。