Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why borrow persists after clone

Tags:

rust

ownership

I can't understand why I am getting this error below: `

error[E0502]: cannot borrow `*s` as mutable because it is also borrowed as immutable
 --> src/main.rs:8:5
  |
7 |     let char_h = s.get(0..0).unwrap().clone();
  |                  ----------- immutable borrow occurs here
8 |     s.replace_range(0..0, "h");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
9 |     println!("char before {char_h} string after {}", s);
  |                            ------ immutable borrow later used here

For more information about this error, try `rustc --explain E0502`.
error: could not compile `q_line_out_of_scope` due to previous error

In the code:

fn main() {
    let mut s = String::from("Hello World!!");
    try_changes(&mut s);
}

fn try_changes(s: &mut String) {
    let char_h = s.get(0..0).unwrap().clone();
    s.replace_range(0..0, "h");
    println!("char before {char_h} string after {}", s);
}

`

I understand that I borrowed the 's' in line 7 'unwrap', but after borrow it I used clone and have no more references to the borrowed value 's'. So I would like to know why rust don't "drop" the borrow in this case, and a solution on how I could perform this feature (modify a string and have the old string version in some variable). Thanks.

I have tried to use 'as_ref' but things are becoming more complex and I think I am missing something, so I am trying to understand that so I can procced with rust studying.

like image 601
Yuri Theo Avatar asked May 31 '26 19:05

Yuri Theo


1 Answers

First, you probably want 0..1 instead of 0..0. In Rust, and most other programming languages, range definitions are inclusive on the lower end and exclusive on the upper end.

Next, s.get(0.11).unwrap() will be of type &str, i.e., a string slice. Cloning that will just copy the reference. See here: What happens when you clone a `&str`?

And because of that, cloning won't "release" the borrow. Instead, you'll need to create a new, owned string, which would be done via to_string().

See here: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9ad9ccf4c23669a77b84c1615501afde

fn main() {
    let mut s = String::from("Hello World!!");
    try_changes(&mut s);
}

fn try_changes(s: &mut String) {
    let char_h = s.get(0..1).unwrap().to_string();
    s.replace_range(0..1, "h");
    println!("char before {} string after {}", char_h, s);
}
like image 175
Lagerbaer Avatar answered Jun 02 '26 21:06

Lagerbaer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!