struct Foo {
stack: Vec<String>,
}
impl Foo {
pub fn bar(&mut self) {
// find condition here is for example only.
// position in the stack is important.
if let Some(s) = self.stack.iter().find(|x| x.is_ascii()) {
self.baz(s.as_str());
}
}
fn baz(&mut self, _input: &str) {
// mutating of `self.stack` and some other fields.
}
}
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/main.rs:8:13
|
7 | if let Some(s) = self.stack.last() {
| ----------------- immutable borrow occurs here
8 | self.baz(s.as_str());
| ^^^^^---^^^^^^^^^^^^
| | |
| | immutable borrow later used by call
| mutable borrow occurs here
I don't want to clone a string every time. How to get it working with borrowed string?
And yes, I really need the &mut self
here.
You can wrap your strings in Rc
that way you can cheaply clone
the Rc
and have something owned so you don't reference the original struct:
use std::rc::Rc;
struct Foo {
stack: Vec<Rc<String>>,
}
impl Foo {
pub fn bar(&mut self) {
if let Some(s) = self
.stack
.iter()
.find(|x| x.is_ascii())
.map(Rc::clone)
{
self.baz(s.as_str());
}
}
// …
}
For mutable access to the underlying strings you can use Rc::get_mut
or wrap further in RefCell
or similar.
Solution to the original underspecified question:
The most straight forward solution is to just remove the String
from Foo
for the baz
call:
struct Foo {
stack: Vec,
}
impl Foo {
pub fn bar(&mut self) {
if let Some(s) = self.stack.pop() {
self.baz(s.as_str());
self.stack.push(s);
}
}
fn baz(&mut self, _input: &str) {}
}