Maximally minimal view types
摘要
Rust语言View Types提案,解决借用检查器痛点。当前Rust在drain循环中调用self方法会报错,因为借用检查器不知道方法只访问某些字段。View Types允许显式声明方法将访问哪些字段。
核心亮点
1. 当前问题
假设有一个MessageProcessor结构体,包含消息和统计信息:
pub struct MessageProcessor {
messages: Vec<String>,
statistics: Statistics,
}
fn process_pushed_messages(&mut self) {
for message in self.messages.drain(..) {
self.process_message(message); // <-- ERROR: `self` is borrowed
}
}
fn process_message(&mut self, message: String) {
self.statistics.message_count += 1;
self.statistics.total_bytes += message.len();
}
问题在于:self.messages.drain(..)借用self.messages。当调用self.process_message时,编译器假设你可能修改任何字段,包括self.messages,因此报错。
2. View Types解决方案
View Types允许你声明方法只访问特定字段:
fn process_message(&mut self {statistics}, message: String) {
// ----------------
// 简写: `self: &mut MessageProcessor {statistics}`
self.statistics.message_count += 1;
self.statistics.total_bytes += message.len();
}
3. 语法扩展
View Types扩展了结构体类型的语法,可选择包含可访问字段列表:
RustType := StructName<...>
| StructName<...> { .. } // 所有字段可访问
| StructName<...> { (fields),* } // 指定字段可访问
4. 借用检查器如何工作
集成Views到借用检查器非常简单。借用检查器在看到借用表达式时,会记录"贷款",跟踪被借用的位置、借用的方式(mut/shared)和生命周期。
对于View Types,我们记录多个贷款而不是单个贷款。例如:
&mut self→ 记录一个mut贷款&mut self {field1, field2}→ 记录两个mut贷款:self.field1和self.field2
5. 运行时无开销
View Types是纯静态构造,不改变编译方式。process_message方法仍然只接受一个指向self的指针。
6. 实现难度
"坦率说,不难。如果我们找到一个想要承担的贡献者,我认为今年就可以发货。"
核心洞察
"借用的核心问题是:借用检查器不知道
process_message方法将只访问statistics字段。"