3

Consider the following:

struct Str<'a> {
    s: &'a str,
}

fn f1<'a>(_: &'a mut Str<'a>) {}

fn f2<'a, 'b>(_: &'a mut Str<'b>) {}

fn main() {
    let s = "hello".to_string();
    let mut a = Str {
        s: &s,
    };

    f1(&mut a);
    // f2(&mut a);

    let t: &Str = &a;
}

f2 uses two different lifetimes, as it would when I elided them, which works fine.

At this point, I thought that the lifetime 'a refers to the lifetime of &mut a, and 'b refers to the lifetime of &s.

And then I wrote f1 which uses a single lifetime parameter, suspecting that lifetime 'a would refer to the shorter of the lifetime of &mut a and the lifetime of &s.

However, this f1 fails with the following error:

error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
  --> src/main.rs:21:19 
   |
18 |     f1(&mut a);
   |        ------ mutable borrow occurs here
...
21 |     let t: &Str = &a;
   |                   ^^
   |                   |
   |                   immutable borrow occurs here
   |                   mutable borrow later used here

The error confuses me: Why is a still borrowed as mutable after calling f1?

Why does this fail, and what does the error message supposed to mean?

1 Answer 1

2

Why is a still borrowed as mutable after calling f1?

fn main() {
    //                  scope of s ---\
    let s = "hello".to_string(); //   |
    let mut a = Str {            //   |
        s: &s,                   //   |
    };                           //   |
                                 //   |
    //        f1 borrows a until ---\ |
    f1(&mut a);                  // | | 
    // but it's used here \         | |
    let t: &Str = &a; //  X      // | |
                                 // X X
}

The scope of s is until the end of main. Due to the lifetime annotations on f1's arguments, the mutable reference &mut a has its lifetime tied to the scope of s, which means that f1 is borrowing a for the entire scope of s.

This is not a problem with immutable references because longer lifetimes may be coerced to shorter ones; in other words lifetimes of immutable references are covariant. But lifetimes of mutable references are invariant. That means they cannot be coerced to shorter (or longer) lifetimes.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.