Keep only the written fields of a record literal in the typed tree
Why
A record literal stored one entry per field of its type: Kept for a field copied from a spread, and a synthesized None expression for every optional field it left out. JSX DOM props have 612 optional fields, so each DOM element added about 610 expressions to the typed tree, ~31 KB to the .cmt, and as many Lambda constants (#9148). With 800 elements, compiling took 0.80 s and 422 MB; now 0.08 s and 50 MB, and the .cmt shrinks from 25 MB to 0.8 MB. Small records lose a third of their .cmt size. The generated JavaScript does not change.
modifiedTypedtree record literals
type r = {a: int, b?: string}let x = {a: 1}
typed
modifiedAnalysis find references
type labelled = {name: string, label?: string}let withLabel = {name: "a", label: "b"}let withoutLabel = {name: "c"}let _ = withLabel.label
text
labellabelReview
- Where do the left-out fields come from now? Translcore rebuilds the positional view from lbl_all: a field missing from
fieldsis read from the spread record when there is one, and isundefinedotherwise. - What else went? The record_label_definition type, the unused type of Kept fields, and the tuple's optional flag, which was always false.