cqlib_core/compile/error.rs
1// This code is part of Cqlib.
2//
3// (C) Copyright China Telecom Quantum Group 2025-2026
4//
5// This code is licensed under the Apache License, Version 2.0. You may
6// obtain a copy of this license in the LICENSE.txt file in the root directory
7// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8//
9// Any modifications or derivative works of this code must retain this
10// copyright notice, and modified files need to carry a notice indicating
11// that they have been altered from the originals.
12
13use crate::circuit::{CircuitError, Instruction};
14use crate::device::{DeviceValidationError, LogicalQubit, PhysicalQubit};
15use std::fmt;
16use thiserror::Error;
17
18/// One exact device-lowering dependency for which no plan exists.
19#[derive(Debug, Clone)]
20pub struct DeviceLoweringDependency {
21 /// Instruction required by the candidate.
22 pub instruction: Instruction,
23 /// Exact ordered physical arguments required by the candidate.
24 pub qargs: Vec<PhysicalQubit>,
25}
26
27/// One unsuccessful candidate considered while lowering a device instruction.
28#[derive(Debug, Clone)]
29pub struct DeviceLoweringCandidateFailure {
30 /// Stable direction-template or knowledge-rule name.
31 pub template: String,
32 /// Unique candidate dependencies for which the planner found no native plan.
33 pub unsatisfied_dependencies: Vec<DeviceLoweringDependency>,
34}
35
36/// Structured diagnostics for an operation with no device instruction plan.
37#[derive(Debug, Clone)]
38pub struct DeviceLoweringFailure {
39 /// Source instruction that could not be lowered.
40 pub instruction: Instruction,
41 /// Ordered physical arguments on which lowering was attempted.
42 pub qargs: Vec<PhysicalQubit>,
43 /// Candidate templates and their unresolved exact-qargs dependencies.
44 pub attempted_candidates: Vec<DeviceLoweringCandidateFailure>,
45}
46
47impl fmt::Display for DeviceLoweringFailure {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 write!(
50 f,
51 "no device instruction lowering plan for {} on ordered physical qargs {:?}",
52 self.instruction, self.qargs
53 )
54 }
55}
56
57impl std::error::Error for DeviceLoweringFailure {}
58
59/// Structured failures produced while selecting or routing a SABRE layout.
60#[derive(Debug, Clone, PartialEq, Eq, Error)]
61pub enum SabreRoutingFailure {
62 /// No physical qubit supports the complete native plan required by a
63 /// logical unary requirement.
64 #[error("logical unary requirement on {logical} has no executable native terminal")]
65 NoExecutableUnaryTerminal {
66 /// Logical qubit carrying the unsupported unary requirement.
67 logical: LogicalQubit,
68 },
69 /// A unary requirement cannot reach any physical qubit on which its
70 /// selected native plan is executable.
71 #[error(
72 "logical unary requirement on {logical} at physical qubit {physical} cannot reach an executable location through lowerable SWAP edges"
73 )]
74 UnreachableUnaryPlacement {
75 /// Logical qubit carrying the unary requirement.
76 logical: LogicalQubit,
77 /// Physical location at which the logical qubit starts.
78 physical: PhysicalQubit,
79 },
80 /// No ordered physical pair supports the complete native plan required by
81 /// a logical interaction.
82 #[error("logical interaction {logical:?} has no executable native terminal pair")]
83 NoExecutablePairTerminal {
84 /// Ordered logical pair carrying the unsupported interaction.
85 logical: [LogicalQubit; 2],
86 },
87 /// An ordered pair requirement cannot reach any physical pair on which its
88 /// selected native plan is executable.
89 #[error(
90 "logical interaction {logical:?} at physical qubits {physical:?} cannot reach an executable terminal pair through lowerable SWAP edges"
91 )]
92 UnreachablePairPlacement {
93 /// Ordered logical pair carrying the interaction.
94 logical: [LogicalQubit; 2],
95 /// Ordered physical placement at which routing starts.
96 physical: [PhysicalQubit; 2],
97 },
98 /// No assignment of logical qubits to SWAP-feasible movement components
99 /// satisfies all unary, ordered-pair, and capacity constraints.
100 #[error(
101 "no movement-component assignment satisfies all unary, ordered-pair, and capacity constraints"
102 )]
103 MovementAssignmentInfeasible,
104 /// The bounded component-assignment search stopped without either finding
105 /// a placement or proving that none exists.
106 #[error(
107 "movement-component assignment exhausted budget {budget} after {expansions} expansions without proving infeasibility"
108 )]
109 MovementAssignmentBudgetExhausted {
110 /// Maximum number of assignment states permitted by the configuration.
111 budget: usize,
112 /// Number of assignment states actually expanded.
113 expansions: usize,
114 },
115 /// Candidate generation succeeded, but every candidate failed an exact
116 /// movement-reachability or native-lowering requirement.
117 #[error(
118 "all {evaluated} SABRE layout candidates were infeasible ({missing_terminal} missing a native terminal, {movement_unreachable} movement-unreachable, {unsupported_native} rejected during native lowering)"
119 )]
120 NoFeasibleLayoutCandidate {
121 /// Total number of candidates evaluated.
122 evaluated: usize,
123 /// Candidates rejected because a requirement has no executable native
124 /// terminal anywhere on the target.
125 missing_terminal: usize,
126 /// Candidates rejected because their starting placement cannot reach
127 /// an existing terminal through lowerable SWAPs.
128 movement_unreachable: usize,
129 /// Candidates rejected because an exact-qargs native plan was absent.
130 unsupported_native: usize,
131 },
132}
133
134/// Errors raised by compiler infrastructure and compiler state validation.
135#[derive(Debug, Error)]
136pub enum CompilerError {
137 /// Conversion or validation of the circuit control-flow graph failed.
138 #[error(transparent)]
139 Circuit(#[from] CircuitError),
140 /// The input compiler state or circuit does not satisfy a pass precondition.
141 #[error("invalid compiler input: {0}")]
142 InvalidInput(String),
143 /// A compiler transform could not complete its declared operation.
144 #[error("compiler transform '{name}' failed: {reason}")]
145 TransformFailed {
146 /// Stable transform or synthesis primitive name.
147 name: &'static str,
148 /// Human-readable diagnostic describing why the transform failed.
149 reason: String,
150 },
151 /// A compiler pass produced a state that violates its declared contract.
152 #[error("compiler invariant violation: {0}")]
153 InvariantViolation(String),
154 /// No exact-qargs native lowering plan exists for an operation.
155 #[error("device instruction lowering failed: {0}")]
156 DeviceLoweringFailed(#[source] DeviceLoweringFailure),
157 /// SABRE could not find a feasible layout or route under the declared
158 /// movement and native-instruction constraints.
159 #[error("SABRE routing failed: {0}")]
160 SabreRoutingFailed(#[source] SabreRoutingFailure),
161 /// The final circuit violates the configured device execution contract.
162 #[error("device validation failed: {0}")]
163 DeviceValidationFailed(#[from] DeviceValidationError),
164}