Dangling reference to intermediate value

HI, I am new to Rust and am confused why this code compiles:

fn main() {
    let r = &(String::from("Hello"));
    println!("{}", r);
}

Who is the owner of the String data here? Doesn't it go out of scope immediately after being calculated and thus the reference is dangling?

The reference is pointing to the static memory, it's not dangling.

You can learn more by reading a similar question from another user asked just a few days ago: &str is same with slice?.

The reference is pointing to the static memory, it's not dangling.

"static"? Did you mean the stack? In this case there is a String created from the static constant.

The String is on the stack and the address refers to the stack location. Rust allows this without creating a separate local variable for the String, as a convenience I assume.

No. I meant this: Static - Rust By Example.

Ok so it's almost like this is de-sugaring to:

fn main() {
    let tmp = String::from("Hello")
    let r = &tmp;
    println!("{}", r);
}

A little weird that it works

No it's not pointing to static memory :slight_smile:

The relevant feature at play here is called “temporary lifetime extension”. The desugaring @Ha5hBr0wn came up with should he accurate.

The feature that would make a value like &0 be a reference pointing to static memory is called “constant static promotion” (exact naming can vary) and (among other conditions) it only applies to const-evaluable values, which String::from isn't.

5 Likes

Yes, if you're used to C or C++ (at least they didn't have this feature the last time I used them.) It's pretty nice once you get used to it.

Gotcha. I thought It was being turned into a string literal.

C++98 12.2.5:

The second context is when a reference is bound to a temporary. The temporary to which the reference is
bound or the temporary that is the complete object to a subobject of which the temporary is bound persists
for the lifetime of the reference except as specified below...

The "except as specified" and references bound to things which look like temporaries are both major sources of bugs.

Interesting, thanks.

Yes, this is a special case that someone thought was a good idea to add. Under the normal lifetime rules, it definitely shouldn't work. (And I think it was a bad idea to allow it in the first place, and IMO you shouldn't rely on it, because it's weirdness for no benefit.)

How could it possibly be "turned into a string literal"? String literals have type &str, not String. String is an opaque UDT that doesn't have special semantics to the compiler, unlike string literals. The compiler isn't allowed to just turn arbitrary types into other types.

Because I thought that &String was being deref coerced to &str. :smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.