2020 年 1 月 5 日,作者发布了dioptre
crate,这是Driveyard的最新添加项。dioptre
是用于结构字段反射的轻量级 proc-macro。本文主题是基于此功能构建的技巧 - Cell
字段投影,从Cell<Struct>
到Cell<Field>
。
内部可变性
Rust 中严格的指针别名规则导致人们在“与借用检查器斗争”,但 Rust 也提供了内部可变性,以各种方式放宽&T
引用的不可变性,同时仍保留内存安全性。最常见的内部可变性例子是Mutex
和OnceCell
,Rust 初学者常被引导使用RefCell
来处理&T
/&mut T
规则。
Cell 及其升级
Cell
类型最初提供简单的内部可变性,可包裹Copy
类型并提供get
和set
方法。RFC 1651 使其可用于非Copy
类型,RFC 1789 使其支持对包裹对象内部的引用,提供了从&Cell<[E]>
到&[Cell<E>]
的转换。
字段投影
RFC 1789 的Cell
索引操作是一种投影形式,可从整体中提取对象的一部分。例如在处理Point
数组时,没有内部可变性会导致编译错误,通过将&mut [Point]
转换为&Cell<[Point]>
,再利用dioptre
进行字段投影可解决问题,如j.project(Point::x).set(...)
。同时,由于可拥有对结构的多个共享引用,无需特殊支持即可获取不相交字段的引用,如split(point: &Cell<Point>) -> (&Cell<f32>, &Cell<f32>)
。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。