我有一个如下所示的结构。
struct Test {
field: Vec<String>,
}
我将此结构的引用作为函数参数传递。 我有第二个函数需要
&Vec<String>
。
fn main() {
let obj = Test { field: vec![] };
takes_ref_to_struct(&obj);
}
fn takes_ref_to_struct(obj: &Test) {
takes_ref_to_field(obj.field);
}
fn takes_ref_to_field(field: &Vec<String>) {}
由于以下错误,此用法将无法编译:
error[E0308]: mismatched types
--> src/main.rs:11:24
|
11 | takes_ref_to_field(obj.field);
| ------------------ ^^^^^^^^^ expected `&Vec<String>`, found `Vec<String>`
| |
| arguments to this function are incorrect
|
= note: expected reference `&Vec<String>`
found struct `Vec<String>`
note: function defined here
--> src/main.rs:14:4
|
14 | fn takes_ref_to_field(field: &Vec<String>) {}
| ^^^^^^^^^^^^^^^^^^ -------------------
help: consider borrowing here
|
11 | takes_ref_to_field(&obj.field);
显然我可以添加建议的借用,但为什么这是必要的?如果我尝试改变这个领域
fn takes_ref_to_struct(obj: &Test) {
obj.field.clear();
}
编译器按预期进行抱怨
error[E0596]: cannot borrow `obj.field` as mutable, as it is behind a `&` reference
--> src/main.rs:11:5
|
11 | obj.field.clear();
| ^^^^^^^^^^^^^^^^^ `obj` is a `&` reference, so the data it refers to cannot be borrowed as mutable
Rust 是一种严格类型的语言。虽然编译器确实会自动执行一些转换,例如 with
self
,但一般来说,您有责任在调用函数时提供所需类型的值。
当您有引用时编译器不会自动执行此操作的原因有两个。首先,如果您did拥有该对象,则移动该字段是有效的。当拥有的对象是引用时自动添加引用会令人困惑,但当它被拥有时却不会。规则、可靠的行为对于人类理解、工具易用性和跨实现兼容性来说非常重要。由于缺乏一致的行为,Perl 5 中的可靠工具(例如代码格式化程序)变得非常困难,并且多种实现实际上是不可能的。
其次,编译器直到编译的这个阶段之后才评估所有权和借用。类型检查发生在借用检查之前,因此编译器此时尚未评估借用和所有权规则。在类型全部解析之前,进行借用和所有权检查将非常困难,因为 Rust 编译器需要推断和计算类型才能有效地进行借用检查,因此实际上您需要首先确保类型正确。