Skip to content

Eliminate redundant round-trip casts in OpenQASM-to-Q# compilation#2990

Merged
minestarks merged 3 commits intomainfrom
minestarks/fix-bit-binop-result-cast
Mar 9, 2026
Merged

Eliminate redundant round-trip casts in OpenQASM-to-Q# compilation#2990
minestarks merged 3 commits intomainfrom
minestarks/fix-bit-binop-result-cast

Conversation

@minestarks
Copy link
Copy Markdown
Member

Fixes #2987

Bitwise operations on bit types (^, &, |) were generating redundant nested casts in the Q# output. The OpenQASM semantic lowerer inserts implicit Bit → UInt(1) and UInt(1) → Bit casts around the operands and result, which the compiler was faithfully translating into IntAsResult(ResultAsInt(...)) wrappers — a no-op round-trip.

Before:

// OpenQASM: bit c = a ^ b;
// Generated Q#:
mutable c = Std.OpenQASM.Convert.IntAsResult(
    Std.OpenQASM.Convert.ResultAsInt(
        Std.OpenQASM.Convert.IntAsResult(
            Std.OpenQASM.Convert.ResultAsInt(a) ^^^ Std.OpenQASM.Convert.ResultAsInt(b))));

After:

mutable c = Std.OpenQASM.Convert.IntAsResult(
    Std.OpenQASM.Convert.ResultAsInt(a) ^^^ Std.OpenQASM.Convert.ResultAsInt(b));

@minestarks minestarks marked this pull request as ready for review March 4, 2026 19:24
@minestarks minestarks requested a review from orpuente-MS March 4, 2026 19:26
Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 6, 2026

@minestarks I've opened a new pull request, #3004, to work on those changes. Once the pull request is ready, I'll request review from you.

The `Type` enum in `qsc_openqasm_compiler` carried a `bool` const
qualifier on most variants (e.g. `Int(bool)`, `Result(bool)`,
`BoolArray(ArrayDimensions, bool)`). Since Q# has no const bindings,
this flag was never meaningful in the Q# type representation and only
added noise — requiring a dedicated `without_const()` method just to
normalize types for equality comparisons.

## Changes

- **`types.rs`**: Strip the `bool` const parameter from all `Type`
variants; remove `without_const()`.
- **`compiler.rs`**:
- `semantic_type_for_qsharp_type`: no longer extracts or forwards
`is_const` into `Type` construction.
  - `make_qsharp_array_ty`: removes hardcoded `false` const args.
- `maps_to_same_qsharp_type`: simplifies to direct `==` comparison (the
note about ignoring const qualifiers is now moot).
- **`ast_builder.rs`**: `map_qsharp_type_to_ast_ty` updated to match new
variant shapes.

```rust
// Before
pub enum Type {
    Int(bool),
    Result(bool),
    ResultArray(ArrayDimensions, bool),
    // ...
}

// After
pub enum Type {
    Int,
    Result,
    ResultArray(ArrayDimensions),
    // ...
}
```

Constness is still read from the OpenQASM parser symbol
(`symbol.ty.is_const()`) where it matters — to decide Q# declaration
mutability (`let` vs `mutable`) — it just no longer flows into the
intermediate `Type` representation.

<!-- START COPILOT CODING AGENT TIPS -->
---

🔒 GitHub Advanced Security automatically protects Copilot coding agent
pull requests. You can protect all pull requests by enabling Advanced
Security for your repositories. [Learn more about Advanced
Security.](https://gh.io/cca-advanced-security)

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: minestarks <16928427+minestarks@users.noreply.github.com>
@minestarks minestarks added this pull request to the merge queue Mar 9, 2026
Merged via the queue into main with commit 75b09db Mar 9, 2026
12 checks passed
@minestarks minestarks deleted the minestarks/fix-bit-binop-result-cast branch March 9, 2026 18:02
github-merge-queue bot pushed a commit that referenced this pull request Mar 23, 2026
This is a bug we discovered while working on #2990 . It doesn't have any
user-visible effects (since constness is ignored when transpiling to
Q#), but it impacts the corectness of the internal OpenQASM AST.

`try_promote_bitarray_to_int` determines the result type when a binary
operation involves an `int`/`uint` and a `bit[N]`. It used `.clone()` on
whichever operand was already an integer type, which blindly inherited
that operand's const qualifier. This meant an expression like `const int
+ bit[4]` would produce `const int` instead of `int` — the non-const
`bit[4]` operand was ignored for constness.

Co-authored-by: Mine Starks <>
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.

OpenQASM: Binary operations between results prevent QIR generation

3 participants