Why is this lifetime function possible?

Viewed 71

I've discovered some behavior I cannot explain. I've written this function:

fn main() {
    let word_one = "ONE";
    let x;
    {
        let word_two = "THREE";
        x = get_ref(&word_one, &word_two);
    }
    println!("{}", x);
}

fn get_ref<'a>(a: &'a str, b: &'a str) -> &'a str {
    if a.chars().count() >= b.chars().count() {
        return a;
    }
    return b;
}

This function is possible, even if the lifetime of word_two isn't long enough to build a reference. Otherwise this example isn't possible:

fn main() {
    let word_one = "ONE";
    let x;
    {
        let word_two = "THREE";
        x = &word_two;
    }
    println!("{}", x);
}

Unfortunately I've discovered nothing in the docs which would explain this behavior.

1 Answers

Rust's auto-derefencing rules are messing you up. What you've written is syntactic sugar for the following:

fn main() {
    let word_one = "ONE";
    let x;
    {
        let word_two = "THREE";
        x = get_ref(word_one, word_two);
    }
    println!("{}", x);
}

fn get_ref<'a>(a: &'a str, b: &'a str) -> &'a str {
    if a.chars().count() >= b.chars().count() {
        return a;
    }
    return b;
}

This is because word_one and word_two are of type & 'static str. They are references to underlying string objects which have been statically allocated.

On the other hand,

let x;
{
   let word = "word";
   x = &word;
}

does not work because there is no dereferencing magic. &word is of type &'a &'static str where 'a is the lifetime bounded by the braces. So the value does not live long enough.

Related