Skip to content

QIR Generation panics when conditional branches use early return #2290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
swernli opened this issue Apr 11, 2025 · 0 comments · Fixed by #2388
Closed

QIR Generation panics when conditional branches use early return #2290

swernli opened this issue Apr 11, 2025 · 0 comments · Fixed by #2388
Assignees
Labels
bug Something isn't working high-priority

Comments

@swernli
Copy link
Collaborator

swernli commented Apr 11, 2025

The following code causes a panic in QIR generation:

function Branch(value : Bool) : Int {
    if (value) {
        return 3;
    } else {
        return 4;
    }
}
@EntryPoint()
operation Main() : Int {
    use qubits = Qubit[2];
    H(qubits[0]);
    CNOT(qubits[0], qubits[1]);
    let result = Branch(MResetZ(qubits[0]) == Zero);
    result
}

However, the same code with implicit returns in the function works as expected:

function Branch(value : Bool) : Int {
    if (value) {
        3
    } else {
        4
    }
}
@EntryPoint()
operation Main() : Int {
    use qubits = Qubit[2];
    H(qubits[0]);
    CNOT(qubits[0], qubits[1]);
    let result = Branch(MResetZ(qubits[0]) == Zero);
    result
}

This appears to be because of how the BranchControlFlow::Return is used to short circuit the handling of the rest of the block:

if body_control.is_return() {
return Ok(BranchControlFlow::Return(body_control.into_value()));
}

This causes the generated RIR program to be missing branch and jump terminator instructions at the end of blocks. The empty block (should have one terminating jump) is what triggers the specific panic, but other non-empty blocks also are missing terminators that mean the program is invalid.

Either the early return should be fully handled by refactoring the control flow handling for dynamic branches (which must correctly handling inlining for functions like the example above) or the RuntimeFeatureFlags::ReturnWithinDynamicScope should be updated to require more than just TargetCapabilityFlags::Adaptive so that RCA rejects this pattern at compile time.

@swernli swernli added bug Something isn't working needs triage labels Apr 11, 2025
swernli added a commit that referenced this issue May 8, 2025
This change avoids the panic in early returns by blocking them in RCA and providing the user with compile-time feedback before failing during QIR generation. It also includes updates to partial evaluation to ensure that the panicking case is now treated as a unimplemented graceful failure, since we don't have proper support for it.

Since QIR generation for programs with early return have never properly been handled, this doesn't take any functionality away but rather ensures earlier indication of the unsupported patterns at compile time. I filed #2387 to cover the additional work needed to fully support dynamic explicit returns.

Fixes #2290
github-merge-queue bot pushed a commit that referenced this issue May 13, 2025
#2388)

This change avoids the panic in early returns by blocking them in RCA
and providing the user with compile-time feedback before failing during
QIR generation. It also includes updates to partial evaluation to ensure
that the panicking case is now treated as a unimplemented graceful
failure, since we don't have proper support for it.

Since QIR generation for programs with early return have never properly
been handled, this doesn't take any functionality away but rather
ensures earlier indication of the unsupported patterns at compile time.
I filed #2387 to cover the additional work needed to fully support
dynamic explicit returns.

Fixes #2290
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working high-priority
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants