package manager: keep the modules of two majors apart in lowering and back ends #325
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
Slice 3 of 3 of #28. After #324 (PR #360, landed) a workspace holds two majors of one package as two
Packageentries and the checker keeps their modules and types apart (Workspace.dependencyOf,Workspace.labelOf). Lowering and the back ends still derive symbol and path names frompackage.name, so two majors would collide in the output. #324 therefore added a guard at the entry oflowerWorkspace(compiler/src/ir/lower/lower.trb,packageInTwoMajors) that refuses such a program withacme/json is in the program in two majors, which build and run cannot keep apart yet (#325). This issue removes the guard and makes the names major-aware.Design
docs/design/PROJECT.md section 6a, "Two majors in the checker, not yet in a binary".
Scope
Workspace.identityOf(package: Package): Stringnext tolabelOf:package.namewhere the workspace holds one package of that name,name@major(acme/json@2) where it holds several (major frompackage.manifest.version; an unparsable version falls back to the bare name, likelabelOf). Single-major workspaces get exactly today's strings.package.namegoes through it:ir/instantiate.trbsymbolPathOf(SymbolPath package.name ...), which feedsir/mangle.trband with it both back ends (they see mangled names only, no package lookups of their own);ir/lower/function.trbscriptNameOfandentryNameOf;ir/lower/lower.trbstablePathOf(the module paths of diagnostics,#line/TORB_LOCATION, the VM manifest and debugger);ir/lower/encoding.trbqualifiedNameOf;reference/model.trbpackageNameOf(torb docand the site must not merge the two majors into one package).path.package == "std/fs",std/number,startsWith("std/"),packageNamed("std/encoding")and friends).std/*keep one version, so these stay bare and the seed path does not change.packageInTwoMajorsand its call inlowerWorkspace, and the imports (LoweredProblem,Span,Diagnostic) if nothing else inlower.trbuses them.lowerScriptsandlowerLibrarynever had it; they must work on a two-major graph too through the same identity.torb addpage (docs/tooling/torb-add.md) gets one sentence that a graph may hold two majors andbuild/runkeep them apart; ROADMAP "package manager" bullet notes two majors built. Regenerateskills/only if a page that feeds it changed (docs skill --check).Acceptance criteria
majorsWorkspacefixture ofcompiler/tests/check.test.trb(move or share the helper): a program wherexandyboth definepublic fn describe(): Stringinacme/json1 and 2 and the app calls both lowers (isLoweredtrue, no problems) and the IR/mangled names of the two differ (t_acme_x2f_json_x40_1_...style: package componentacme/json@1/acme/json@2, escaped). A test asserts the emitted function, type layout and static names of both majors are present and distinct.... cannot keep apart yet (#325)) is replaced by the positive test above; the message is gone from the tree (grep '#325' compiler docsfinds nothing).bytecode.test.trbdoes) and C (functions andTORB_LOCATIONpaths of both, asemit-c.test.trbdoes); the module paths readacme/json@1/src/lib.trbandacme/json@2/src/lib.trb.coverage.test.trb/debugger.test.trbrun a program (fixture written to a temp directory with the locked cache):torb runequivalent prints a value from each major; if the harness cannot place a cache, the criterion is met by the bytecode and C tests above plus thetorb lock --checkof the same fixture.torb docmodel of the fixture holds two packages namedacme/json@1andacme/json@2.same C on every hoststay green (they compile the single-major compiler workspace).tools/check-commits.shclean; ROADMAP bullet for #28 marked built; #28 closes when this lands.Seed impact
None. Only compiler sources written in existing TorbScript change (no syntax, no native, no driver flag); the
std/*lookups by name stay bare, and a single-major workspace gets the same strings as before, so the seed's output does not move. State "seed impact: none" in the PR; if a golden file changes, that is a bug in the identity rule, not an expected diff.Dependencies
#324 (landed, PR #360). Size: one PR, one or two Conventional Commits:
feat(ir): keep modules of two majors apart(identity, name derivation, guard removal, tests) and, if the diff gets large,docs: two majors of one package build and run(docs only).[loop:torbscript] refine: slice 3 of 3 of #28, specified; next: waiting (dependency #324)
[loop:torbscript] claim refine by session:loop-torbscript-20261013 until 2026-10-13T12:36Z
[loop:torbscript] decided by the loop: scope of #325 after #324 (PR #360, read on
main3468a08). No owner question: this is the internal naming of symbols and paths in the toolchain; the language, the lock and the published contract do not change, and single-major output stays byte-identical. The issue body is rewritten; the points below are the decisions.packageInTwoMajorsand its call at the top oflowerWorkspace(ir/lower/lower.trb), with its test incheck.test.trb.lowerScriptsandlowerLibraryhave no guard and need no removal, only the same identity.Workspace.identityOf(package)next tolabelOf(design rule: a method, no free wrapper). Barenamefor a name held once,name@majorfor each of several.@cannot occur in a package name, so the mangled component (_x40_after escaping) cannot collide with any other package, and both majors get the suffix (not only the second), so a name does not depend on which major is listed first.name@majorand notlabelOf'sacme/json 2.x:labelOfis message text with a space; names and paths (#line,TORB_LOCATION, VM manifest,torb doc) want a token with no space.labelOfstays for messages.symbolPathOf(which only has the checker) and would make a name depend on what is built. The cost is that adding a second major to the lock renames the symbols of the first; nothing persists those names (the fixpoint compares builds of one workspace), so this is harmless. Single-major workspaces, including the compiler's own, are unchanged: seed impact none.main:ir/instantiate.trb symbolPathOf(feedsir/mangle.trband both back ends;backend/candbackend/bytecodehave no package lookup of their own),ir/lower/function.trb scriptNameOf/entryNameOf,ir/lower/lower.trb stablePathOf(viapathsOfModulesfor diagnostics, C#line, VM manifest),ir/lower/encoding.trb qualifiedNameOf,reference/model.trb packageNameOf(torb doc). Not changed on purpose: the by-name toolchain lookups ofstd/*(path.package == "std/fs",std/number,startsWith("std/"),packageNamed("std/encoding"));std/*keep one version.majorsWorkspacefixture, plus a VM run if the harness can place the cache; the VM and C back ends need no change of their own beyond the names. Docs andskills/as in the issue.[loop:torbscript] refine: read #324/PR #360 and
main, rewrote the scope and acceptance criteria (guardpackageInTwoMajorsinlowerWorkspaceto remove; newWorkspace.identityOf=nameorname@major, used byir/instantiatesymbolPathOf,scriptNameOf/entryNameOf,stablePathOf,qualifiedNameOf,torb doc;std/*lookups stay bare; back ends need only the names), decided the design points (see the decided-by-the-loop comment), one PR in one or two Conventional Commits, seed impact none, no owner question. Labelready. Tokens: ~95k, next: implement[loop:torbscript] claim implement by session:loop-torbscript-20261014 until 2026-10-14T04:02Z
[loop:torbscript] implement: PR #361 opened for #325 (
Workspace.identityOf, all name/path derivations routed through it, guard removed, newtwo-majors.test.trb, docs andskills/updated). CI green ond8e9b575(gates, bootstrap linux-x64, tier A/B, commit messages, pdisc; the other targets are skipped by the workflow). One red run on the first push (the VM-run test's program had no entry statement) was fixed on the same branch and squashed into the two commits. seed impact: none. Token usage: not reported by the runtime. next: review