Skip to content

return in a generator finishes it - #428

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-generator-return
Oct 1, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
fix-generator-return

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

return in a function* was not rewritten by the generator transform:

function* g() { yield "a"; return "end"; }
const r = g().next(); r.value;          // error: Can't resolve property 'value' of type string | {value:string, done:boolean}

function* h(n: number) { yield 1; if (n > 0) return; yield 2; }
for (const v of h(1)) print(v);         // 1, 2, 2, 2, ... forever

The body is pasted into the generated next(), where yield e sets the resume step and returns {value: e, done: false}. A user return stayed a plain return, so it returned the bare value, and it didn't advance the step, so every later next() resumed at the last yield.

Change

  • buildGeneratorWrapperDeclaration flags the body's own return statements with InternalFlags::GeneratorReturn (new bit). FilterVisitorSkipFuncsAST leaves the returns of nested functions, arrows and classes alone.
  • mlirGen(ReturnStatement) turns a flagged return e into step = -1; return {value: e, done: true}; a bare return gives value: undefined.
  • next() starts with if (this.step < 0) return {value: undefined, done: true}, so every call after a return is done. It's a sentinel rather than a final state label because labels are numbered in program order, so a final label's number isn't known yet at an earlier return.

Not changed (exists on main)

The finished value is wrong even without a user return: function* g() { yield "a"; }, and after the last next(), r.value === undefined is false. It reads as the text "undefined" for a string generator and 0 for a number one (warning using casting to undefined value). This is return-type inference dropping undefined from next()'s value type. The new test asserts done and real values only.

Tests

  • New 00generator_return.ts (compile + jit): value + done on return, done after it, for...of stopping, an early bare return, a return inside a loop, a nested arrow's return, and a method generator.
  • Release suite: 3341/3341 passed.
  • DefaultLib (main b67a213) rebuilt release/gc with this compiler: 158/158 compile, 158/158 jit.
  • The new test passes under gc, rc and none.
  • Not run: Debug, x86, -mm=own.

🤖 Generated with Claude Code

@ASDAlexander77
ASDAlexander77 merged commit e04d3d7 into main Oct 1, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-generator-return branch October 1, 2026 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant