build: torb build --explain-copies #61
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Copy on write hides where a copy happens;
torb build --explain-copiesreports each copy the compiler can prove, at its source span, with the reason. Design: PERFORMANCE.md section 6 ("torb build --explain-copies"). It is a flag and not a warning: a copy is the semantics working, not a mistake.Source
Decisions (refined)
Seed impact: none, one commit, implementable now.
tools/bootstrap.shbuilds the compiler withbuild ./compiler --output ...only, so the compiler's own build does not use the new flag (CLAUDE.md "Seed and breaking changes": only a flag the build uses needs the two-commit dance). The change must use no syntax or native the published seed lacks. Do not touchseed/.Flag:
--explain-copiesontorb build, boolean, no value; parsed inbuildOptionsOf(compiler/src/main.trb, next to--timings), carried asBuildOptions.explainCopies: Bool = false(compiler/src/cli/build.trb), listed in the usage text (compiler/src/cli/usage.trb).torb run/test/checkdo not accept it (existing unknown-flag error).Which pass: the report is produced by a new
compiler/src/ir/explain-copies.trb, run incli/build.trbright afterinsertOwnership(where--timingsnotes "ownership"), only when the flag is set. With the flag off nothing runs and the emitted C is byte-identical (the bootstrap fixpoint must still hold).What counts as a copy: a
MakeUnique(reference)the ownership pass inserted (uniqueOwnersOf,ir/ownership.trb) whose owner is provably shared at that point: the base slot (or the prefix being made unique) has a retained alias (Retain/Copytarget) that liveness (ir/liveness.trb) still holds live after the write. That is PERFORMANCE.md's "aMakeUniqueon a reference whose base is live afterwards". AMakeUniquethat may copy only depending on runtime counts is not reported (no false positives; the report says "the compiler can see", not "all"). Shared-storage owners (boxes,lazy) are already skipped byuniqueOwnersOf.Spans:
Instruction.MakeUniquehas no location today (onlyBlock.at,Call.at,Element.atdo). Addat: LocationId? = NonetoMakeUnique(a defaulted case field likeCall.at), set it whereir/lower/place.trbforms the path and inuniqueOwnersOffrom the guarded instruction's location, falling back toBlock.at. The IR text format (ir/print.trb) does not print it, so no existing IR snapshot changes. Locations are workspace-relative (Location), so no machine path leaks.Scope: only copies whose location is in the built project's own sources;
std/and package dependencies are excluded.Output: standard error (like
--timings), stdout and exit code unchanged (always 0). One note per distinct (path, line, column, reason), sorted by path, line, column - monomorphized instances of one generic body are reported once. Format, per PERFORMANCE.md section 6, without the second hint line (see follow-up):followed by one summary line,
explain-copies: N copies at M places(0 copies at 0 placeswhen none). The reason line names the holder slot by its source name when it has one.Works with
--emit-cand--timings; it is printed before the C compiler step, so it needs no C compiler.Follow-up (out of scope here): the "how to avoid it" hint line is #302.
Acceptance criteria
torb build --explain-copiesis accepted bytorb buildonly, appears intorb build --help/usage, andBuildOptions.explainCopiesdefaults to false (parse test in the style ofcompiler/tests/deprecation.test.trblines ~545-552 ordriver.test.trb).MakeUniquecarries an optionalat; the IR text of all existing snapshots is unchanged (compiler/tests/ownership.test.trb,devirtualize.test.trbstay green unmodified).compiler/tests/explain-copies.test.trb(usingownedIrOffromlower-harness.trb) pins the report text for: (a) therows[row][column] = ...program of PERFORMANCE.md section 6 whilerows[row]is still held: exactly one note at the right line:column with the reason; (b) the same write when the row is not held elsewhere: no note; (c) avararray/list written after aletalias that is dead: no note; (d) two instances of one generic body: one note.tests/command-line/(or the existing harness there) pins stderr for one program with a copy and one without.std/are not reported.torb build --emit-coutput is byte-identical to before the change oncompiler/(program.cdiff empty) and the bootstrap fixpoint holds.docs/tooling/torb-build.mddocuments the flag (synopsis line, a### \--explain-copies`section with the sample output, in the style of### `--timings`), and PERFORMANCE.md section 6 /docs/ROADMAP.md` line 131 mark it built.seed/and no seed refresh needed.Dependencies
None. (#302, the hint line, depends on this.)
Windowandwindows(CONCURRENCY slice F, gap 6) #4[loop:torbscript] intake: in scope (author orion, label loop), source PERFORMANCE.md section 6, not a duplicate, no collision with a design record. New driver flag (
torb build), so check in refine whether the build uses it (seed impact); sonnet/medium unless the compiler needs a copy trace. next: refine, waiting (ready buffer full: #4, #163, #164, #223 are ready) until 2026-10-10T04:00:00Z[loop:torbscript] claim refine by session:loop-torbscript-20261010 until 2026-10-10T04:06Z
--explain-copieshint line for nested writes (take out, put back) #302[loop:torbscript] refine: body rewritten with decisions and testable criteria; no seed impact (bootstrap does not use the flag, one commit),
MakeUniqueneeds an optionalat, report from a new ir/explain-copies.trb after insertOwnership; hint line split off as #302, next: ready for implement[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T08:08Z
[loop:torbscript] claim implement by session:loop-torbscript-20261010 until 2026-10-10T14:02Z (re-claim: the previous worker died in the gateway gap between 02:10Z and 08:00Z without a write-back)
[loop:torbscript] implement: PR #303 opened (head
a26c683e1a, argus requested, CI pending); the worker ended before its write-back, posted by the loop session; est. tokens unknown, next: waiting (review by argus)--explain-copieshint line for nested writes (take out, put back) #302