Why does the order of borrowing matter in rust?

这一生的挚爱 提交于 2020-08-19 11:41:09

问题


fn say_hello(s: &str) {
    println!("Hello {}", s);
}

Why does this work

fn main() {
    let mut name = String::from("Charlie");
    let x = &mut name;
    say_hello(x);
    name.push_str(" Brown");
}

but this doesn't?

fn main() {
    let mut name = String::from("Charlie");
    let x = &mut name;
    name.push_str(" Brown");
    say_hello(x);
}

all I did was switch the order of the two functions but it seems like x has mutably borrowed name and push_str has also mutably borrowed name in both situations, so why does the first example compile?

If I take out the call to say_hello() why does the order of the two not matter even though there are still two mutable borrows?

Edit: Is this similar?

fn change_string(s: &mut String) { // s is mutably borrowed but isn't used yet
    println!("{}", s.is_empty()); // so the scopes don't overlap even though is_empty is making an immutable borrow?
    s.push_str(" Brown");
}

回答1:


One of Rust's borrowing rules is that mutable references are exclusive. Meaning, while x is alive, name cannot be used.

So, why does the first example compile even if x is still in scope? Because Rust also has non-lexical lifetimes meaning x stops "living" after its last use.

fn main() {
    let mut name = String::from("Charlie");
    let x = &mut name;
    say_hello(x);            // "x"s lifetime ends here, releasing the exclusive borrow
    name.push_str(" Brown"); // "name" can be used again
}



回答2:


Because in your first case, the two mutable borrow scopes don't overlap and you have only one borrow at any given point of time; but in your second case, they overlap, which means you have multiple mutable borrows at the certain point of time, which is not allowed:

First case:

fn main() {
    let mut name = String::from("Charlie");
    let x = &mut name;
    say_hello(x);             // the mutable borrow ends here
    name.push_str(" Brown");  // a new mutable borrow
}

Second case:

fn main() {
    let mut name = String::from("Charlie");
    let x = &mut name;
    name.push_str(" Brown");  // the first mutable borrow is still 
                      // alive, you have two mutable borrows here
    say_hello(x);       // the first mutable borrow ends here
}


来源:https://stackoverflow.com/questions/62959393/why-does-the-order-of-borrowing-matter-in-rust

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!