Carrying dependencies

As an example, I feel the thread-local which stored global “parsing state” in rustc was 30% of the reason why rust-analyzer needed to exist as a project. Things which should be independent, parallel&incremental, and which look like they are, actually aren’t, which affects the semantics of the language and constraints its evolution.

If that dependency had been explicit, maybe we would have ended up with the same Rust, but there’s a reasonable chance that, with constant reminders that “hey, our parsing is order-dependent”, someone would have done something about it.

I agree. I wrote a linter rule for zlinter to disallow global variables https://github.com/KurtWagner/zlinter/blob/0.16.x/src/rules/no_global_vars.zig. They might be a neccessary evil sometimes, but even then I recommend encapsulating the global state into a struct and exposing a global instance variable.

Such as:

const SomeState = struct {
    foo: u32,
    bar: u64,

    // zlinter-disable-next-line no_global_vars - Unfortunately the underlying API relies on global state
    var instance: @This() = .{ ... };
};
2 Likes