What is the problem in this code?

fn main() {
    let mut x = "1234";

    ok(&mut x);
    println!("{}", x);
}

pub fn ok<'s>(_z: &'s mut &'s str) {}

The error is:

error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
 --> src/main.rs:5:20
  |
4 |     ok(&mut x);
  |        ------ mutable borrow occurs here
5 |     println!("{}", x);
  |                    ^
  |                    |
  |                    immutable borrow occurs here
  |                    mutable borrow later used here

Well the message unfortunately does not point at the real cause, which is the ok function:

pub fn ok<'s>(_z: &'s mut &'s str) {}

The issue here is that both lifetimes are the same: this forces the compiler to assume that you are borrowing x mutably for its entire lifetime, which is not the case: the mutable borrow is dropped right after the execution of ok !
To fix this, you can simply remove the lifetime annotations:

pub fn ok(_z: &mut &str) {}

Or write explicitly different lifetimes:

pub fn ok<'m, 's>(_z: &'m mut &'s str) {}

Thanks now am understand..

But explain below quote in detail with example
"assume that you are borrowing x mutably for its entire lifetime"

The outer borrow ('m in @arnaudgolfouse's explicit lifetimes example) and inner borrow ('s) are the same. That means when we did &mut x the borrow must live as long as the &str string being borrowed.

However, because string literals are compiled into the program 's is 'static while our &mut x only lasts for the duration of ok(&mut x). These lifetimes aren't compatible, so it's a compile error.

When the ok function execution is over then it would be releasing the resources right?

Then where mut borrow still held on?

The lifetimes say otherwise. The compiler will follow the lifetimes as written, even if they impose more strict requirements than you need.

What the lifetimes say in this case is that the inner immutable borrow of the str and the outer mutable borrow must end at the same place. Since the inner immutable borrow is used in the println!, the inner immutable borrow ends after the println!, but this forces the mutable borrow to also last until after the println!. This triggers a compilation error because mutable borrows are required to have exclusive access for the full duration of the borrow, but accessing x in the println! is in violation with that exclusive access.

If you don't want this requirement, change the lifetimes to say the thing you intended.

1 Like

Thank you ALICE..now am understanding

But what's happening in this case

fn main() {

let mut x  =1234;

ok(&mut x);

println!("{}",x);

}

pub fn ok<'s>(_z:& 'static mut i32){

}

At compilation, this code shows 2 errors.
How your last answer applicable to this code.

ok requires the passed borrow to live for 'static, i.e. indefinitely. So, the value behind this borrow remains inaccessible indefinitely, too.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.