oxc-project / oxc-project/backlog
AST: Represent for-in/of Declaration Heads with a Single Declarator
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 7
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Summary
Replace the general VariableDeclaration used in for-in and for-of left-hand sides with a declaration-head node that contains exactly one VariableDeclarator.
The grammar permits one binding in these loop heads. A vector is appropriate for ordinary variable statements and classic for initializers, but it makes zero or multiple declarators representable in for-in/for-of.
Motivation
Valid loop declaration heads contain one declarator:
for (const key in object) {}
for (let value of iterable) {}
for await (const value of asyncIterable) {}
for (const [key, value] of entries) {}
The current ForStatementLeft::VariableDeclaration reuses:
pub declarations: Vec<'a, VariableDeclarator<'a>>
It can represent invalid states such as:
declarations.is_empty();- two or more declarators in one
for-in/for-ofhead; - consumers indexing
declarations[0]based on a parser-maintained convention.
The single binding may itself be a destructuring pattern, so cardinality cannot be inferred by counting identifiers. It should be encoded at the declarator level.
Initializer legality is related but distinct. JavaScript's legacy var grammar, TypeScript recovery, and early errors may require preserving an initializer on the single declarator. This issue should enforce cardinality without prematurely encoding every contextual initializer rule.
Current AST Shape
pub struct ForInStatement<'a> {
pub left: ForStatementLeft<'a>,
pub right: Expression<'a>,
pub body: Statement<'a>,
// ...
}
pub struct ForOfStatement<'a> {
pub r#await: bool,
pub left: ForStatementLeft<'a>,
pub right: Expression<'a>,
pub body: Statement<'a>,
// ...
}
pub enum ForStatementLeft<'a> {
VariableDeclaration(Box<'a, VariableDeclaration<'a>>) = 16,
INHERIT(AssignmentTarget<'a>),
}
pub struct VariableDeclaration<'a> {
pub kind: VariableDeclarationKind,
pub declarations: Vec<'a, VariableDeclarator<'a>>,
pub declare: bool,
// ...
}
declare and a general declaration list are not meaningful properties of a loop declaration head.
Proposed AST Shape
pub enum ForStatementLeft<'a> {
VariableDeclaration(Box<'a, ForStatementDeclaration<'a>>) = 16,
INHERIT(AssignmentTarget<'a>),
}
pub struct ForStatementDeclaration<'a> {
pub node_id: Cell<NodeId>,
pub span: Span,
pub kind: VariableDeclarationKind,
pub declaration: VariableDeclarator<'a>,
}
The singular declaration retains the existing binding pattern, optional TypeScript annotation, and optional initializer while parser/semantic checks decide which combinations are permitted for for-in, for-of, for await, var, let, and const.
Syntax Mapping
| Source form | Current representation | Proposed representation |
|---|---|---|
for (const x of xs) {} |
General declaration with one-element vector | ForStatementDeclaration { kind: Const, declaration: x } |
for (let k in obj) {} |
General declaration with one-element vector | ForStatementDeclaration { kind: Let, declaration: k } |
for (const [k, v] of entries) {} |
One vector item containing a pattern | One singular declarator containing the same pattern |
for (x of xs) {} |
Inherited assignment target | Unchanged assignment-target variant |
| Zero or multiple declaration items | Constructible through builders/mutation | Not representable |
Guaranteed Invariants
- Every declaration-form
for-in/for-ofhead contains exactly one declarator. - Destructuring remains a single declarator regardless of bound-name count.
- Loop declaration heads cannot carry a declaration-list-only
declareflag. - ESTree compatibility is preserved with a synthesized one-element array.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating ForStatementLeft, VariableDeclaration, and the parser and consumer entry points that construct or inspect declaration-form for-in/for-of heads. Trace how destructuring, TypeScript annotations, initializers, and ESTree compatibility are handled; the work is done when these heads enforce one declarator without exposing declaration-list-only state.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100