I am trying to create a struct
that modifies its current_value
by appending some "constant" string first_step
which is defined when the struct
is first created.
code
fn main() {
let mut adder = Adder {
current_value: "init".to_string(),
first_step: ", first".to_string(),
};
adder.do_something()
}
struct Adder {
current_value: String,
first_step: String,
}
impl Adder {
fn add(&mut self, value: &String) {
self.current_value = format!("{}{}", self.current_value, value);
}
fn do_something(&mut self) {
// cannot borrow `*self` as mutable because it is also borrowed as immutable
// mutable borrow occurs here rustc(E0502)
// main.rs(24, 18): immutable borrow occurs here
// main.rs(24, 14): immutable borrow later used by call
self.add(&self.first_step);
}
}
I think the errors are quite clear (the self
in self.add
is borrowed as mutable because the signature of add
has &mut self
, but then the value to be appended also comes from self
, but this time borrowed as immutable, and we cannot borrow self
both mutable and immutable).
But I don't know how to fix this, creating a data structure that can update itself with some "constant" values that are defined when the structure itself is created. In the actual "real life" case I have a struct
that contains both a file
and file_header: String
, and I want to have a method that writes the file_header
into the file
.
Rust does allow for borrowing parts of a struct
separately, but when you call a function/method that takes &mut Self
, that always borrows the entire struct
— the body of the function is never used as additional information. So, a solution to problems like where you want to mutate part of your structure using information from another part is to rewrite your function signature so that it does have the necessary information.
impl Adder {
/// Algorithm implementation; takes all components explicitly.
/// Is not a method.
fn add_impl(current_value: &mut String, add_value: &str) {
current_value.push_str(add_value);
}
/// Method for external use — less flexible, but simple.
pub fn add(&mut self, value: &str) {
Self::add_impl(&mut self.current_value, value);
}
fn do_something(&mut self) {
Self::add_impl(&mut self.current_value, &self.first_step);
}
}
Your description “…a data structure that can update itself with some "constant" values that are defined when the structure itself is created…” suggests that you might have a more complicated situation than this simple example. If you have more than one mutable field that needs updating (or even if you really want to use method syntax), you can make another struct
that contains the right subset of fields — then the methods like do_something
can call ordinary &mut self
methods on the inner struct.
struct FancyAdder {
first_step: String,
data: AdderData,
}
struct AdderData {
current_value: String,
...
}
impl FancyAdder {
fn do_something(&mut self) {
// This borrows `self.data` mutably and `self.first_step` immutably.
// No overlap.
self.data.add(&self.first_step);
}
}
impl AdderData {
fn add(&mut self, value: &str) {
self.current_value.push_str(value);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.