Semantic Diff

#8905 Represent array and list literals with spreads with a Pexp_spread node

1 commit, rendered from its record.

Summary

RangeCommitsChangelogAreasJS output changesFormatsFailed checks
186944164e7f47fab38547e46612c136a3e399aa..pr-89051๐Ÿ’… Polish ๐Ÿ› Bug fix ๐Ÿ  Internalsyntaxprintertypecheckerlambdacodegenanalysisreanalyzetests0ast cmt0

Changelog draft

๐Ÿ› Bug fix
  • Fix the formatter dropping spreads of array and list literals, attributes on literals with spreads, and comments in list literals with spreads.
๐Ÿ’… Polish
  • Report a spread of the wrong collection type, such as a list spread into an array, as a mismatch of the spread instead of an array item.
๐Ÿ  Internal
  • Represent array and list literals with spreads with a dedicated parsetree node.

186944164e7f47fab38547e46612c136a3e399aa..pr-8905

aa5c53bae ยท Christoph Knittel ยท Oct 18, 2026

Represent array and list literals with spreads with a Pexp_spread node

๐Ÿ’… Polish๐Ÿ› Bug fix๐Ÿ  Internalsyntaxprintertypecheckerlambdacodegenanalysisreanalyzetests

The parser no longer turns [a, ...b] and list{...a, b} into calls of Primitive_array.spread and Primitive_list.spread marked with res.spread. Pexp_spread keeps the items and spreads in source order, and the type checker gives it a Texp_spread node. Translation emits new Parray_spread and Plist_spread primitives that compile to the same runtime calls. A list literal whose only spread is its tail stays a chain of ::.

Before ReScript
let x = [...[1, 2], 3, ...[]]let y = @attr list{...xs, ...list{}, 1}
After ReScript
let x = [...[1, 2], 3, ...[]]let y = @attr list{...xs, ...list{}, 1}

Source the old formatter printed [1, 2, 3, ] and list{...xs, , 1} without the attribute; the new one prints the input unchanged (tests/syntax_tests/data/printer/expr).

๐Ÿ’… PolishReport a spread of the wrong collection type, such as a list spread into an array, as a mismatch of the spread instead of an array item.
๐Ÿ› Bug fixFix the formatter dropping spreads of array and list literals, attributes on literals with spreads, and comments in list literals with spreads.
๐Ÿ  InternalRepresent array and list literals with spreads with a dedicated parsetree node.

Review

Output
unchangedtests/tests JS byte-identical after a rebuild; a combinatorial harness of all item/spread sequences up to length 4 compiles to identical JS with the old and new bsc
Formatting
changedspreads of array and list literals and attributes on literals with spreads are kept; comments in list spreads stay in place
Formats
astcmt
PPX
unchangedwire: the v0 encoding is the res.spread call it was, decoded back to Pexp_spread (ast-mapping fixture SpreadLiterals.res)
Editor
unchanged:pipe completion types the literal as the runtime call; SpreadLiterals.res covers AST dump, hints, highlighting and completion
Tests
syntax tests/syntax_tests/data/+ ast-mapping/SpreadLiterals.res~ printer/expr/array.res~ printer/expr/list.res~ printer/comments/array.res
analysis+ tests/analysis_tests/tests/src/SpreadLiterals.res
super_errors tests/build_tests/+ super_errors/fixtures/array_spread_type_mismatch.res+ super_errors/fixtures/list_spread_type_mismatch.res+ super_errors/fixtures/array_spread_annotation_mismatch.res
ounit tests/ounit_tests/~ ounit_ast_mapper0_tests.ml
61 files ยท +761 โˆ’294 ยท reanalyze 2 ยท analysis 5 ยท changelog 3 ยท lambda 2 ยท compiler 1 ยท typechecker 23 ยท syntax 5 ยท tests 20
Manalysis/reanalyze/src/arnold.ml+2โˆ’0
Manalysis/reanalyze/src/side_effects.ml+2โˆ’0
Manalysis/src/completion_front_end.ml+12โˆ’0
Manalysis/src/dump_ast.ml+17โˆ’0
Manalysis/src/hint.ml+4โˆ’3
Manalysis/src/semantic_tokens.ml+0โˆ’8
Manalysis/src/utils.ml+1โˆ’0
Achanges/spread-literal-errors.polish.md+1โˆ’0
Achanges/spread-literal-formatting.fix.md+1โˆ’0
Achanges/spread-literal-node.internal.md+1โˆ’0
Mcompiler/core/lam_analysis.ml+2โˆ’1
Mcompiler/core/lam_compile_primitive.ml+2โˆ’0
Mcompiler/ext/config.ml+3โˆ’3
Mcompiler/ml/ast_helper.ml+1โˆ’0
Mcompiler/ml/ast_helper.mli+2โˆ’0
Mcompiler/ml/ast_iterator.ml+5โˆ’0
Mcompiler/ml/ast_mapper.ml+7โˆ’0
Mcompiler/ml/ast_mapper_from0.ml+49โˆ’0
Mcompiler/ml/ast_mapper_to0.ml+6โˆ’0
Acompiler/ml/ast_spread.ml+95โˆ’0
Mcompiler/ml/depend.ml+5โˆ’0
Mcompiler/ml/lambda.ml+6โˆ’0
Mcompiler/ml/lambda.mli+4โˆ’0
Mcompiler/ml/parsetree.ml+11โˆ’0
Mcompiler/ml/pprintast.ml+11โˆ’0
Mcompiler/ml/printast.ml+14โˆ’0
Mcompiler/ml/printlambda.ml+2โˆ’0
Mcompiler/ml/printtyped.ml+6โˆ’0
Mcompiler/ml/rec_check.ml+6โˆ’4
Mcompiler/ml/tast_iterator.ml+1โˆ’0
Mcompiler/ml/tast_mapper.ml+2โˆ’0
Mcompiler/ml/translcore.ml+8โˆ’0
Mcompiler/ml/typecore.ml+29โˆ’0
Mcompiler/ml/typedtree.ml+3โˆ’0
Mcompiler/ml/typedtree.mli+3โˆ’0
Mcompiler/ml/typedtree_iter.ml+1โˆ’0
Mcompiler/syntax/src/res_comments_table.ml+9โˆ’24
Mcompiler/syntax/src/res_core.ml+29โˆ’95
Mcompiler/syntax/src/res_parsetree_viewer.ml+0โˆ’27
Mcompiler/syntax/src/res_parsetree_viewer.mli+0โˆ’7
Mcompiler/syntax/src/res_printer.ml+27โˆ’114
Atests/analysis_tests/tests/src/SpreadLiterals.res+20โˆ’0
Atests/analysis_tests/tests/src/expected/SpreadLiterals.res.txt+119โˆ’0
Atests/build_tests/super_errors/expected/array_spread_annotation_mismatch.res.expected+16โˆ’0
Atests/build_tests/super_errors/expected/array_spread_type_mismatch.res.expected+11โˆ’0
Atests/build_tests/super_errors/expected/list_spread_type_mismatch.res.expected+11โˆ’0
Atests/build_tests/super_errors/fixtures/array_spread_annotation_mismatch.res+4โˆ’0
Atests/build_tests/super_errors/fixtures/array_spread_type_mismatch.res+4โˆ’0
Atests/build_tests/super_errors/fixtures/list_spread_type_mismatch.res+4โˆ’0
Mtests/ounit_tests/ounit_ast_mapper0_tests.ml+95โˆ’0
Atests/syntax_tests/data/ast-mapping/SpreadLiterals.res+15โˆ’0
Atests/syntax_tests/data/ast-mapping/expected/SpreadLiterals.res.txt+15โˆ’0
Mtests/syntax_tests/data/parsing/grammar/expressions/expected/array.res.txt+5โˆ’5
Mtests/syntax_tests/data/parsing/grammar/expressions/expected/list.res.txt+1โˆ’1
Mtests/syntax_tests/data/parsing/recovery/expression/expected/list.res.txt+1โˆ’2
Mtests/syntax_tests/data/printer/comments/array.res+9โˆ’0
Mtests/syntax_tests/data/printer/comments/expected/array.res.txt+9โˆ’0
Mtests/syntax_tests/data/printer/expr/array.res+12โˆ’0
Mtests/syntax_tests/data/printer/expr/expected/array.res.txt+12โˆ’0
Mtests/syntax_tests/data/printer/expr/expected/list.res.txt+4โˆ’0
Mtests/syntax_tests/data/printer/expr/list.res+4โˆ’0
with Claude Opus 5.5