[rust-dev] Proposal: Eliminate "let" hoisting

Brendan Eich brendan at mozilla.org
Sun Jul 31 09:35:14 PDT 2011

On Jul 31, 2011, at 9:23 AM, Patrick Walton wrote:

> Rust always hoists function items (named functions), even nested ones. I think that's a great feature for the reasons you describe -- it gets rid of having to think about the function dependency DAG, which is a big pain in C and C++, and even worse in Standard ML and OCaml, where there aren't even prototypes. Hoisting for named functions is fine because they're always completely defined before execution begins -- in particular, they can't close over any values, so there's no question as to which bindings they capture (uncertainty over this is why I assume ML functions don't hoist).

Right (and sorry for forgetting Rust's hoisting of named fns).

> So I should have been more clear -- in this scheme local variables would be the only non-hoisted bindings. It's rare that local variables need to be mutually recursive; the only time is when you want mutually recursive capturing lambdas, and in that case I don't think manually hoisting is too bad.

That was exactly our conclusion for JS when we were entertaining the C++-based scope rule. You can't make:

    let a = b;
    let b = a;

work in either the temporal-dead-zone let-hoisting regime, or in the C++-like regime. But the interesting case is of course not this nonsense-case, it is something more like this:

    let a = function(){return b};
    let b = function(){return a};

and here, hoisting with temporal dead zone wins since the above "just works" -- you do not have to refactor to:

    let a, b;
    a = function(){return b};
    b = function(){return a};

as you would with the C++-based rule.

> Absent mutual recursion, I don't see any benefit to hoisting local variables, other than (a) consistency between items and locals and (b) simplifying the compiler implementation a bit (but note that we actually get this wrong at the moment -- we initialize local variables at the time we see the "let", which can cause segfaults).

The crucial requirement is that Rust doesn't allow local variables to be captured by hoisted (i.e., named) fns -- right?


More information about the Rust-dev mailing list