Skip to main content

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}