diff options
| author | 2026-10-14 07:55:08 +0000 | |
|---|---|---|
| committer | 2026-10-14 07:55:08 +0000 | |
| commit | d8da21a406f449d277c42b91d4c9bf8b20bd0dcc (patch) | |
| tree | 79a4dbf6839eaee19aa626f1aa3981d5b0c19377 /docs/BORROW.md | |
| parent | build: embed images with #embed, keep everything generated in build/ (diff) | |
embed: tests, editor support and docs; js vm file access; test fixes
embed declarations get accept and reject fixtures, a run-only image check
through zc0, an lsp keyword hover and the grammar keyword. errors point at
the declaration and still declare the name, so its uses are not reported
again. zc0 tracks byte-string globals and lays embedded arrays out one word
per element, the way its own indexing reads them.
the command-line javascript vm reaches node's file system for the file
syscalls, so include and embed work there; other embedders opt in.
the web build is self-contained in build/web with its examples. README,
BORROW and BOOTSTRAP-OWNERSHIP describe the new build and ownership rules,
and ONBOARD.md is a reading and verification order for the code.
the suite passes the map header to mklayout, the wasm fuzz program uses
the include format, and lsp drivers scale their deadlines on hosts
without the arm64 jit (ZC_TEST_TIMEOUT_SCALE). LLVM_CONFIG selects an
llvm with headers for the llvm section.
Diffstat (limited to 'docs/BORROW.md')
| -rw-r--r-- | docs/BORROW.md | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/docs/BORROW.md b/docs/BORROW.md index 10beb84..f270574 100644 --- a/docs/BORROW.md +++ b/docs/BORROW.md @@ -27,7 +27,11 @@ effects are cached for the current compiler analysis and participate in the lang aliases are tied to their owner. when a tracked alias has no later use, a subsequent move or free can proceed; uses after a definite transfer or free produce an error that points to both the transfer and the later use. independent struct fields and constant array elements can be used when their projections prove they do not overlap. unknown indices and overlapping projections are not treated as disjoint. -after an owned local is released, assignment from another owner in the same declaring scope moves the replacement into that empty slot. the source and its aliases expire, the destination receives its cleanup responsibility, and loop paths still have to agree. this supports buffer-growth code such as `rt.free(buffer); buffer = replacement;` without a cast. initial declarations still cannot copy an owned local, overwriting a live owner remains an error, and captured owners are excluded from this replacement rule. +after an owned local is released, assignment from another owner declared in the same scope or a deeper one moves the replacement into that empty slot. the source and its aliases expire, the destination receives its cleanup responsibility, and loop paths still have to agree. this supports buffer-growth code such as `rt.free(buffer); buffer = replacement;` without a cast, including a replacement built inside a branch. initial declarations still cannot copy an owned local, overwriting a live owner remains an error, and captured owners are excluded from this replacement rule. + +## lends to globals + +`g = m*x;` lends an owned local to a global for the rest of the block: `x` keeps ownership and stays usable while code reached through `g` reads it, and assigning `g` again in the same block ends the lend. giving `x` away, returning, breaking out, or reaching the end of the block while the lend is open is an error, so a global never holds a borrow that outlives its owner. a restore inside a nested branch does not end a lend made outside it; the restore has to be unconditional. this is the idiom for pointing the output stream at a scratch buffer. an element borrow records its base array and known range. a constant index outside a known length gets a bounds diagnostic. mutations such as `push`, `pop`, and `resize` advance the array generation and invalidate element borrows; a later use reports the mutation and where the borrow was made. uncertain branch and loop facts are not promoted to definite errors. runtime checks remain for dynamic indices. @@ -41,7 +45,7 @@ the compiler functions, standard library, and language server currently run with the analysis runs with the existing parser, ownership checker, and lifetime records; it does not have a separate source parser or a complete path-sensitive proof. snapshots conservatively join branches and loops. low-level and unknown boundaries can hide behavior, so a quiet diagnostic set is not a whole-program safety proof. zc is single-threaded; shared closure cells do not define concurrent mutation rules. -two completeness limits block the compiler from compiling itself, and are written up in `docs/BOOTSTRAP-OWNERSHIP.md`. an owned value already held in a local has no move into another local; every accepted move originates at a call, so the free-then-replace rule above applies only when the replacement comes from a call result. and a local cannot be lent to a global, so an output stream has to be redirected at a module-level buffer rather than a scratch local. neither limit accepts an unsafe program; both refuse correct ones. +two completeness limits once stopped the compiler from compiling itself: an owner held in a local could not move into another local, and a local could not be lent to a global. the replacement and lend rules above close them; `docs/BOOTSTRAP-OWNERSHIP.md` keeps the record. the maintained regressions cover these cases: |
