Skip to content

break / continue in a for await body, and nested for await, crash the compiler #502

Closed

Description

@ASDAlexander77

break or continue in the body of a for await loop, and a for await nested in another, crash the compiler (0xC0000005, no message), under every memory model.

let log = "";
async function* numbers() { yield 1; yield 2; yield 3; yield 4; }
async function* letters() { yield "a"; yield "b"; }
async function main() {
    for await (const x of numbers()) {
        if (x == 3) break;          // or: if (x == 2) continue;
        log += x;
    }
    print(log);
}
async function main() {
    for await (const x of numbers()) {
        for await (const y of letters()) {
            log += x + y;
        }
    }
    print(log);
}

Expected: 12 (break), 134 (continue), and 1a1b2a2b3a3b4a4b (nested).

Same on main a2a3258, and with #498's fix (PR for #498): an await in the body works, break, continue and the nested loop do not.

Where

  • break / continue: --emit=mlir succeeds, and the crash is in lowering (--emit=mlir-affine crashes). The body of a for await is generated inside an async.execute region (MLIRGenImpl::mlirGen(ForStatement), MLIRGenStatements.cpp), and the ts.Break / ts.Continue is inside that region, so the loop it refers to is outside it:

    %token = async.execute {
        ...
        "ts.Break"() <{label = ""}> : () -> ()
    

    A branch cannot leave the region, and the lowering that looks for the enclosing loop finds none.

  • Nested for await: --emit=mlir itself crashes, during MLIR generation.

Possible fix

The body is an async.execute only so that an await in it has an async region. One option is to generate the body directly in the loop (like a plain for...of in an async function, where await already works), dropping the extra region. Then break and continue reach the loop, and nesting needs nothing special. Failing that, report break / continue in a for await body as an error rather than crashing.

Found while fixing #498.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions