Found during the documentation-validation sweep (Aug 2026).
Current behavior
fir/src/lower/stmt.rs:144-165 — "Inject globals into the function scope": when lowering each function, the lowerer builds a global_prelude of fresh FirStmt::Lets that re-evaluate every recorded top-level let (snapshot of top_level_lets), plus replays deferred top-level statements (top_level_stmts, stmt.rs:165). There is no analysis of which globals the function actually references.
Problems
- Semantics: a side-effecting top-level initializer runs once per function invocation, not once at program start. That is observably different from what a module-level
let suggests.
- Performance: O(functions × globals) redundant evaluation, paid on every call.
- Shared state: since each function gets its own fresh locals, it appears module-level mutable state cannot exist (a reassignment in one function is invisible to another). Worth a test to confirm — if true, it should at least be a documented and diagnosed limitation rather than a silent one.
Possible directions
- True global storage: runtime cells initialized once (the
__top_main entry synthesis in the lowerer already exists as a natural home for one-time init).
- Or, at minimum: reference analysis so functions only re-evaluate globals they use, plus documentation/tests locking in the once-per-function semantics deliberately.
Documentation
The observed behavior is documented in the docs site under docs/src/content/docs/internals/fir.mdx (globals injection section).
Found during the documentation-validation sweep (Aug 2026).
Current behavior
fir/src/lower/stmt.rs:144-165— "Inject globals into the function scope": when lowering each function, the lowerer builds aglobal_preludeof freshFirStmt::Lets that re-evaluate every recorded top-level let (snapshot oftop_level_lets), plus replays deferred top-level statements (top_level_stmts,stmt.rs:165). There is no analysis of which globals the function actually references.Problems
letsuggests.Possible directions
__top_mainentry synthesis in the lowerer already exists as a natural home for one-time init).Documentation
The observed behavior is documented in the docs site under
docs/src/content/docs/internals/fir.mdx(globals injection section).