🔎 Search Terms
compareNodes fileIndexMap, CompareTypes ordering, unindexed source file
Version & Regression Information
Code
internal/checker/utilities.go:
func (c *Checker) compareNodes(n1, n2 *ast.Node) int {
...
s1 := ast.GetSourceFileOfNode(n1)
s2 := ast.GetSourceFileOfNode(n2)
if s1 != s2 {
f1 := c.fileIndexMap[s1]
f2 := c.fileIndexMap[s2]
// Order by index of file in the containing program
return f1 - f2
}
...
}
fileIndexMap (createFileIndexMap in checker.go) is built only from the program's own file list. A source file that isn't a key — e.g. a synthetic file constructed by a custom host, or a content-mapper-produced supplemental file parsed outside the program — hits a plain map lookup, which returns Go's zero value for a missing key. That's indistinguishable from a real file that actually occupies index 0.
Actual behavior
- An unindexed file compares as equal to whichever real file occupies index 0.
- Two different unindexed files compare as equal to each other.
compareNodes/CompareTypes aren't purely cosmetic — they're used as a tiebreaker during real type inference (inference.go), so a wrong comparison here can affect more than display/declaration-emit order.
Expected behavior
A file missing from fileIndexMap should never be treated as if it were index 0. It should consistently sort relative to indexed files (e.g. always after them), and two different unindexed files should not collapse to "equal" — they should still get some deterministic order (e.g. by file name).
Fix
Opened #64217, which extracts the comparison into a small helper that uses the two-value map form to distinguish "index 0" from "not present," and adds a unit test constructing exactly this scenario (one indexed file, two independently-parsed never-indexed files).
🔎 Search Terms
compareNodes fileIndexMap, CompareTypes ordering, unindexed source file
Version & Regression Information
main(Go checker,internal/checker/utilities.go)--stableTypeOrderingdefects: compiler hang (NaN incompareNodes), missingBigIntLiteral, primitive alias bypass, and mapper omissions #64203, which bundles this together with a JS-checker-only hang (undefined - undefined→NaNin V8's sort) that doesn't reproduce in the Go checker, since Go's zero-valuedintcan't beNaN. This issue is specifically about the Go-side defect that remains: silently wrong ordering, not a hang.Code
internal/checker/utilities.go:fileIndexMap(createFileIndexMapinchecker.go) is built only from the program's own file list. A source file that isn't a key — e.g. a synthetic file constructed by a custom host, or a content-mapper-produced supplemental file parsed outside the program — hits a plain map lookup, which returns Go's zero value for a missing key. That's indistinguishable from a real file that actually occupies index 0.Actual behavior
compareNodes/CompareTypesaren't purely cosmetic — they're used as a tiebreaker during real type inference (inference.go), so a wrong comparison here can affect more than display/declaration-emit order.Expected behavior
A file missing from
fileIndexMapshould never be treated as if it were index 0. It should consistently sort relative to indexed files (e.g. always after them), and two different unindexed files should not collapse to "equal" — they should still get some deterministic order (e.g. by file name).Fix
Opened #64217, which extracts the comparison into a small helper that uses the two-value map form to distinguish "index 0" from "not present," and adds a unit test constructing exactly this scenario (one indexed file, two independently-parsed never-indexed files).