使用结构本身的值更新结构给出:"cannot borrow `*self` as mutable because it is also borrowed as immutable"
update struct using a value from the struct itself gives: "cannot borrow `*self` as mutable because it is also borrowed as immutable"
我正在尝试创建一个 struct
,它通过附加一些“常量”字符串 first_step
来修改其 current_value
,该字符串是在首次创建 struct
时定义的。
代码
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);
}
}
我认为错误很明显(self.add
中的 self
被借用为可变的,因为 add
的签名具有 &mut self
,但随后的值be appended 也来自self
,但是这次是作为不可变借来的,我们不能借用self
既可变又不可变。
但我不知道如何解决这个问题,创建一个可以使用在创建结构本身时定义的一些“常量”值来更新自身的数据结构。在实际的“现实生活”案例中,我有一个包含 file
和 file_header: String
的 struct
,并且我想要一个将 file_header
写入 file
.
Rust 确实 允许单独借用 struct
的 部分 ,但是当您调用 function/method它采用 &mut Self
,它总是借用整个 struct
— 函数体从不用作附加信息。因此,对于您想使用来自另一部分的信息来改变结构的一部分等问题的解决方案是重写您的函数签名,以便它 具有必要的信息。
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);
}
}
你的描述“......一个可以用一些在创建结构本身时定义的“常量”值更新自己的数据结构......”表明你可能遇到比这个简单示例更复杂的情况。如果你有多个需要更新的可变字段(或者即使你真的想使用方法语法),你可以创建另一个 struct
包含正确的字段子集——然后像 do_something
这样的方法可以在内部结构上调用普通 &mut self
方法。
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);
}
}
我正在尝试创建一个 struct
,它通过附加一些“常量”字符串 first_step
来修改其 current_value
,该字符串是在首次创建 struct
时定义的。
代码
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);
}
}
我认为错误很明显(self.add
中的 self
被借用为可变的,因为 add
的签名具有 &mut self
,但随后的值be appended 也来自self
,但是这次是作为不可变借来的,我们不能借用self
既可变又不可变。
但我不知道如何解决这个问题,创建一个可以使用在创建结构本身时定义的一些“常量”值来更新自身的数据结构。在实际的“现实生活”案例中,我有一个包含 file
和 file_header: String
的 struct
,并且我想要一个将 file_header
写入 file
.
Rust 确实 允许单独借用 struct
的 部分 ,但是当您调用 function/method它采用 &mut Self
,它总是借用整个 struct
— 函数体从不用作附加信息。因此,对于您想使用来自另一部分的信息来改变结构的一部分等问题的解决方案是重写您的函数签名,以便它 具有必要的信息。
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);
}
}
你的描述“......一个可以用一些在创建结构本身时定义的“常量”值更新自己的数据结构......”表明你可能遇到比这个简单示例更复杂的情况。如果你有多个需要更新的可变字段(或者即使你真的想使用方法语法),你可以创建另一个 struct
包含正确的字段子集——然后像 do_something
这样的方法可以在内部结构上调用普通 &mut self
方法。
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);
}
}