As far as I understand it, it is not so easy to get not confused by variables, what's behind variables and what's behind references (or references to references to........).
I think that the reference to var50 is assigned to var228 (you will correct me if I am wrong, and I think that I sometimes use an improvable terminology..). Before leaving the {} block (statement), so when everything inside goes out of scope, RUST "cleans up" everything that's inside the statement and frees the memory. It can only clean up from bottom to top and would need to free the memory that lies behind the reference to var50. &var50 cannot be freed (dropped) because it is intended to be used in the println macro where var49 also holds a reference to what is behind var50. But now your var231 cannot be dropped and the procedure cannot finish. You create a "frustrated system by doing so". (With an integer instead of a reference this wouldn't happen because the integer would be copied not moved (or so).)
Here a citation from: Rust for Rustaceans, page 9 (I think I am allowed to cite it)
DROP ORDER
Rust automatically drops values when they go out of scope [...]. The rules for the order in which to drop are fairly simple: variables (including function arguments) are dropped in reverse
order, and nested values are dropped in source-code order.
This might sound weird at first—why the discrepancy? If we look at it
closely, though, it makes a lot of sense. Say you write a function that declares
a string and then inserts a reference to that string into a new hash table. When
the function returns, the hash table must be dropped first; if the string were
dropped first, the hash table would then hold an invalid reference! In general,
later variables may contain references to earlier values, whereas the inverse
cannot happen due to Rust’s lifetime rules. And for that reason, Rust drops variables
in reverse order.
Now, we could have the same behavior for nested values, like the values
in a tuple, array, or struct, but that would likely surprise users. If you constructed
an array that contained two values, it’d seem odd if the last element of the array
were dropped first. The same applies to tuples and structs, where the most intuitive
behavior is for the first tuple element or field to be dropped first, then the
second, and so on. Unlike for variables, there is no need to reverse the drop
order in this case, since Rust doesn’t (currently) allow self-references in a single
value. So, Rust goes with the intuitive option.
Here a code that would work with some comments when it would not work:
//#[allow(dead_code, unused_variables, unused_mut)]
fn main() {
let mut a: i32 = 9;
a = 10;
let b = &mut a;
*b = 11;
drop(b);
// must drop b otherwise problem because a cannot be
//borrowed mutably (from b) and unmutably (for printing)
println!("{a}");
let mut vart: i32 = 45;
let vart1 = &&mut &mut vart;
{
let mut var231: i32 = 1735471491i32;
let mut var230: &mut i32 = &mut var231;
let var229: &mut &mut i32 = &mut var230;
let mut var228: &&mut &mut i32 = &var229;
// this reference leads to an unsatisfiable condition
//var228 = &vart1;
}
println!("{:?}", vart1);
// two other examples concerning borrowing:
/*
//this would work
println!("{:?}", vart1);
println!("{:?}", vart);
*/
/*
//this would NOT work
println!("{:?}", vart);
println!("{:?}", vart1);
*/
}
See also here and the links in the answer ( Do mutable references have move semantics?)