Angle-handling defects at four ingress points: silent CRz drop, deg-as-rad, malformed PHIR angles, backend-dependent ZLUP angle #691
Description
Summary
An ingress audit of controlled-rotation lowering turned up four smaller defects alongside the sheet-loss ones (#688, #689, #690). Grouping them because each is small and they share a theme: an ingress that silently drops, mis-scales, or backend-varies an angle rather than failing loudly.
1. Legacy HUGR to SLR silently drops CRz
python/quantum-pecos/src/pecos/circuit_converters/hugr_to_ast.py omits CRz/CRx/CRy from its gate map, and the scanner then continues past unrecognized quantum nodes without reporting. A program containing a controlled rotation converts to an SLR AST that is missing it, with no error.
Fix: reject unrecognized quantum operations rather than skipping them, or map the controlled rotations.
2. Pure-Python PHIR treats degree angles as radians
python/quantum-pecos/src/pecos/reps/pyphir/pyphir.py multiplies only the "pi" unit; "deg" values pass through unchanged and are then consumed as radians. Only affects HybridEngine(cinterp="python").
Fix: convert "deg" by pi/180, and fail loudly on any unit the converter does not handle rather than passing it through.
3. QuantumCircuit.to_phir_dict/json emits the wrong angle shape
qc2phir.py emits a flat list of angle values where PHIR expects [[values], unit]. Independently of the sheet issue in #689, the emitted PHIR is malformed for consumers that read the unit.
4. ZLUP bare-number CRZ means different angles per backend
For a bare numeric argument, the PHIR backend treats it as turns and multiplies by tau, the HUGR backend treats it as radians, and the QASM backend prints it unchanged (exp/zlup/src/codegen/{phir,hugr,qasm}.rs). The same source program produces three different rotations.
Fix: settle one interpretation for a bare number at the language level and make all three backends agree, or require an explicit unit and reject bare numbers. Experimental crate, so lower urgency, but it should not be left ambiguous.
Also undetermined, recorded for follow-up
The HUGR-to-DAG and HUGR-to-PHIR scanners do not resolve ControlModifier nodes. Whether a modified function is merely omitted or an unmodified body can leak through depends on graph shape. A nested ControlModifier<2, Rz> full-matrix fixture through each converter would settle it. Note the QIS/LLVM compiler path is safe here: the locked resolver halves in raw f64 half-turns without Angle64, and recursively halves controlled global phase.
Background: ~/Repos/pecos-docs/design/angle-representation-and-controlled-rotations.md.
Activity