Skip to content

Instantly share code, notes, and snippets.

@xiaozhiliaoo
Created March 22, 2025 11:35
Show Gist options
  • Select an option

  • Save xiaozhiliaoo/fa84b3dbfd2cb63d5374b368765d2979 to your computer and use it in GitHub Desktop.

Select an option

Save xiaozhiliaoo/fa84b3dbfd2cb63d5374b368765d2979 to your computer and use it in GitHub Desktop.
rust demo:cannot borrow `*user` as mutable more than once at a time
use std::collections::HashMap;
fn main() {
}
#[derive(Debug)]
struct BigUser {
liquidation: i32,
}
#[derive(Debug)]
struct User {
symbols: HashMap<String, String>,
one_symbol: String,
}
fn fun2(user: &mut BigUser) {}
fn fun3(user: &mut BigUser, data: &mut i32) {}
// cannot borrow `*user` as mutable more than once at a time
fn loop_test(user: &mut BigUser) {
let vec1 = vec![1, 2, 3, 4, 123];
let liq_ctx = &mut user.liquidation;
// 在 for 循环中,fun2(user) 尝试再次借用 user 的可变引用,而 liq_ctx 已经是一个可变引用,
for i in vec1.iter() {
if liq_ctx == &123 {
continue;
}
fun2(user); // liq_ctx 的作用域还没有结束
}
}
fn loop_test_2(user: &mut BigUser) {
let vec1 = vec![1, 2, 3, 4, 123];
let liq_ctx = &mut user.liquidation;
// 在 for 循环中,fun2(user) 尝试再次借用 user 的可变引用,而 liq_ctx 已经是一个可变引用,
for i in vec1.iter() {
if liq_ctx == &123 {
continue;
}
}
fun2(user);
}
// cannot borrow `*user` as mutable more than once at a time
fn loop_test_3(user: &mut BigUser) {
let vec1 = vec![1, 2, 3, 4, 123];
let liq_ctx = &mut user.liquidation;
// 在 for 循环中,fun2(user) 尝试再次借用 user 的可变引用,而 liq_ctx 已经是一个可变引用,
for i in vec1.iter() {
if liq_ctx == &123 {
fun2(user);
continue;
}
}
}
// 不会发生可变借用:if_test 中,liq_ctx 的作用域在 if 语句结束后就结束了,因此 fun2(user) 可以安全地借用 user。
// if_test 函数不会发生多次可变借用,因为:
// liq_ctx 的可变引用只在 if 条件判断中被使用,不会导致额外的可变借用。
// 在调用 fun2(user) 时,liq_ctx 的生命周期已经结束,不会与 user 的可变引用冲突。
fn if_test(user: &mut BigUser) {
let vec1 = vec![1, 2, 3, 4, 123];
let liq_ctx = &mut user.liquidation; // liq_ctx 借用 user.liquidation
if liq_ctx == &123 {
// liq_ctx 的作用域在这里结束,liq_ctx 在这里被最后一次使用.一旦这个条件判断完成,liq_ctx 的作用域就结束了。
fun2(user); // liq_ctx 的借用已经释放,可以安全地借用 user, fun2(user) 的调用是在 liq_ctx 的作用域结束之后发生的。
}
// println!("{}", liq_ctx) // ------- first borrow later used here
}
// error[E0499]: cannot borrow `*user` as mutable more than once at a time
// 由于 liq_ctx 的生命周期覆盖了整个函数,Rust 编译器会认为你在调用 fun3 时同时持有了两个可变引用
fn if_test_2(user: &mut BigUser) {
let vec1 = vec![1, 2, 3, 4, 123];
let liq_ctx = &mut user.liquidation;
if liq_ctx == &123 {
fun3(user, liq_ctx);
}
}
// error[E0499]: cannot borrow `*user` as mutable more than once at a time
fn if_test_3(user: &mut BigUser) {
let vec1 = vec![1, 2, 3, 4, 123];
let liq_ctx = &mut user.liquidation;
if liq_ctx == &123 {
fun2(user);
}
println!("{}", liq_ctx)
}
// error[E0499]: cannot borrow `*user` as mutable more than once at a time
// if_multi_test 会报错是因为 liq_ctx 的作用域覆盖了整个函数,导致多次可变借用冲突。
fn if_multi_test(user: &mut BigUser) {
let vec1 = vec![1, 2, 3, 4, 123];
let liq_ctx = &mut user.liquidation; // liq_ctx 借用 user.liquidation
if liq_ctx == &123 {
fun2(user);
}
if liq_ctx == &123 {
fun2(user);
}
if liq_ctx == &123 {
fun2(user);
}
}
// error[E0499]: cannot borrow `*user` as mutable more than once at a time
// 二次可变借用
fn no_if_test(user: &mut BigUser) {
let liq_ctx = &mut user.liquidation;
fun3(user, liq_ctx);
}
fn handle_cancel_stop_order(user: &mut User, name: &str) {
// 由于symbol是从user中派生的,且symbol仍然在作用域内,Rust认为user仍然被借用,因此不允许再次借用。
let symbol = match user.symbols.get_mut(name) {
None => {
return;
}
Some(v) => v,
};
if symbol.is_empty() {
println!("cancelling stop order");
}
//change_user(user, symbol);
}
fn handle_cancel_stop_order2(user: &mut User, name: &str) {
let symbol = match user.symbols.get_mut(name) {
None => {
return;
}
Some(v) => v,
};
if symbol.is_empty() {
println!("cancelling stop order");
return;
}
change_user2(user);
}
fn change_user(user: &mut User, symbol: &mut String) {
user.one_symbol = symbol.clone();
println!("change_user: {:#?}", user);
}
fn change_user2(user: &mut User) {
println!("change_user: {:#?}", user);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment