[Panic] Ctl operation that calls an element of an operation-array parameter panics
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 55/100
Research direction
Start with the reported invariant failure in qsc_fir_transforms/src/invariants.rs:1926, then inspect the defunctionalization evaluation and index order changes from #3893. Use the Q# example and Python reproduction in the issue to compare indexed calls under Ctl and Adj controls. Done means the reproductions compile without panicking across the listed profiles while the control cases continue to compile.
Written by the indexing model from the issue text.
Description
operation W(q : Qubit, ops : (Qubit => Unit is Ctl)[]) : Unit is Ctl {
ops[0](q);
}
operation Main() : Result {
use q = Qubit();
W(q, [S]);
MResetZ(q)
}
- Failure: every profile, including Base, panics in
qsc_fir_transforms/src/invariants.rs:1926:
PostArgPromote/PostAll call invariant violation: Expr 67 passes Expr 66 with type Tuple([Array(Prim(Qubit)), Prim(Qubit)]) to callee Expr 65 expecting input type Prim(Qubit). The program never usesControlled, so the
panic probably comes from the generated controlled specialization ofW, which passes(ctls, q)to an array
element. - What triggers it:
is Ctloris Adj + Ctl, together with indexing (ops[i](q)). It compiles withis Adj
alone, withfor op in ops { op(q); }, or with a single operation parameter instead of an array. - Regression: a bisect over the commits between merge base
7c6a2b51and main gives6adfda105(#3891)
compiles it, and84d1ec2e4"Defunctionalization: evaluation and index order (#3893)" panics. Branches without
#3893 (f05438eb,ca2fe553) compile it correctly. - Related: #3966 (open) reports the same invariant violation when
Controlledis applied to a callable-array closure through the Python callable API. This is a much simpler
trigger in plain Q#, with no closure, noControlledcall, and no Python, so it's likely the same root cause. - Impact: this accounts for half of all panics in the run, including all 8 Base panics, and stops every program
with aWgate-array operation from compiling.
"""Panic: an `is Ctl` operation that calls an element of an operation-array parameter.
Every profile, including Base, panics in qsc_fir_transforms (invariants.rs) with
"PostArgPromote/PostAll call invariant violation ... passes ... Tuple([Array(Prim(Qubit)), Prim(Qubit)]) to callee
... expecting input type Prim(Qubit)". The program never uses `Controlled`, so the panic probably comes from the
generated controlled specialization of `W`. It's a regression: a bisect over upstream/main gives 6adfda105 (#3891) good,
84d1ec2e4 "Defunctionalization: evaluation and index order (#3893)" bad. Related: #3966 (the same invariant through the
Python callable API with a callable-array closure).
The controls show what the trigger needs: `is Ctl` (or `is Adj + Ctl`) and indexing into the array. They compile.
Requires only the `qdk` package. Exits 0 while the panic reproduces.
"""
import sys
from qdk import Context, TargetProfile
PROFILES = ("Base", "Adaptive_RI", "Adaptive_RIF", "Adaptive")
MAIN = """
operation Main() : Result {
use q = Qubit();
W(q, [S]);
MResetZ(q)
}
"""
def w(functors: str, body: str) -> str:
return f"operation W(q : Qubit, ops : (Qubit => Unit is {functors})[]) : Unit is {functors} {{ {body} }}"
PROGRAMS = {
"Ctl, indexed (bug)": w("Ctl", "ops[0](q);"),
"Adj + Ctl, indexed (bug)": w("Adj + Ctl", "ops[0](q);"),
"Adj only, indexed (control)": w("Adj", "ops[0](q);"),
"Ctl, for loop (control)": w("Ctl", "for op in ops { op(q); }"),
}
def compile_status(source: str, profile: str) -> str:
ctx = Context(target_profile=getattr(TargetProfile, profile))
try:
ctx.eval(source)
ctx.compile("Main()")
return "ok"
except BaseException as e: # pyo3's PanicException derives from BaseException
kind = "PANIC" if type(e).__name__ == "PanicException" else "error"
return f"{kind}: {' '.join(str(e).split())[:110]}"
reproduced = False
for label, w in PROGRAMS.items():
print(label)
for profile in PROFILES:
status = compile_status(w + MAIN, profile)
print(f" {profile:13s} {status}")
if "(bug)" in label and "PostArgPromote" in status:
reproduced = True
print("REPRODUCED" if reproduced else "NOT REPRODUCED")
sys.exit(0 if reproduced else 1)
- Dominant language
- Rust
- Stars
- 1k
- Forks
- 219
- Avg merge
- 4d 1h
- Merged PRs (30d)
- 88
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from microsoft/qdk
-
bug needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
[Samples] Investigate redundant CheckMay be free again @theARCania claimed this 41 days ago, and no pull request is open. Openenhancement good first issue low-priority
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
microsoft/qdk#1933 · 4 comments ·
Maintainers usually reply within 1 day
-
bug needs triage
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Maintainers usually reply within 1 day
-
RCA: `set () = { … }` drops its value's dynamic kind; code is lostPossibly taken @domorale claimed this today. Openbug needs triage
Difficulty 4/5 3-5 days Newbie friendliness 20/100
Maintainers usually reply within 1 day
-
FIR `tuple_decompose`: `{ set p = new P { … } }` (an assignment without a semicolon) panics with `LocalVarId consistency: … not bound`Possibly taken @domorale claimed this today. Openbug needs triage
Difficulty 4/5 3-5 days Newbie friendliness 35/100
Maintainers usually reply within 1 day
Similar issues
-
bug cli p3
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
Telegram and Twitch adapters panic when splitting long messages with multibyte charactersPossibly taken @RaphaelFakhri claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
spacedriveapp/spacebot#661 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
project-robius/robrix#1177 ·
Maintainers usually reply within 1 day