Why shadowing is implicit?


#1

I just realize shadowing variable is implicit. From my humble perspective, it can bring some mess is big functions.

A lot of things are explicit in Rust, is there a particular reason why shadowing is not?

I’m just curious.

Thanks in advance! :smile:


#2

You can use clippy and warn on shadowing if you’re into that sort of thing. Personally I rather like shadowing and miss it in c#. Shadowing in Rust in more useful than in many other languages because it can be used to switch a local variable to or from a mutable binding without having to pick a new name. E.g.:

{
    let x = ...;
    // do stuff that does not modify x.
    let mut x = x;
    // do stuff that modifies x.
    let x = x;
    // x is immutable once more.
}

Without shadowing you would either have to pick a new name for x several times, or (which I think is more likely) you would simply declare x as mutable for the entire block of code, which is a shame if it is unnecessary.


#3

This most likely comes from Rust’s ML heritage, where shadowing is common. I don’t think it is too much of a problem, because Rust warns you about unused assignments and type errors. It is also nice for unfreezing variables, or when working with options.


#4

Note that I split the shadow lint into three lints for this exact reason; only shadow_unrelated is warn by default. At least shadow_same is considered completely rusty by many, and I’ve seen recursive code that would trip shadow_reuse, which looked quite elegant with the rebinding (think let x = x + 1 before recursing).

Also you could create another scope for your let mut x = x outside of which x would be immutable. That way you’d need one less rebinding.