Skip to content

Commit 4dea918

Browse files
fix(parser): remove duplicate [T] array-sugar production (#214)
`type_expr_primary` declared the array-shorthand production `LBRACKET type_expr RBRACKET -> TyApp("Array", ...)` twice (lines 443/469) — added independently by issues-drafts/02 and #40 with byte-identical semantic actions. The second copy was a verbatim duplicate of the first. Effects of the duplication, both confirmed via `menhir --explain`: - Menhir reported "1 production is never reduced" (the second copy is dead — the first always wins in the LALR automaton). - It generated a real reduce/reduce conflict family: state 80 (reached after `[ type_expr ]`) could not choose which identical production to reduce, and that ambiguity propagated through inherited lookaheads. Removing the dead copy and folding its substantive rationale (the `Array`-not-`List` desugar reason + typecheck.ml canonicalisation note + #40 ref) into the surviving comment so no documented knowledge is lost. Measured impact (full `dune test --force` gate green at 257/257 before and after — zero parse-behaviour change, this is a pure dedup): - "production never reduced" warning: eliminated. - reduce/reduce conflicts: 36 -> 10 (R/R conflict states 5 -> 4). - shift/reduce conflicts: unchanged at 75 (the duplicate was a reduce/reduce source only). The residual 75 S/R + 10 R/R conflicts are inherent LALR(1) ambiguities that Menhir resolves deterministically and correctly (the 257-test suite, incl. STAGE-A AOT + multi-module + STAGE-B effect-row coverage, proves the chosen resolution is the intended language). This Menhir (20260209) has no expected-conflict declaration mechanism, so eliminating the rest requires deliberate per-conflict grammar refactoring with estate-wide parse blast radius — tracked separately, not bundled here. Refs #40 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 22d7dbc commit 4dea918

1 file changed

Lines changed: 8 additions & 13 deletions

File tree

lib/parser.mly

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,14 @@ type_expr_primary:
437437
LT/GT tokens are shared with expression-position less-than. */
438438
| name = upper_ident LT args = separated_nonempty_list(COMMA, type_arg) GT
439439
{ TyApp (mk_ident name $startpos(name) $endpos(name), args) }
440-
/* Array sugar: [T] desugars to Array[T] (issues-drafts/02). The element
441-
type can be any type_expr (recursive), so [[Int]] means Array[Array[Int]]
442-
and [Result[T, E]] works as expected. */
440+
/* Array sugar: `[T]` desugars to `Array[T]` (issues-drafts/02; #40). The
441+
element type can be any type_expr (recursive), so `[[Int]]` means
442+
Array[Array[Int]] and `[Result[T, E]]` works as expected. This is the
443+
syntax stdlib has used all along (`fn map<T, U>(arr: [T], ...)`). The
444+
typechecker (lib/typecheck.ml ~724, 813, 1024) canonicalises array
445+
literals/operations on `TApp (TCon "Array", ...)`, so `Array` is the
446+
right desugar target — `List` here would trigger a
447+
`Unify.TypeMismatch (List, Array)` at check time. */
443448
| LBRACKET elem = type_expr RBRACKET
444449
{ TyApp (mk_ident "Array" $startpos $endpos, [TyArg elem]) }
445450
/* Function-type-as-type: `fn(A, B) -> C` lowers to the curried arrow
@@ -458,16 +463,6 @@ type_expr_primary:
458463
the interior in one pass without lookahead conflicts. */
459464
| LBRACE body = ty_record_body RBRACE
460465
{ TyRecord (fst body, snd body) }
461-
/* Array shorthand: `[T]` desugars to `Array[T]`. This is the syntax
462-
stdlib has used all along (`fn map<T, U>(arr: [T], f: T -> U) -> [U]`,
463-
`Result[[T], E]`, etc.) but it was previously only accepted in stdlib
464-
load paths, not in user source. The typechecker (lib/typecheck.ml
465-
lines 724, 813, 1024) canonicalises array literals/operations on
466-
`TApp (TCon "Array", ...)`, so `Array` is the right desugar target
467-
using `List` here triggers a `Unify.TypeMismatch (List, Array)` at
468-
check time. Closes #40. */
469-
| LBRACKET ty = type_expr RBRACKET
470-
{ TyApp (mk_ident "Array" $startpos $endpos, [TyArg ty]) }
471466
/* Built-in types */
472467
| NAT { TyCon (mk_ident "Nat" $startpos $endpos) }
473468
| INT_T { TyCon (mk_ident "Int" $startpos $endpos) }

0 commit comments

Comments
 (0)