Roadmap
Rough ordering of the major pieces of work. This page is the one-screen view; the design detail and the reasoning live in the RFCs each milestone links to. Everything here is subject to change as we learn.
The design today is RFC 0036
over the guards of RFC 0035. The
milestones before it are summarised under History; their RFCs keep the
detail, and the per-RFC validation records of the milestones before RFC
0030 remain in the repository history at tag v0.10.0.
Now: RFC 0036 — Deterministic heap reuse
Section titled “Now: RFC 0036 — Deterministic heap reuse”Design: RFC 0036 — Deterministic heap reuse
(Accepted; being implemented on rfc0036-deterministic-safety, and
Implemented once its Acceptance gates pass on the final tree). A released
heap block is reused only after a sweep (the program’s threads stopped,
its stacks, registers, writable data and live heap scanned conservatively)
finds no pointer to it, so a use after free or a double free traps however
much memory the program allocated since; sweeps are paced to a small share
of the run time. A fortified call’s object size is checked; code written
for ASan sees ASan’s macros and interface; locals whose lifetimes never
overlap share frame space; the globals of shared libraries and bundles are
registered with the process’s runtime; the number parsers no longer need a
terminator they never read. Deleted: the advisory analysis (the weavec
tool, -fweavec-diagnose, weavec --whole-program, lib/Analysis, all of
lib/Core but the library table), every annotation but WEAVEC_UNSAFE,
and their diagnostics.
The RFC’s first draft also made spatial safety and use after return deterministic (bounds from each pointer’s provenance, locals in frame blocks from the arena). It was implemented on the same branch and measured at twice v0.16.0’s run time (geometric mean 3.1× the reference compiler, QuickJS 10.8×); the revision keeps the cheap part and records the measurement of each mechanism in its Alternatives. The stages:
- S0 The RFC: the revision.
- S1 Remove the first draft’s spatial and frame mechanisms:
provenance bounds, escapes and the escape registry, pointer slots,
frame blocks, the
setjmphook, the globals table; RFC 0035’s native frames back. - S2 Shared frame space (
StackLifetime). - S3 The sweep’s cost: pacing, the image table, address-order reuse.
- S4 Cases, lit and runtime tests for the revised scope.
- S5 Fresh iterations on darwin-arm64: the motivation’s projects, the corpus, the gates (recorded in the RFC’s Measured gates), the documentation.
- Linux through CI, then the RFC is Implemented (QuickJS’s run time, the cost of the ASan contract, is carried forward).
RFC 0035’s plan for RFC 0036, ownership as contracts checked at function entry, is withdrawn: it would remove guards on the strength of inferred facts, which would have to be right where the analysis measured 62 false findings in 69 (RFC 0036 Alternatives).
Done: RFC 0035 — Guard by default
Section titled “Done: RFC 0035 — Guard by default”Design: RFC 0035 — Guard by default
(Implemented; its Measured gates record the final tree, with the run
time of interpreters (Lua, cJSON) and the build time of some units carried
forward; RFC 0036 supersedes its quarantine’s reuse after a byte budget
and its advisory analysis, and amends its frame layout).
weavec-cc guards every memory access in LLVM IR against the runtime’s
shadow memory, and removes a guard only where a local rule proves it
redundant (in bounds of a local or a global, covered by a dominating guard,
merged in a block, a loop whose whole range is checked once); the passes
lay out stack frames and globals with redzones, so use after scope traps;
the shadow says what is addressable, so untracked memory is fast; Clang’s
array-bounds checks keep typed indexes in bounds; library calls are
guarded from the library table or redirected to checked versions. Deleted:
the checks inserted through Sema, deferred CodeGen, the check planner and
the prelude, unit records and the link step, the require levels, and the
analysis ledger.
RFC 0036’s Future work:
- Spatial determinism (an access checked against its pointer’s object) and use after return, under a cost budget measured before the design.
- Concurrent marking, so that a sweep does not stop the program for its whole duration.
- Hardware memory tagging (Arm MTE, Apple MIE) where the processor has it.
- Adoption: relocatable installs, packages, a vendored
weavec.h.
- Concurrency safety beyond assumption A3 (data races between a guard and its access).
- C++ and Objective-C, which pass through to Clang unchanged today.
History
Section titled “History”The milestones that built the model, the analysis and the guards. RFC 0036 deletes the analysis and marks the RFCs that specified it (0001–0017, 0031) Superseded; they stay as the record of what was built and measured.
| Milestone | Design | Scope | RFC status |
|---|---|---|---|
| 0 Scaffolding | RFC 0001 | Layered libraries, pipeline, annotation header, the ownership model | Superseded by RFC 0036; guarantee replaced by RFC 0030, then RFC 0035 |
| 1 Intra-procedural checking | RFC 0002 | CFG dataflow, alias relation, moves, loans, lifetimes | Superseded by RFC 0036 |
| 2 Signature inference and annotations | RFC 0003, RFC 0004 | Summaries, reconciliation, raw pointers, unsafe regions, indirect calls | Superseded by RFC 0036; unsafe regions live on in RFC 0035 |
| 3–4 Compiler driver and whole program | RFC 0005 | weavec-cc, --whole-program |
Superseded by RFC 0036; weavec-cc lives on, records and the link step deleted by RFC 0035 |
| 5 Precision | RFC 0006 | Non-lexical loans, condition facts, element places, outcome-conditional summaries | Superseded by RFC 0036 |
| 6 Resource lifecycle | RFC 0007 | Leaks, release families, owned fields | Superseded by RFC 0036 |
| 7 Pointer validity | RFC 0008 | Null dereferences, uninitialised pointers, invalid releases, replaced values | Superseded by RFC 0036 |
| 8 Value-conditional behaviour | RFC 0009 | Scalar facts, guarded effects, inferred noreturn |
Superseded by RFC 0036 |
| 9 Shared ownership | RFC 0010 | Reference counts, ownership by outcome | Superseded by RFC 0036 |
| 10–11 Spatial safety | RFC 0011, RFC 0012 | Derived pointers, extents, strings, sized fields, assumptions | Superseded by RFC 0036 |
| 12 Interprocedural heap state | RFC 0013 | Heap postconditions, value snapshots | Superseded by RFC 0036 |
| 13 Pointer identity and call effects | RFC 0014 | Function values, callback specialisation, pointer-copy identity | Superseded by RFC 0036 |
| 14 Arrays and containers | RFC 0015 | Element selectors, ranges, container ownership | Superseded by RFC 0036 |
| 15 Compositional call checking | RFC 0016 | Call contexts under caller alias relationships | Superseded by RFC 0036 |
| 16 C integers and spatial checking | RFC 0017 | Target integer semantics, typed expressions, VLAs, flexible arrays | Superseded by RFC 0036 |
| 17–27 Checked mode | RFC 0018–RFC 0029 | Opt-in checked functions with safety contracts | Superseded by RFC 0030; the mode is deleted |
| 28 Prove or trap | RFC 0030 | One outcome per safety facet, the library table, pointer kinds, function-pointer slots | Implemented; its enforcement superseded by RFC 0035 and its analysis by RFC 0036; the library table lives on |
| 29 The object engine | RFC 0031 | Facts on abstract objects and symbolic values, so every alias sees every fact | Superseded by RFC 0036, which deletes the analysis and weavec |
| 30 Runtime enforcement | RFC 0032 | The runtime’s allocator and quarantine, guards | Implemented; guards and registration superseded by RFC 0035, the quarantine’s reuse by RFC 0036 |
| 31 Drop-in by default | RFC 0033 | Correct untuned projects build and run; one runtime per process | Implemented; link modes and records superseded by RFC 0035 |
| 32 Fast enforcement | RFC 0034 | Shadow memory, confirmed errors, the work budget | Implemented; guard lowering superseded by RFC 0035 |
| 33 Guard by default | RFC 0035 | Every access guarded in LLVM IR, local removal rules, redzones, the advisory analysis | Implemented; the quarantine’s budget and the analysis superseded by RFC 0036, the frame layout amended |
RFCs 0030–0034 made the analysis decide what the build enforced. Measured after RFC 0034, the runtime did the catching and the analysis caused the false stops, the missed bugs (wrong proofs removed needed guards) and most of the build cost, which is why RFC 0035 guards every access and makes the analysis advisory. Measured after RFC 0035, the advisory analysis reported no bug worth fixing on untuned code and found none of the bugs the guards miss, while a use after free passed once the quarantine had recycled its block, which is why RFC 0036 deletes the analysis and reuses released memory only after a sweep finds no pointer to it.
Ongoing
Section titled “Ongoing”- Corpus testing against real C projects pinned by SHA
(
scripts/corpus-gate.pyovertest/corpus/: a ratchet intest/corpus/expected.jsonand a verdict for every guard failure intest/corpus/triage.json);--quickon every pull request,--fullweekly. - Windows support.