Problem
for is treated as a reserved keyword everywhere, but it should be a contextual keyword like type, opaque, trusted, etc. Users hit this when naming variables, fields, or parameters for (very common — e.g. for: "submit", htmlFor, waitFor, a function param named for).
A for block only ever appears at the item-statement position (for Type { ... }), so the parser can disambiguate the same way it does for type (type X = ... at item start vs. { type: "click" } in expressions).
Expected
These should all parse as identifier uses, not as for-blocks:
let for = 1 // local binding
type Form = { for: string } // record field
let fn(for: string) -> string = { for } // parameter
<label for="name" /> // JSX attribute (already works for some keywords)
obj.for // member access
Why
for collides with HTML/React (<label for>, htmlFor), with idiomatic English variable names, and with common API params (waitFor, searchFor). Forcing users to rename around it is hostile.
The contextual-keyword table in docs/llms.txt already lists type, opaque, trusted, deriving, mock, parse, collect, todo, unreachable, clear, unchanged. for belongs in the same row — keyword only at item start (for Type { ... } and import { for Type }), identifier elsewhere.
Tests
- Lexer/parser test:
let for = 1 parses as a binding
- Lexer/parser test:
type T = { for: string } parses as a record field
- Lexer/parser test:
let f(for: string) -> string = { for } parses as a parameter + ident reference
- Lexer/parser test:
<label for="name" /> parses as a JSX attribute named for
- Lexer/parser test: existing
for Type { ... } blocks still parse
- Lexer/parser test: existing
import { for Type } from "..." still parses
- Negative:
let for Type = ... (ambiguous misuse) emits a clear error
- Update
docs/llms.txt contextual-keywords table to add a for row
Problem
foris treated as a reserved keyword everywhere, but it should be a contextual keyword liketype,opaque,trusted, etc. Users hit this when naming variables, fields, or parametersfor(very common — e.g.for: "submit",htmlFor,waitFor, a function param namedfor).A
forblock only ever appears at the item-statement position (for Type { ... }), so the parser can disambiguate the same way it does fortype(type X = ...at item start vs.{ type: "click" }in expressions).Expected
These should all parse as identifier uses, not as for-blocks:
Why
forcollides with HTML/React (<label for>,htmlFor), with idiomatic English variable names, and with common API params (waitFor,searchFor). Forcing users to rename around it is hostile.The contextual-keyword table in
docs/llms.txtalready liststype,opaque,trusted,deriving,mock,parse,collect,todo,unreachable,clear,unchanged.forbelongs in the same row — keyword only at item start (for Type { ... }andimport { for Type }), identifier elsewhere.Tests
let for = 1parses as a bindingtype T = { for: string }parses as a record fieldlet f(for: string) -> string = { for }parses as a parameter + ident reference<label for="name" />parses as a JSX attribute namedforfor Type { ... }blocks still parseimport { for Type } from "..."still parseslet for Type = ...(ambiguous misuse) emits a clear errordocs/llms.txtcontextual-keywords table to add aforrow