aboutsummaryrefslogtreecommitdiff
path: root/docs/design/storage-analysis.md
blob: 432139a6d2bb7b4bf8a22e4dab9d447893db7d39 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# bounds and lifetime findings

## what the compiler knows

the compiler records constant element counts for `new(n)`, `new(T, n)`, fixed arrays, and newly created array handles. a direct local alias shares the allocation's facts. a definite `free` or `recycle` ends that allocation's lifetime; closing a scope ends its stack storage and automatically released owned objects.

an index outside a known length produces a warning. dereferencing, indexing, or accessing a field after a recorded lifetime end also produces a warning. these findings apply to unchecked code too. existing ownership errors and fixed-array index errors keep their current behavior. warnings do not prevent compilation.

```zc
unchecked fn example() {
    let p = new(int, 3);
    let q = p;
    q[3] = 1;       // warns: index 3 is outside length 3
    free(p);
    return q[0];    // warns: this allocation was freed
}
```

## what stays unknown

this is analysis of compiler-recorded facts, not a proof of the whole program. branch and loop snapshots stay conservative where paths disagree. typed pointer arithmetic, casts, fields, element ranges, and checked function parameter effects carry provenance when the compiler can establish it. known array mutations advance a generation and invalidate older element borrows. an unknown call or opaque operation drops facts it may change; an inferred checked function summary can preserve facts for a read-only borrower.

unknown facts do not produce definite bounds or lifetime findings. runtime array checks still run. unchecked code, raw assembly, integer-to-pointer casts, untyped word storage, and unknown native or indirect calls remain boundaries. the ownership and temporary-slot rules, including those limits, are described in [BORROW.md](../BORROW.md).

## editor previews

array and pointer hovers show the known element count and lifetime at that reference. a live stack allocation names its scope exit as its lifetime end. a live heap allocation ends when freed or released by its owner. a reference after a recorded end names that line. unavailable sizes and lifetimes say `unknown`.

facts are copied into each reference's editor record while the compiler parses it. a later `free` therefore does not make an earlier hover claim the object was already dead. block comments and inferred type text remain part of the same markdown preview.

## focused checks

`node tests/drivers/storage_analysis_test.js build/bin/zclsp` checks known bounds, packed elements, direct aliases, free and scope lifetimes, hover metadata, and safe or uncertain neighboring cases.