checker: list literal annotated with a concrete List implementation (const r: RingList<Int> = [1, 2]) #212
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?
Finding
Found by the loop worker for #197 (PR #201): a list literal whose annotation is a concrete
Listimplementation other than the default (RingList<Int>, likewiseArrayList-style types) is refused by lowering. The worker tried a checker change but it broke the existingArrayListliteral test, so it was reverted; the conformance program usesRingList.from([...]).Goal
Decide and implement how list literals adopt a concrete
Listimplementation from the annotation (or document that they do not, with a clear diagnostic).Next
Refine: check the design records (COLLECTIONS.md, literal typing), reproduce on main, write acceptance criteria. Seed impact unknown until refined.
[loop:torbscript] intake: in scope (finding from the loop worker of PR #201, author orion, label
loop), no duplicate among the open issues, no collision with a design record seen at triage; a checker/lowering question on list literals, seed impact unknown until refined, next: refine (queued behind the ready buffer, waiting until the buffer drops below 4readyissues)[loop:torbscript] refine: held back, the ready buffer is above its target of 4
readyissues, next: waiting (ready buffer full)RingList,ConsStack,BankersQueue,Heap(C7) #139[loop:torbscript] refine: held back, the ready buffer is at its target (#230, #264, #252, #251, #164 are
ready). next: waiting (ready buffer full) until 2026-10-10T04:00:00Z==on two concrete stack values fails to compile #209[loop:torbscript] claim refine by session:loop-torbscript-20261012 until 2026-10-12T18:02Z
[loop:torbscript] decided by the loop: a list (and map) literal against a concrete implementation is built through
From<Iterate<Item>>, except for the one implementation the lowering builds itself.Reproduced by reading main (
d679af0e), no code run (bootstrap is CI-only).listLiteralType(compiler/src/semantics/checker/expression.trb) asksitemOfCollectionfirst. A concrete type that implementsList(RingList<Int>,TrieList<Int>) answers it, so the literal takesdefaultListTypeand is recordedCollectionLiteral.Defaultwith the annotation as its type.lowerListLiteralthen always fills anArrayListand coerces it to the annotation's bounds, which cannot be aRingList, so lowering refuses.Defaultis only correct forArrayList, which is whycompiler/tests/collections.test.trb("a concrete implementation of the literal's own trait is built directly instead") passes and why the earlier attempt, which routed every concrete type throughFrom, turned that test red (ArrayListisFrom<Iterate<Item>>too). The map literal has the same gap forHashMap(mapLiteralTypefindsKey/ValuethroughMap, sobuiltMapTypeis never reached; its doc comment already promises theHashMapcase).Design.
docs/design/COLLECTIONS.md3.5 keeps a literal's static type at the trait and asks nothing else;docs/TYPECHECKER.md("A list literal has three shapes") says a concrete implementation isDefault"because building the type that is asked for directly is the fast path". That reasoning holds only for the implementation the lowering builds, so the rule is narrowed, not reversed:ArrayList<Item>(lists) orTrieMap<K, V>(maps): unchanged,Default;List/Map:FromIteratethrough itsFrom<Iterate<Item>>(RingList.from([...])), same asConsStack,ArrayQueue,Setalready do;List/Mapbut is notFrom<Iterate<...>>: the existingreportWrongTargetdiagnostic ("A list literal cannot become aX:Xis notFrom<Iterate<Item>>") instead of a lowering refusal.Alternative rejected: making lowering build the target's own storage directly. It needs a per-type construction protocol that
Fromalready is, and COLLECTIONS 3.5 says noCollectable.Seed impact: none. No syntax, native, driver flag or new string-looked-up std name:
ArrayList/TrieMapare resolved by name inir/lower/collection.trbalready and the checker reads them fromchecker.wellKnown.names.compiler/andstd/contain no literal against a non-default concreteList/Mapimplementation (grep forRingList|TrieList|HashMap|TrieMap<...> = [hits only docs), so the seed compiles the new code unchanged. One PR, no two-commit rule.Acceptance criteria
const r: RingList<Int> = [1, 2],var r: RingList<Int> = [],const t: TrieList<Int> = [1, 2]andconst m: HashMap<String, Int> = ["a": 1]check clean and compile:compiler/tests/collections.test.trbassertscollectionOfisfrom RingList of Int64 through RingList: From<Iterate<Int64>>(etc.) and the literal'stypeOfis the annotation.ArrayList<Int> = [1, 2]andTrieMapmap literals staydefault; the existing tests are unchanged and green; trait-typed literals (List<Int>,Iterate<Int>,Show) unchanged.Item(const r: RingList<String> = ["a", 2]reports at the item), and aList/Mapimplementation that is notFrom<Iterate<...>>gets the "cannot become" diagnostic (test with a small user type).tests/conformance/ring-list.trbusesconst literal: RingList<String> = ["a", "b"]instead ofRingList.from([...])with the same.expected;tests/conformance/literal-through-from.trbgains aHashMapliteral (expected updated).docs/TYPECHECKER.md(the three-shapes bullet), theCollectionLiteral.Defaultcomment incompiler/src/semantics/checker/context.trb,docs/design/COLLECTIONS.mdC7 (drop "Known gap" -> done, link the PR) and thedocs/ROADMAP.mdcollections row (drop the "open" part);skills/regenerated.sh tools/gates.sh agreen in forge CI; Conventional Commitsfix(checker): ...and, if split,docs(...);tools/check-commits.shclean.Where:
listLiteralType/mapLiteralType(+ a smallisDefaultImplementationhelper). Size: ~40 lines of checker, tests and docs; one PR. Worker: opus/high (compiler/src).[loop:torbscript] refine: ready (decision, acceptance criteria, design/TYPECHECKER point and seed impact "none" recorded above; size one PR), next: implement. Tokens used: ~75k (sonnet).
[loop:torbscript] intake: picked up for implementation (ready, oldest ready item).
[loop:torbscript] claim implement by session:loop-torbscript-20261012 until 2026-10-12T22:22Z
[loop:torbscript] implement: PR #345 is open and forge CI is green (gates, tier A and B); the worker ended on a usage limit after pushing. Review by the merge gate is requested. next: waiting (merge gate review of PR #345)
[loop:torbscript] PR #345 merged by argus on 2026-10-12T23:01Z after an approved review of
66ab611(CI green incl. gates, tier A/B). The PR has no After-merge steps (no release or deploy, seed impact none); the issue was closed by the merge. Nothing left to do.