Rust 函数返回不可变引用,但借用检查器不这么认为

Rust 函数返回不可变引用,但借用检查器不这么认为,rust,borrow-checker,Rust,Borrow Checker,这里,我将一些可变引用传递到函数中,以对这些引用执行一些操作。然后,通过将这些可变引用转换为不可变引用来删除它们。然而,铁锈借用检查者似乎仍然认为它们是可变的。代码如下: //! src/lib.rs fn将\u 1\u追加到\u所有字符串:Vec->Vec{ strings.into|iter.map|s{s.push_str1;s}.collect } fn获取\u共享\u引用字符串:Vec->Vec{ strings.into|iter.map | c |和*c.collect } [测试

这里,我将一些可变引用传递到函数中,以对这些引用执行一些操作。然后,通过将这些可变引用转换为不可变引用来删除它们。然而,铁锈借用检查者似乎仍然认为它们是可变的。代码如下:

//! src/lib.rs fn将\u 1\u追加到\u所有字符串:Vec->Vec{ strings.into|iter.map|s{s.push_str1;s}.collect } fn获取\u共享\u引用字符串:Vec->Vec{ strings.into|iter.map | c |和*c.collect } [测试] fn试验{ 让strings=vec![1.to_string,2.to_string,3.to_string]; 让strings_added=将_1_追加到_allstrings.iter_mut.collect; 让strings\u shared=get\u shared\u referencestrings\u追加; 断言字符串[0],*字符串共享[0]; } 编译错误:

error[E0502]: cannot borrow `strings` as immutable because it is also borrowed as mutable
  --> src/lib.rs:16:16
   |
12 |     let strings_appended = append_1_to_all(strings.iter_mut().collect());
   |                                            ------- mutable borrow occurs here
...
16 |     assert_ne!(strings[0], *strings_shared[0]);
   |                ^^^^^^^      -------------- mutable borrow later used here
   |                |
   |                immutable borrow occurs here

如何修复此错误?我认为共享的字符串不应该再与可变借用相关。

问题不在于您的引用实际上是可变的,而是它使可变引用保持活动状态

如果有引用,请键入&'a。。。或者&“一个mut…”,然后使用它生成另一个引用,无论是reborrow&*some_引用还是字段访问&some_struct_引用。some_字段或方法或其他任何内容,那么它总是被认为是从原始引用借用的,要求原始引用与派生引用一样有效

注意,在函数声明中

fn获取共享的引用字符串:Vec->Vec{…} 如果我们将其更改为写出省略的生存期,我们得到:

fn获取共享的引用->向量字符串:向量{…} 但是,即使您可以用这种类型实现一个函数,它对调用者也没有用处,因为调用者除了至少知道'm'之外,对生命周期'i'一无所知

我们可以想象一个系统,其中可变引用具有两个生存期-让我们假设语法&'m mut'it,其中'm是引用可变的生存期,而'i不超过值的生存期。那样的话,我们可能会

fn消耗_mut_ref_products_refx:&'m mut'i i32->&'i i32{…} 但是,必须设计一套全新的生命周期规则来实现这一点,甚至可能不可能做到始终如一。这肯定不是今天的情况

我的建议是,在没有关于您正在尝试做什么的更多细节的情况下,让这段代码在您拥有的值上工作。拥有的值可以按您尝试的方式传递-因为将它们作为函数参数传递所有权,因此无需担心生命周期,而且更有可能说:我的函数使用这个并生成那个,没有强制关系

fn将\u 1\u追加到\u allmut字符串:Vec->Vec{ 对于字符串中的s.iter_mut{ s、 推送str1 } 串 } fn获取\u共享\u引用字符串:&Vec->Vec{ //或者更好,只需使用strings.iter而不是此函数 strings.iter.collect } [测试] fn试验{ 让strings=vec![1.to_string,2.to_string,3.to_string]; //.clone在这里是必需的,因为下面的断言中使用了字符串 让strings\u added=将\u 1\u追加到\u allstrings.clone; 让字符串共享=获取共享的引用和附加的字符串; 断言字符串[0],*字符串共享[0]; }
问题不在于您的引用实际上是可变的,而是它使可变引用保持活动状态

如果有引用,请键入&'a。。。或者&“一个mut…”,然后使用它生成另一个引用,无论是reborrow&*some_引用还是字段访问&some_struct_引用。some_字段或方法或其他任何内容,那么它总是被认为是从原始引用借用的,要求原始引用与派生引用一样有效

注意,在函数声明中

fn获取共享的引用字符串:Vec->Vec{…} 如果我们将其更改为写出省略的生存期,我们得到:

fn获取共享的引用->向量字符串:向量{…} 但是,即使您可以用这种类型实现一个函数,它对调用者也没有用处,因为调用者除了至少知道'm'之外,对生命周期'i'一无所知

我们可以想象一个系统,其中可变引用具有两个生存期-让我们假设语法&'m mut'it,其中'm是引用可变的生存期,而'i不超过值的生存期。那样的话,我们可能会

fn消耗_mut_ref_products_refx:&'m mut'i i32->&'i i32{…} 但是,必须设计一套全新的生命周期规则来实现这一点,甚至可能不可能做到始终如一。这肯定不是今天的情况

我的建议是,在没有关于您正在尝试做什么的更多细节的情况下,让这段代码在您拥有的值上工作。自有价值 es可以按照您尝试的方式传递-因为将它们作为函数参数转移所有权,因此无需担心生命周期,更有可能说:我的函数消耗这个并产生那个,没有强制关系

fn将\u 1\u追加到\u allmut字符串:Vec->Vec{ 对于字符串中的s.iter_mut{ s、 推送str1 } 串 } fn获取\u共享\u引用字符串:&Vec->Vec{ //或者更好,只需使用strings.iter而不是此函数 strings.iter.collect } [测试] fn试验{ 让strings=vec![1.to_string,2.to_string,3.to_string]; //.clone在这里是必需的,因为下面的断言中使用了字符串 让strings\u added=将\u 1\u追加到\u allstrings.clone; 让字符串共享=获取共享的引用和附加的字符串; 断言字符串[0],*字符串共享[0]; }
我自己还是个初学者,但我想知道字符串\u shared是否包含可变引用的不可变引用?@lxop,我已经检查过了,但你可以在签名中看到,get\u shared\u references只返回Vec,而不是Vec,所以它只是不可变引用。我自己还是个初学者,但是我想知道字符串\u shared是否包含对可变引用的不可变引用?@lxop,我已经检查过了,但是你可以在签名中看到get\u shared\u references只返回Vec,而不是Vec,所以它只是不可变引用。