Bug
The checkMissingReturns pass (in src/semantic/safety-checks.ts, invoked from src/codegen/llvm-generator.ts:3033 during codegen prep) false-positives on the transformExpression function in src/parser-native/transformer.ts (or src/parser-ts/handlers/expressions.ts — same name) when chad-native.ts contains 8 or more registerStdlib() calls.
Both transformExpression definitions return on all paths (switch with default case that returns a value or throws). The check incorrectly flags them only past a threshold of registered stdlib modules.
Repro
From a fresh checkout of origin/main (SHA 0f8e9a26 at time of filing):
-
Add one more registerStdlib(...) call to src/chad-native.ts, anywhere after the existing 7:
registerStdlib("anything.ts", ChadScript.embedFile("../lib/colors.ts"));
The 8th can reference any existing lib content — content doesn't matter, count does.
-
Build stage 0: npm run build && node dist/chad-node.js build src/chad-native.ts -o /tmp/chad-stage0
-
Run it on itself: /tmp/chad-stage0 build src/chad-native.ts -o /tmp/stage1
Result:
Semantic analysis passed
Generating LLVM IR...
error: function 'transformExpression' does not return a value on all code paths
= help: add a return statement to all branches
Reducing back to 7 registerStdlib calls → compile succeeds. Content of the embedded file is irrelevant; so is the path, key name, and position.
Bisect
Introduced in #583.
Impact
Blocks any PR that adds an 8th stdlib module. Currently blocking #585 (net module — registerStdlib("net.ts", ...) was the 8th). The existing 7-stdlib main branch works fine, so the regression didn't surface until someone tried to add a new stdlib.
Likely cause (speculation)
#583 changed how resolveExpressionType results are cached via the typeOf() annotator. The regression is probably a hash/ordering dependency that kicks in past a certain AST size — most likely the switch-case analysis in mrAllReturn reads stale cached type info for case consequents when the top-level function count crosses a threshold.
Workaround
Keep registerStdlib calls ≤ 7 until fixed. (Not a real workaround for anyone shipping a new stdlib module.)
Bug
The
checkMissingReturnspass (insrc/semantic/safety-checks.ts, invoked fromsrc/codegen/llvm-generator.ts:3033during codegen prep) false-positives on thetransformExpressionfunction insrc/parser-native/transformer.ts(orsrc/parser-ts/handlers/expressions.ts— same name) whenchad-native.tscontains 8 or moreregisterStdlib()calls.Both
transformExpressiondefinitions return on all paths (switch with default case that returns a value or throws). The check incorrectly flags them only past a threshold of registered stdlib modules.Repro
From a fresh checkout of
origin/main(SHA0f8e9a26at time of filing):Add one more
registerStdlib(...)call tosrc/chad-native.ts, anywhere after the existing 7:The 8th can reference any existing lib content — content doesn't matter, count does.
Build stage 0:
npm run build && node dist/chad-node.js build src/chad-native.ts -o /tmp/chad-stage0Run it on itself:
/tmp/chad-stage0 build src/chad-native.ts -o /tmp/stage1Result:
Reducing back to 7
registerStdlibcalls → compile succeeds. Content of the embedded file is irrelevant; so is the path, key name, and position.Bisect
b1c00c87(pre-typeOf-migration) — 8 calls compiles fineb52c6449(refactor(codegen): migrate 4 llvm-generator resolveExpressionType sites to typeOf() #583 first typeOf migration) — 8 calls fails82108faa(refactor(codegen): migrate map-allocator to typeOf() #584 map-allocator migration) — fails (inherits)0f8e9a26(refactor(codegen): drop redundant resolveExpressionType fallback in variable-allocator #592 variable-allocator cleanup) — fails (inherits)Introduced in #583.
Impact
Blocks any PR that adds an 8th stdlib module. Currently blocking #585 (net module —
registerStdlib("net.ts", ...)was the 8th). The existing 7-stdlib main branch works fine, so the regression didn't surface until someone tried to add a new stdlib.Likely cause (speculation)
#583 changed how
resolveExpressionTyperesults are cached via thetypeOf()annotator. The regression is probably a hash/ordering dependency that kicks in past a certain AST size — most likely the switch-case analysis inmrAllReturnreads stale cached type info for case consequents when the top-level function count crosses a threshold.Workaround
Keep
registerStdlibcalls ≤ 7 until fixed. (Not a real workaround for anyone shipping a new stdlib module.)