Wouter van Oortmerssen has published Goose, a systems language built on one premise: there is no heap. Every dynamic value lives inline on a data stack the compiler assigns statically, growth is a pointer bump, and scope exit is the only free. No allocator, no GC, no reference counting, no destructors, no unsafe. It compiles to a single C file, so it runs anywhere a C compiler does.

The memory model is where the speed comes from:

  • A program gets the native call stack, static data, and N data stacks the compiler works out. At most one resizable value is live per stack and it is always on top, so growth never moves anything and never checks a capacity.
  • Nothing ever moves. push returns a reference to the element it just made, so a reference into a growing array stays valid a million pushes later — the thing Vec<T> cannot promise.
  • Every reference carries a static root, the variable that bounds its target’s lifetime. The whole lifetime rule is one line: a reference must not outlive its owner. Roots are inferred and functions are specialized per root, so there is no lifetime syntax and no aliasing or exclusivity rules.
  • Freeing a million-element structure is one store to the stack top, however deeply it nests.

The data layout does the rest:

  • There is no single array type. Fixed, sized-at-construction, inline-capacity, grow-only and grow-shrink arrays all store metadata and elements inline, never a pointer to a block.
  • Structs may hold variable-size fields inline, so an order record that is 160 bytes and one allocation in C++ is 29 bytes and zero allocations here. The tradeoff: an array of variable-size elements is iterable but not indexable.
  • Algebraic data types come in two modes. Fixed mode is a tag plus room for the largest payload and stays indexable; variable mode gives every value exactly its variant’s size — 4x less memory and 2x faster than a Rust enum in their benchmark, at the cost of a value never changing variant.
  • Relative references store a typed, checked link as a one-, two- or four-byte offset, so structures are position independent and double as their own file format: saving is a write, loading is a read plus a verification pass that rejects hostile bytes.
  • Threads share nothing. A worker compiles as a separate program with its own memory, and flat values cross typed queues as a memcpy, so data races, locks and memory orderings do not exist in the language.

The claims are large and the README publishes the losses next to the wins: across sixteen benchmarks, 3.3x idiomatic C++, 1.16x hand-optimized C++, 1.12x the best safe Rust, on 1.2x to 1.9x less memory. Status is early — about 30,000 lines of C++ for a whole-program compiler, with deliberate gaps (moves for resizable values, more than one resizable per struct, labelled break, namespace privacy) tracked in the spec’s open-items appendix.

One thing worth knowing before reading the code: almost the entire implementation is AI-written. Van Oortmerssen designed Goose years ago and started implementing it, then had an LLM clone the structure of his earlier Lobster compiler. He calls it an experiment in how far a human design plus a model implementation can get, and says the back-and-forth forced him to pin down design decisions he had left unspecified.

The interesting bet is not the benchmark multiple. It is moving lifetime reasoning from the programmer to the container — Rust asks you to annotate relationships, Goose infers a root per reference — and whether that holds up outside small, whole-program code is what the samples and open items are there to test.