The discussion about shadowing variables doesn’t seem to make a very good case to me about this feature. Why would you want to introduce all those variables on the stack, each of a different type (even if they have the same name, presumably they are new pieces of stack memory)? Why not just mutate an existing variable each time?
Sometimes you need a different type and you don't care about the intermediate values. Parsing a string into an integer is a good example. Once you have the integer, generally you don't care to use the string anymore.
let num = String::from("10");
let num: i32 = num.parse().unwrap();
For me, understanding shadowing adds to one's understanding of what 'let' means. Whether the shadowed variables each get new memory I'd be happy to leave to the compiler/optimiser.