Skip to content

Parser: total rejected as a variable name in let-binding / assignment-target position #682

Description

@hyperpolymath

Repro (canonical, no face involved)

fn f() -> Int { let mut total = 0; total = total + 1; total }
parse error: Syntax error   (at `total` in the `let` binding)

Rename totalsum/acc and it compiles + runs fine.

Cause

total is lexed as the keyword TOTAL (lib/lexer.ml:39), the totality modifier for total fn (lib/parser.mly:249). The grammar already recovers TOTAL as an ordinary identifier in expression position (lib/parser.mly:1359| TOTAL { mk_ident "total" … }, added for hand-ports like HealthIndex.total). But that recovery does not cover:

  • let/let mut binding-name position, and
  • assignment-target (LHS) position.

total is the only soft-keyword in the table (lib/lexer.ml:13-40) that reads like a common variable name, so this bites real code — especially face-authored code (a Python-shaped mod naturally writes total). The other keywords (while, let, …) nobody names a variable.

Fix direction

Extend the TOTAL-as-ident recovery to the let-pattern and assignment-target nonterminals (mirroring parser.mly:1359). Per ADR-012 the change must be conflict-neutral — verify just build-loud / dune build show no new S/R or R/R conflicts (the comment at parser.mly:1350 argues TOTAL is safe because as a decl-modifier it always precedes FN; the same reasoning should extend to binding/assignment positions, but confirm against the conflict count).

Discovered

2026-07-07, while proving a Python-face program end-to-end to wasm (the faces path surfaces exactly this class of real-world naming friction).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions