Skip to content

Allow 'for' as an identifier outside for-block position #1432

@milkyskies

Description

@milkyskies

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions