Why is this considered borrowed

72 views Asked by At

I've been learning rust and I've been trying to learn the borrow checker works but i've come across this two examples that i don't understand why only one of those is considered borrowed :

fn main() {
    let mut x = String::from("aa ab");

    let y = first_word(&x);

    x.clear(); //Error cannot borrow X

    println!("{y}");


}

//Returns an i32 reference
fn first_word(s: &String) -> &i32 {
    return &32;
}   
fn main() {
    let mut x = String::from("aa ab");

    let y = first_word(&x);

    x.clear(); //Everything is fine

    println!("{y}");


}

//Returns an i32
fn first_word(s: &String) -> i32 {
    return 32;
}   

Is it possible for someone to explain why only the second one works?

1

There are 1 answers

0
Sebastian Redl On BEST ANSWER

Rust does not look into function to understand how they work on the outside. The function signature must contain all necessary information.

The signature fn first_word(s: &String) -> &i32 says "takes a reference to a string" (by the way, it's practically never useful to have a &String, always use &str instead), and return a reference to an int. But Rust also needs lifetime information, i.e. some bounds on how long the things behind the references live.

The way this works is a very simple process called lifetime elision. For "takes a reference, returns a reference", the sane assumption is that whatever is returned is somehow related to what's passed in, so the full signature becomes fn first_word<'a>(s: &'a String) -> &'a i32.

This means that the compiler, when it sees a call to first_word, will assume that as long as you keep the returned reference around (the y in your code), the thing passed in is still borrowed.