Skip to content

A local declared without a value (long x, int[3] k, P p) reads whatever its stack slot held #3114

Closed

Description

@nicolas-maman

A local declared with a type and no value holds whatever its stack slot held before. Reading it is undefined behaviour in the generated C, and nothing reports it:

struct P {
    a: long
    w: long[4]
}

fn g() -> long {
    long x
    int[3] k
    P p
    return x + k[1] + p.a + p.w[2]
}

main() {
    println("${g()}")
}

This compiles with no diagnostic. The generated C is int64_t x; int k[3]; P p;, so g returns garbage. The same holds for an array a function means to fill in a loop when the loop misses an element (long[16] v in a block function).

Everywhere else the language gives a value a defined start:

  • make([]T, n) returns zeroed elements;
  • an array literal shorter than its array zeroes the rest;
  • a function that falls off its end returns its type's zero value.

The reference never says what a declared local holds, so the program reads a stack slot.

Fix:

  • A declaration without a value starts at its type's zero value: 0, false, "" (the null string), null, an all-zero array, and a struct with every field zero. Generated C: = 0 and = {0}. The C compiler drops the store when the program writes the value before reading it.
  • The reference says so in the Variables section.
  • Tests cover a scalar, an array, a struct with an array field, an actor handler's local and a closure's local.
  • The cost is measured on code that declares large local arrays in hot functions (the cryptography modules after std and contrib call other modules' raw layer (97 calls in 49 files) instead of their public API #3107, the cross-language benchmarks).

Found on #3101 (#3107, moving crypto buffers onto local arrays).

Activity

  1. nicolas-maman commented on Oct 26, 2026

    @nicolas-maman
    CollaboratorAuthor

    Fixed by 0082f2f, "A local declared without a value starts at its type's zero value (#3114)", which merged with #3101 (the commit named the issue without a closing keyword, so it stayed open). Checked on main at 00df4c7 (0.848.0), MinGW gcc, Windows: tests/regression/test_declared_local_starts_at_zero.ae passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions