简体   繁体   中英

Rust: why does borrowing a reference inside struct borrow the whole struct?

I have the following code:

struct MyStruct<'a>{
    data: &'a str,
}

fn get<'a>(S: &'a MyStruct<'a>) -> &'a str{
    S.data
}

fn set<'a>(S: &'a mut MyStruct<'a>, x: &'a str){
    S.data = x;
}

fn main(){
    let mut S = MyStruct{data: "hello"};
    let foo: &str = get(&S);
    set(&mut S, "goodbye");
    dbg!(foo);
}

This fails to compile because let bar: &str = get(&S) takes an immutable borrow of S, and on the next line we take a mutable borrow. But we didn't borrow the whole Struct S, just the reference inside the struct. Why is the borrow still active?

I think it has something to do with the lifetime annotations in get and set. Those functions are my attempt to "desugar" how the corresponding member functions would look like. If I change the signature of get to fn get<'a, 'b>(S: &'a MyStruct<'b>) -> &'b str , the code compiles. Why does the signature affect the duration of the borrow?

By specifying the lifetime in get() to be fn(&'a MyStruct<'a>) -> &'a str , you say you're borrowing the whole struct for the lifetime of the string. Because the string is used after the set() , that time period includes the set() . Thus, during the set() the struct is borrowed, which is an error.

If, on the other hand, you specify it to be fn(&'b MyStruct<'a>) -> &'a str , you borrow the struct only for the get() , and return the string inside with a different lifetime.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM