Why does the following program compile? Foo(1) is a temporary value, so it should go out of scope after the line where it is created, and x should be a dangling reference after that.
// This program unexpectedly compiles.
struct Foo(i32);
fn f(x: &Foo) -> &Foo {
x
}
fn main() {
let x = f(&Foo(1));
assert_eq!(x.0, 1);
}
However, if I implement the Drop trait for Foo, then the compiler rejects the program, the expected behavior.
// This program does not compile.
struct Foo(i32);
fn f(x: &Foo) -> &Foo {
x
}
impl Drop for Foo {
fn drop(&mut self) {
println!("drop");
}
}
fn main() {
let x = f(&Foo(1));
assert_eq!(x.0, 1);
}
It seems suboptimal that this case causes static promotion, rather than just promoting to a “hidden” stack slot. Why tie up space in the binary with a static if this could be desugared to a purely stack local. I guess it makes the rules and impl easier?
I suppose that depends. In a "perfect" world, the code like OP's would get optimized away entirely, with at most the constant 1 being put into a register. Without optimizations, sure, instructions would need to be present to materialize the value on each call to the function that makes use of it.
Perhaps promoting it to static still leaves room for not actually emitting it into the image, as in it's promoted to static in a moral equivalent sense but not necessarily physically.
Perhaps, although string literals being &'static is rooted in Rust history, whereas static promotion is a relatively new thing .
I suppose one could even make the argument that a stack local string ought to be subject to the same optimization potential, and maybe it is. I'm not sure how firm the compiler treats the static-ness of string slices (or static promoted rvalues). But I can see a case to be made for scalar replacing a short string slice as well (or even materializing into a stack local buffer), rather than loading from memory. I suppose if we want to be sticklers to the "zero cost abstractions" memo, then this type of thing seems relevant .
Yup -- the static is anonymous (and thus non-pub), so the optimizer is absolutely free to remove it if it turns out that nothing cares about its static-ness. As a trivial example,
Yeah, ok - I suppose if the optimizer is aggressive about removing statics whose static-ness is unobservable - and these rvalue promotions should fall into that camp - then all's good .