1

If I call:

fn nothing() -> i32{
    let x = 2;
    let x = 3;
}

I have read that a new address is allocated on the stack and the old variable is "inaccessible" by its name (but isn't deallocated?). Did I get bad information?

Why doesn't Rust keep the same part of memory on the stack and.. mutate it? let does not declare a constant or static so what is going on here? Is there a way to have multiple handles during variable shadowing such as pointing to the stack?

If so can the compiler perform a 0 reference count check and optimize away multiple lets with a single mut if it is never pointed to since there is by definition only the name handle that mutates value?

Is this solely due to the native multithreading and concurrence safety design choices?

Bots Fab
  • 139
  • 1
  • 9
  • See also: https://stackoverflow.com/questions/40621325, https://stackoverflow.com/questions/59860476, and https://stackoverflow.com/questions/57844021 – E_net4 Oct 09 '20 at 08:32
  • That is insightful, thank you, but I am more asking about what happens in the compiler and runtime stack (memory) with allocated variables. Why don't shadowed variables get cleaned up when there is no handle/reference? It seems like a runtime artifact to bloat the stack with multiple shadows of a variable that aren't pointed to otherwise which seems like it'd be 80% of the variables that get shadowed in the wild. What if I have a large struct like a neural network that barely fits into memory on the stack and shadow it 2 or 3 times in the same stack frame, I get a stack overflow right? – Bots Fab Oct 09 '20 at 21:23
  • I don't mean to complain given all the memory magic that Rust does and I'm fanboying really hard already given the tidiness, freedom and free abstraction built into Rust. I mean for this to be constructive and insightful, maybe I'll contribute to rust-lang one day (I wish). – Bots Fab Oct 09 '20 at 21:29
  • actually ya that answers it moreover :( – Bots Fab Oct 09 '20 at 21:37

1 Answers1

4

Did I get bad information?

Your information is correct. But your original variable may be borrowed, and used indirectly, so it cannot simply go away unconditionally:

fn nothing() {
    let x = 2;
    let p = &x;
    let x = 3;
    dbg!(*p); //prints 2
}

And it has nothing to do with multithreading. It is a purely syntactic feature. From the code generation point of view, your code is identical to:

fn nothing() -> i32{
    let x1 = 2;
    let x2 = 3;
    //do not use x1 ever again
}

That is, shadowing does not change the semantics of the code. Why should it? The simplest definition of shadowing is that it does nothing special, just hides the previous name, syntactically.

If you want to reuse the stack memory just use the same variable:

fn nothing() -> i32{
    let mut x = 2;
    x = 3;
}

That said, if your type is not Drop then it is perfectly possible that your two x reuse the same memory. But so does my x1/x2, as they are equivalent.

rodrigo
  • 94,151
  • 12
  • 143
  • 190