Skip to content

Type checker: nested generator function declaration infers yield type as 'void' (ignores its yield expressions) #532

@nickna

Description

@nickna

Summary

A generator function declaration nested inside another function has its yield type inferred as void, ignoring the yield expressions in its body. The same generator at the top level infers correctly.

Repro

function outer() {
  function* g() { yield 42; }
  return [...g()];
}
console.log(outer());
  • Interpreter: prints [42] — runtime is unaffected (it ignores the inferred type).
  • Compiled: Error: The type 'System.Void' may not be used as a type argument. — the inferred Generator<void> becomes an invalid IEnumerator<System.Void> in IL.

Annotating the return type works around the inference but then hits the separate compiled-lowering bug #501:

function* g(): Generator<number> { yield 42; }   // nested → "Compile Error: Yield not supported in this context" (#501)

Contrast — top level infers correctly

let y = 5;
function* g() { yield y; }     // inferred Generator<number>
console.log([...g()]);         // [5] in both modes

Notes

  • Type-checker bug, independent of compilation: the inferred type is wrong (Generator<void> vs Generator<number>). It also produces spurious assignability errors, e.g. Type 'Generator<void>' is not assignable to type 'Generator<number>' when annotated as the latter.
  • Found while fixing Type checker: generator function *expression* can't close over block-scoped (let/const) outer variables — 'Undefined variable' #522 (generator function-expression closures). The GeneratorArrowLifter lifts generator expressions to top-level declarations partly to stay on the working top-level inference path; this issue is one reason lifting them into a nested scope instead is not yet viable.
  • Likely the return-type refinement pass that runs for top-level function declarations is not applied to nested function declarations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions