m00am
m00am

Reputation: 6298

Why is this not a dangling reference?

I am following the second edition of the TRPL book (second edition) and am a little confused by one of the tasks. At the end of section 10.2 (Traits) I am asked to reimplement the largest function using the Clone trait. (Note that at this point I have not learned anything about lifetimes yet.) I implemented the following

fn largest<T: PartialOrd + Clone>(list: &[T]) -> &T {
    let l = list.clone();
    let mut largest = &l[0];

    for item in l {
        if item > &largest {
            largest = item;
        }
    }

    largest
}

This returns a reference to an item of the cloned list. And, lo and behold, it compiles. Why is this not a dangling reference (as described in section 4.2)?

As far as I understand it, largest contains a reference to an item of a (cloned) copy of list, but should l not go out of scope and thus invalidate the reference after largest has finished?

Upvotes: 3

Views: 150

Answers (1)

Matthieu M.
Matthieu M.

Reputation: 299890

Because l does not have the type you think it does:

fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let l: &[T] = list.clone();
    let mut largest = &l[0];

    for item in l {
        if item > &largest {
            largest = item;
        }
    }

    largest
}

l is a reference too, cloning a slice actually just returns the slice itself, with the same lifetime.

Therefore it's perfectly fine to take references into the slice, and your return value borrows the original slice.

Upvotes: 8

Related Questions