如何返回一个不可变引用后面的可变引用,该可变引用作为参数传递给该函数并得到处理?
struct Foo { i: i32 }
struct Bar<'b> {
f: &'b mut Foo
}
impl<'a: 'b, 'b> Bar<'b> {
fn func(&'a self) -> &'b mut Foo {
self.f
}
}
fn main() {
let mut foo = Foo { i: 1 };
let bar = Bar { f: &mut foo };
bar.func();
}
出现以下错误:
error[E0389]: cannot borrow data mutably in a `&` reference
--> src/main.rs:9:14
|
8 | fn func(&'a self) -> &'b mut Foo {
| -------- use `&'a mut self` here to make mutable
9 | self.f
| ^^^^^^ assignment into an immutable reference
我(某种程度上)了解编译器在此处试图阻止的事情。但是我对错误消息assignment into an immutable reference
感到困惑。到底分配给self
(或self.f
内部的是什么?)?
我编写了以下代码来模拟此问题,并得到了相同的错误消息,与上面的代码不同,我能够理解。这是代码:
fn main() {
let mut foo = Foo { i: 1 };
let bar = Bar { f: &mut foo };
let pbar = &bar;
pbar.f.i = 2; // assignment into an immutable reference
}
在第一个示例中,是否尝试将可变引用f
从self
中移出(因为&mut
不是Copy
类型),将其视为不变引用self
内部发生突变,因此错误消息assignment into an immutable reference
?
答案 0 :(得分:4)
您不能从不可变引用创建可变引用。这意味着您需要将&self
更改为&mut self
:
impl<'a: 'b, 'b> Bar<'b> {
fn func(&'a mut self) -> &'b mut Foo {
self.f
}
}
现在您的变量需要是可变的,以便您可以对该方法进行可变引用:
let mut bar = Bar { f: &mut foo };
bar.func();
到底是什么被分配给self(或在
self.x
内部?)?
该错误消息可能有点偏离。您的代码中没有分配,但是您返回的是 mutable 引用。可变引用在此可以让您做的唯一的一件额外事情就是分配self.f
或self.f.i
。
绝对可以改善此错误消息,但确实包含使&'a self
可变以解决问题的提示。
现在,您的原始问题:
如何返回一个不可变引用后面的可变引用,该可变引用作为参数传递给该函数并得到处理?
Rust为内部可变性提供了多种容器类型,例如Cell
和RefCell
。这些类型负责确保编译器的正确性,并使其成为运行时检查。将RefCell
应用于代码的一种方法可能是这样的:
use std::cell::RefCell;
use std::ops::DerefMut;
struct Foo { i: i32 }
struct Bar<'b> {
// store the data in a RefCell for interior mutability
f: &'b RefCell<Foo>
}
impl<'a: 'b, 'b> Bar<'b> {
// Return a RefMut smart pointer instead of mutable ref, but hide the implementation,
// just exposing it as something that can be mutably dereferenced as a Foo
fn func(&'a self) -> impl DerefMut<Target = Foo> + 'b {
self.f.borrow_mut()
}
}
fn main() {
let foo = RefCell::new(Foo { i: 1 });
let bar = Bar { f: &foo };
let mut f = bar.func();
f.i = 3;
}