Strictness, Demand, Escape, And Alias Analysis
This page explains the native analyses used by the optimizer before it decides
whether a value can be evaluated early, skipped, stack-allocated, arena-placed,
or treated as non-aliasing memory.
The short version:
- strictness says a value is definitely needed;
- demand says how many times a value is needed;
- absence says a value, field, return piece, or closure capture is not needed;
- escape says whether an allocation stays local or leaves its lifetime;
- alias says whether two memory references can name the same storage;
- guards stop an optimization when effects, volatile operations, traps, FFI,
dynamic dispatch, or unsafe pointers make the result unsafe.
The bounded gates are:
make strictness-analysis-check
make escape-analysis-check
make alias-analysis-check
make region-arena-promotion-check
They validate the source-owned analysis rules, fixtures, generated decision
report, benchmark rows, compatibility contract, public docs, and ADR/RFC
records. They are intentionally small and single-job so they can run without
the broad release or self-host gates.
make escape-analysis-check runs make region-arena-promotion-check before
the escape-analysis evidence. Allocation promotion depends on the same escape
facts, so a stack, region, or arena decision must pass the promotion validator
before the broader escape gate accepts it.
Evidence Files
The implementation is described by these source-owned files:
analysis/native-analysis/schema.tsv;analysis/native-analysis/kinds.tsv;analysis/native-analysis/strictness-rules.tsv;analysis/native-analysis/escape-rules.tsv;analysis/native-analysis/alias-rules.tsv;analysis/native-analysis/guard-rules.tsv;analysis/native-analysis/verification-cases.tsv;analysis/native-analysis/fixtures/valid-native-analysis.json;release/native-analysis-decisions.tsv;perf/native-analysis-benchmarks.tsv;compat/native-analysis-contract.tsv;tools/native-analysis-check.py.
release/native-analysis-decisions.tsv is generated from the valid analysis
fixture and checked for byte-for-byte agreement by every gate. This makes the
optimizer decisions reproducible and reviewable.
Allocation-promotion decisions are documented separately in
docs/allocation-promotion.html and validated by
tools/allocation-promotion-check.py.
Strictness And Demand
A strict value is needed on every returning path. The optimizer may evaluate it
earlier only when doing so cannot introduce a new effect, trap, volatile access,
unknown FFI call, or dynamic dispatch result.
Demand records how often a value is needed. A value marked used-once can feed
later decisions such as call-by-value lowering, closure layout, or move-like
code generation. The demand result is rejected when an open call target,
unknown FFI boundary, or effectful operation could observe or duplicate the
value differently.
Absence
Absence analysis proves a value does not need to exist at runtime. Current
decisions cover:
- unused ADT fields;
- unused return components;
- unused closure captures.
An absence decision is accepted only when the evidence says the value is
absent and materialized=false. It is rejected around reflection-like
dynamic dispatch, unknown FFI, and effectful boundaries that could observe the
layout.
Escape
Escape analysis decides where an allocation can live:
stack-promotemeans the allocation does not leave the function frame;arena-placemeans the value escapes only inside a named arena lifetime.
The gate rejects stack promotion for any value with escapes=true. This is the
diagnostic:
NATIVE_ANALYSIS_ESCAPE
No-heap and freestanding profiles depend on these decisions because a value
that secretly escapes cannot safely live on the stack.
The allocation-promotion gate extends these checks with object lifetime, alias,
ownership, closure, actor-boundary, host-buffer, FFI, scalar replacement, stack,
region, arena, and dynamic heapification evidence.
Alias
Alias analysis decides whether memory references can overlap. mark-noalias
requires distinct provenance and alias classes. mark-readonly requires an
imported package signature that marks the referenced storage readonly.
The gate rejects noalias claims when another pointer in the same function has
the same alias class or the same provenance:
NATIVE_ANALYSIS_ALIAS
This keeps copy, load/store, and layout optimizations from corrupting memory.
Soundness Guards
The optimizer must reject accepted analysis decisions when one of these guards
is present:
NATIVE_ANALYSIS_EFFECT_GUARD
NATIVE_ANALYSIS_VOLATILE_GUARD
NATIVE_ANALYSIS_TRAP_GUARD
NATIVE_ANALYSIS_UNKNOWN_GUARD
NATIVE_ANALYSIS_DYNAMIC_GUARD
NATIVE_ANALYSIS_UNSAFE_POINTER_GUARD
The valid fixture includes rejected opportunities for each guard. The negative
fixtures prove that the checker fails closed if a forbidden decision is marked
accepted.
What This Does Not Overpromise
These gates prove analysis decisions and safety invalidation. Downstream passes
such as inlining, unrolling, tail-call lowering, code generation, and post-link
layout must still consume these decisions through their own gates before a
release can claim a generated binary changed because of them.