Rust 编译器坚持要求我传递一个拥有的值,但看起来它位于“&”引用后面

问题描述 投票:0回答:1

我有一个如下所示的结构。

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 borrow-checker
1个回答
0
投票

Rust 是一种严格类型的语言。虽然编译器确实会自动执行一些转换,例如 with

self
,但一般来说,您有责任在调用函数时提供所需类型的值。

当您有引用时编译器不会自动执行此操作的原因有两个。首先,如果您did拥有该对象,则移动该字段是有效的。当拥有的对象是引用时自动添加引用会令人困惑,但当它被拥有时却不会。规则、可靠的行为对于人类理解、工具易用性和跨实现兼容性来说非常重要。由于缺乏一致的行为,Perl 5 中的可靠工具(例如代码格式化程序)变得非常困难,并且多种实现实际上是不可能的。

其次,编译器直到编译的这个阶段之后才评估所有权和借用。类型检查发生在借用检查之前,因此编译器此时尚未评估借用和所有权规则。在类型全部解析之前,进行借用和所有权检查将非常困难,因为 Rust 编译器需要推断和计算类型才能有效地进行借用检查,因此实际上您需要首先确保类型正确。

© www.soinside.com 2019 - 2024. All rights reserved.