A bit problem about Rust's function parameter and ownership

Viewed 137

here's my problem:

fn main() {
    let mut s = String::from("hello");
    let s1 = &mut s;
    let s2 = s1;

    *s2 = String::from("world1");
    *s1 = String::from("world2");

    println!("{:?}", s);
}

it will result in a compile error because s1 has type &mut String which doesn't implement the Copy trait.

But if I change the code as below:

fn c(s: &mut String) -> &mut String {
    s
}

fn main() {
    let mut s = String::from("hello");
    let s1 = &mut s;
    let s2 = c(s1);

    *s2 = String::from("world1");
    *s1 = String::from("world2");

    println!("{:?}", s);
}

it will compile without any error message.

I know when a reference passed to a function, it means the reference borrows the value insteading of owning it.

But in the situation above, it seems like when s1 was passed to fn c and returned immediatelly, s2 borrowed s1 so s1 couldn't be derefed until s2 was out of it's lifetime scope.

So what happened when s1 was passed into the fn c?

1 Answers

From @Denys Séguret's hint, I guess when s1 was passed to fn C, Rust core compiled the parameter s1 to something like &mut *s1, so there was an immutable borrow of s1.

That's why if we put

*s2 = String::from("world1");

behind

*s1 = String::from("world2");

Rust would tell us:

assignment to borrowed `*s1`

And when s2 goes out of it's lifetime scope, there is no borrow of s1 anymore, so s1 can be derefed again.

But I'm not quite sure whether it's a right explanation.

Related