Вы не можете создать изменяемую ссылку из неизменной. Это означает, что вам нужно изменить &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.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;
}