3

This first Rust program won't compile because b is dropped before its reference r, which makes sense:

fn main() {
    let a = "a";
    let v;
    {
        let b = "b";
        v = &b;
    }
    println!("{}", v);
}

In this second Rust program, a reference to b is retrieved via a function, and all of the sudden there's no issue:

fn getRef(b: &str) -> &str {
    b
}

fn main() {
    let a = "a";
    let v;
    {
        let b = "b";
        v = getRef(&b);
    }
    println!("{}", v);
}

The thing is, v is still a reference to b, and b is out of scope for the println!().

Why are these two different?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
AaronF
  • 2,841
  • 3
  • 22
  • 32

1 Answers1

5

Because they aren't doing the same thing.

If you print the type of the variable, you'll see that in the first example, v is of type &&str, specifically & &'static str. In the second example, v is of type &str, specifically &'static str.

In the first example, you have a reference to a local value, which indeed goes out of scope.

In the second example, although you take a reference to b, producing a &&str, you then call a function that expects a &str. Deref coercion kicks in and automatically dereferences the value.

Thus the second example is equivalent to

fn main() {
    let a = "a";
    let v;
    {
        let b = "b";
        v = b;
    }
    println!("{}", v);
}

That is, you are making a copy of an immutable reference to a string that will live the entire life of the program.

Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • In the second example, why isn't the type of `&b` `&&'static str`? – Michael Hewson Mar 30 '17 at 03:45
  • Weird - so Rust automatically dereferences arguments as many times as is necessary? `getRef(&&&&&&&&&&&b)` compiles just fine. – Michael Hewson Mar 30 '17 at 03:50
  • 1
    @MichaelHewson [dereferences and then references once](http://stackoverflow.com/q/28519997/155423). And not just arguments, but [return values and variable assignments too](http://stackoverflow.com/q/43036307/155423). – Shepmaster Mar 30 '17 at 03:57
  • @MichaelHewson: It's a bit weird indeed; very useful for smart pointers though, which is the primary usecase of `Deref`. – Matthieu M. Mar 30 '17 at 07:12
  • So `a` and `b` have the same lifetime. And you could just pass b in directly to getRef(). – AaronF Mar 31 '17 at 17:07
  • ... without losing ownership in the process? – AaronF Mar 31 '17 at 17:08
  • @AaronF yes, because [immutable references implement `Copy`](http://stackoverflow.com/q/37381212/155423). – Shepmaster Mar 31 '17 at 18:03