• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Qiskit / qiskit / 15645153029

13 Jun 2025 10:31PM CUT coverage: 88.021% (+0.02%) from 88.004%
15645153029

Pull #14599

github

web-flow
Merge 948c85bfa into 4d7d46ebc
Pull Request #14599: Port `expr::structurally_equivalent` to Rust.

850 of 951 new or added lines in 5 files covered. (89.38%)

25 existing lines in 6 files now uncovered.

83854 of 95266 relevant lines covered (88.02%)

514730.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.09
/crates/circuit/src/bit.rs
1
// This code is part of Qiskit.
2
//
3
// (C) Copyright IBM 2025
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

13
//! Definitions of the shareable bit types and registers.
14

15
use std::{
16
    fmt::Debug,
17
    hash::Hash,
18
    sync::atomic::{AtomicU32, AtomicU64, Ordering},
19
    sync::Arc,
20
};
21

22
use hashbrown::HashSet;
23
use pyo3::prelude::*;
24
use pyo3::{
25
    exceptions::{PyIndexError, PyTypeError, PyValueError},
26
    types::{PyList, PyType},
27
    IntoPyObjectExt, PyTypeInfo,
28
};
29

30
use crate::circuit_data::CircuitError;
31
use crate::dag_circuit::PyBitLocations;
32
use crate::slice::{PySequenceIndex, SequenceIndex};
33

34
/// Describes a relationship between a bit and all the registers it belongs to
35
#[derive(Debug, Clone)]
36
pub struct BitLocations<R: Register> {
37
    pub(crate) index: u32,
38
    registers: Vec<(R, usize)>,
39
}
40

41
impl<R: Register + PartialEq> BitLocations<R> {
42
    /// Creates new instance of [BitLocations]
43
    pub fn new<T: IntoIterator<Item = (R, usize)>>(index: u32, registers: T) -> Self {
8,483,319✔
44
        Self {
8,483,319✔
45
            index,
8,483,319✔
46
            registers: registers.into_iter().collect(),
8,483,319✔
47
        }
8,483,319✔
48
    }
8,483,319✔
49

50
    /// Adds a register entry
51
    pub fn add_register(&mut self, register: R, index: usize) {
2,738,431✔
52
        self.registers.push((register, index))
2,738,431✔
53
    }
2,738,431✔
54

55
    /// Removes a register location in `O(n)`` time, where N is the number of
56
    /// registers in this entry.
57
    pub fn remove_register(&mut self, register: &R, index: usize) -> Option<(R, usize)> {
40,484✔
58
        for (idx, reg) in self.registers.iter().enumerate() {
40,484✔
59
            if (&reg.0, &reg.1) == (register, &index) {
40,484✔
60
                let res = self.registers.remove(idx);
40,484✔
61
                return Some(res);
40,484✔
62
            }
×
63
        }
64
        None
×
65
    }
40,484✔
66

67
    pub fn index(&self) -> u32 {
1,284✔
68
        self.index
1,284✔
69
    }
1,284✔
70

71
    pub fn registers(&self) -> &[(R, usize)] {
200✔
72
        &self.registers
200✔
73
    }
200✔
74
}
75

76
impl<'py, R> IntoPyObject<'py> for BitLocations<R>
77
where
78
    R: Debug + Clone + Register + for<'a> IntoPyObject<'a>,
79
{
80
    type Target = PyBitLocations;
81
    type Output = Bound<'py, PyBitLocations>;
82
    type Error = PyErr;
83

84
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
536,950✔
85
        PyBitLocations::new(
536,950✔
86
            self.index as usize,
536,950✔
87
            self.registers
536,950✔
88
                .into_pyobject(py)?
536,950✔
89
                .downcast_into::<PyList>()?
536,950✔
90
                .unbind(),
536,950✔
91
        )
536,950✔
92
        .into_pyobject(py)
536,950✔
93
    }
536,950✔
94
}
95

96
impl<'py, R> FromPyObject<'py> for BitLocations<R>
97
where
98
    R: Debug + Clone + Register + for<'a> IntoPyObject<'a> + for<'a> FromPyObject<'a>,
99
{
100
    fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
1,838✔
101
        let ob_down = ob.downcast::<PyBitLocations>()?.borrow();
1,838✔
102
        Ok(Self {
1,838✔
103
            index: ob_down.index as u32,
1,838✔
104
            registers: ob_down.registers.extract(ob.py())?,
1,838✔
105
        })
106
    }
1,838✔
107
}
108

109
/// Main representation of the inner properties of a shareable `Bit` object.
110
///
111
/// This is supplemented by an extra marker type to encode additional subclass information for
112
/// communication with Python space, which is used to distinguish an AncillaQubit from a Qubit
113
/// which is a Python domain construct only for backwards compatibility, but we don't need in
114
/// rust.
115
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
116
enum BitInfo<B> {
117
    Owned {
118
        register: Arc<OwningRegisterInfo<B>>,
119
        index: u32,
120
    },
121
    Anonymous {
122
        /// Unique id for bit, derives from [ShareableBit::anonymous_instance_count]
123
        uid: u64,
124
        subclass: B,
125
    },
126
}
127
impl<B> BitInfo<B> {
128
    /// Which subclass the bit is.
129
    #[inline]
130
    fn subclass(&self) -> &B {
35,814,696✔
131
        match self {
35,814,696✔
132
            BitInfo::Owned { register, .. } => &register.subclass,
31,730,420✔
133
            BitInfo::Anonymous { subclass, .. } => subclass,
4,084,276✔
134
        }
135
    }
35,814,696✔
136
}
137

138
// The trait bounds aren't _strictly_ necessary, but they simplify a lot of later bounds.
139
pub trait ShareableBit: Clone + Eq + Hash + Debug {
140
    type Subclass: Copy + Eq + Hash + Debug + Default;
141
    // A description of the bit class which is used for error messages
142
    const DESCRIPTION: &'static str;
143
}
144
// An internal trait to let `RegisterInfo` manifest full `ShareableBit` instances from `BitInfo`
145
// structs without leaking that implemntation detail into the public.
146
trait ManifestableBit: ShareableBit {
147
    fn from_info(val: BitInfo<<Self as ShareableBit>::Subclass>) -> Self;
148
    fn info(&self) -> &BitInfo<<Self as ShareableBit>::Subclass>;
149
}
150

151
/// Implement a generic bit.
152
///
153
/// .. note::
154
///     This class cannot be instantiated directly. Its only purpose is to allow generic type
155
///     checking for :class:`.Clbit` and :class:`.Qubit`.
156
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
157
#[pyclass(subclass, name = "Bit", module = "qiskit.circuit", frozen)]
12✔
158
pub struct PyBit;
159
/// Implement a generic register.
160
///
161
/// .. note::
162
///     This class cannot be instantiated directly.  Its only purpose is to allow generic type
163
///     checking for :class:`~.ClassicalRegister` and :class:`~.QuantumRegister`.
164
#[pyclass(
12✔
165
    name = "Register",
12✔
166
    module = "qiskit.circuit",
12✔
167
    subclass,
12✔
168
    frozen,
12✔
169
    eq,
12✔
170
    hash
12✔
171
)]
12✔
172
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
173
pub struct PyRegister;
174

175
/// Contains the information for a register that owns the bits it contains.
176
///
177
/// This is separate to the full [RegisterInfo] because owned bits also need to store a
178
/// backreference to their owning register.
179
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
180
pub struct OwningRegisterInfo<S> {
181
    name: String,
182
    size: u32,
183
    subclass: S,
184
}
185

186
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
187
enum RegisterInfo<B: ShareableBit> {
188
    Owning(Arc<OwningRegisterInfo<<B as ShareableBit>::Subclass>>),
189
    Alias {
190
        name: String,
191
        bits: Vec<B>,
192
        subclass: <B as ShareableBit>::Subclass,
193
    },
194
}
195
impl<B: ShareableBit> RegisterInfo<B> {
196
    /// The name of the register.
197
    pub fn name(&self) -> &str {
1,895,015✔
198
        match self {
1,895,015✔
199
            Self::Owning(reg) => &reg.name,
1,631,153✔
200
            Self::Alias { name, .. } => name,
263,862✔
201
        }
202
    }
1,895,015✔
203
    /// The length of the register.
204
    pub fn len(&self) -> usize {
1,653,435✔
205
        match self {
1,653,435✔
206
            Self::Owning(reg) => reg.size as usize,
1,626,709✔
207
            Self::Alias { bits, .. } => bits.len(),
26,726✔
208
        }
209
    }
1,653,435✔
210
    /// Is the register empty?
211
    pub fn is_empty(&self) -> bool {
×
212
        self.len() == 0
×
213
    }
×
214
    /// Which subclass does the register correspond to?
215
    fn subclass(&self) -> &<B as ShareableBit>::Subclass {
917,886✔
216
        match self {
917,886✔
217
            Self::Owning(reg) => &reg.subclass,
877,258✔
218
            Self::Alias { subclass, .. } => subclass,
40,628✔
219
        }
220
    }
917,886✔
221
}
222
impl<B: ManifestableBit> RegisterInfo<B> {
223
    /// What is the index of this bit in the register, if any?
224
    pub fn index_of(&self, bit: &B) -> Option<usize> {
7,084✔
225
        match self {
7,084✔
226
            Self::Owning(our_reg) => {
7,064✔
227
                let BitInfo::Owned {
228
                    register: bit_reg,
7,048✔
229
                    index,
7,048✔
230
                } = bit.info()
7,064✔
231
                else {
232
                    return None;
16✔
233
                };
234
                (*our_reg == *bit_reg).then_some(*index as usize)
7,048✔
235
            }
236
            Self::Alias { bits, .. } => bits.iter().position(|other| *other == *bit),
20✔
237
        }
238
    }
7,084✔
239
    /// Does this register contain this bit?
240
    pub fn contains(&self, bit: &B) -> bool {
164✔
241
        self.index_of(bit).is_some()
164✔
242
    }
164✔
243
    /// Get the bit at the given index, if in range.
244
    fn get(&self, index: usize) -> Option<B> {
6,097,025✔
245
        match self {
6,097,025✔
246
            RegisterInfo::Owning(reg) => (index < (reg.size as usize)).then(|| {
5,460,149✔
247
                B::from_info(BitInfo::Owned {
4,389,495✔
248
                    register: reg.clone(),
4,389,495✔
249
                    index: index as u32,
4,389,495✔
250
                })
4,389,495✔
251
            }),
5,460,149✔
252
            RegisterInfo::Alias { bits, .. } => bits.get(index).cloned(),
636,876✔
253
        }
254
    }
6,097,025✔
255
    /// Iterate over the bits in the register.
256
    fn iter(&self) -> RegisterInfoIter<B> {
1,279,622✔
257
        RegisterInfoIter {
1,279,622✔
258
            base: self,
1,279,622✔
259
            index: 0,
1,279,622✔
260
        }
1,279,622✔
261
    }
1,279,622✔
262
}
263

264
struct RegisterInfoIter<'a, B: ManifestableBit> {
265
    base: &'a RegisterInfo<B>,
266
    index: usize,
267
}
268
impl<B: ManifestableBit> Iterator for RegisterInfoIter<'_, B> {
269
    type Item = B;
270
    fn next(&mut self) -> Option<Self::Item> {
4,810,617✔
271
        let out = self.base.get(self.index);
4,810,617✔
272
        if out.is_some() {
4,810,617✔
273
            self.index += 1;
3,532,497✔
274
        }
3,532,497✔
275
        out
4,810,617✔
276
    }
4,810,617✔
277
    fn size_hint(&self) -> (usize, Option<usize>) {
26,028✔
278
        let rem = self.base.len().saturating_sub(self.index);
26,028✔
279
        (rem, Some(rem))
26,028✔
280
    }
26,028✔
281
}
282
impl<B: ManifestableBit> ExactSizeIterator for RegisterInfoIter<'_, B> {}
283

284
pub trait Register {
285
    /// The type of bit stored by the [Register]
286
    type Bit;
287

288
    /// Returns the size of the [Register].
289
    fn len(&self) -> usize;
290
    /// Checks if the [Register] is empty.
291
    fn is_empty(&self) -> bool;
292
    /// Returns the name of the [Register].
293
    fn name(&self) -> &str;
294
    /// Checks if a bit exists within the [Register].
295
    fn contains(&self, bit: &Self::Bit) -> bool;
296
    /// Return an iterator over all the bits in the register
297
    fn bits(&self) -> impl ExactSizeIterator<Item = Self::Bit>;
298
    /// Gets a bit by index
299
    fn get(&self, index: usize) -> Option<Self::Bit>;
300
}
301

302
/// Create a (Bit, Register) pair, and the associated Python objects.
303
///
304
/// # Args
305
///
306
/// * `bit_struct` - Identifier for new bit struct, for example, `ShareableQubit`.
307
/// * `subclass_ty` - Subclass type used for determining parent bit type, typically an enum to
308
///   select between different bit types (for qubit this is Qubit vs AncillaQubit). See
309
///   [QubitSubclass] and [ClbitSubclass] for typical types used here.
310
/// * `pybit_struct` - Identifier for python bit struct name, for example `PyQubit`.
311
/// * `pybit_name` - Python space class name for `pybit_struct`, for example `"Qubit"`.
312
/// * `bit_desc` - &'static str used as a name for describing bits, typically only used in error
313
///   messages to describe the bit. For example,   "qubit",
314
/// * `reg_struct` - Identifier for rust register struct name, for example `QuantumRegister`
315
/// * `pyreg_struct` - Identifier for python register struct, for example `PyQuantumRegister`
316
/// * `pyreg_name` - Python space class name for `pyreg_struct. For example, `"QuantumRegister"`.
317
/// * `pyreg_prefix` - String prefix for python space registers. Normally only `"q"` or `"c"`.
318
/// * `bit_counter_name` - Identifier to use for global static atomic counter of anonymous bits
319
///   created. For example, `QUBIT_INSTANCES`.
320
/// * `reg_counter_name` - Identifier to use for global static atomic counter of anonymous
321
///   registers create. For example, `QUANTUM_REGISTER_INSTANCES`.
322
macro_rules! create_bit_object {
323
    (
324
        $bit_struct:ident,
325
        $subclass_ty:ty,
326
        $pybit_struct:ident,
327
        $pybit_name:expr,
328
        $bit_desc:expr,
329
        $reg_struct:ident,
330
        $pyreg_struct:ident,
331
        $pyreg_name:expr,
332
        $pyreg_prefix:expr,
333
        $bit_counter_name:ident,
334
        $reg_counter_name:ident
335
    ) => {
336
        /// Global counter for the number of anonymous bits created.
337
        static $bit_counter_name: AtomicU64 = AtomicU64::new(0);
338
        /// Global counter for the number of anonymous register created.
339
        static $reg_counter_name: AtomicU32 = AtomicU32::new(0);
340

341
        /// A representation of a bit that can be shared between circuits, and allows linking
342
        /// corresponding bits between two circuits.
343
        ///
344
        /// These objects are comparable in a global sense, unlike the lighter [Qubit] or [Clbit]
345
        /// index-like objects used only _within_ a cirucit.  We use these objects when comparing
346
        /// two circuits to each other, and resolving Python objects, but within the context of a
347
        /// circuit, we just use the simple indices.
348
        #[derive(Clone, Debug, PartialEq, Eq, Hash)]
349
        pub struct $bit_struct(BitInfo<$subclass_ty>);
350
        impl $bit_struct {
351
            #[inline]
352
            fn anonymous_instance_count() -> &'static AtomicU64 {
497,602✔
353
                &$bit_counter_name
497,602✔
354
            }
497,602✔
355

356
            /// Which subclass the bit is.
357
            #[inline]
358
            pub fn subclass(&self) -> &$subclass_ty {
35,814,696✔
359
                self.0.subclass()
35,814,696✔
360
            }
35,814,696✔
361

362
            /// Create a new anonymous bit.
363
            pub fn new_anonymous() -> Self {
497,512✔
364
                Self(BitInfo::Anonymous {
497,512✔
365
                    uid: Self::anonymous_instance_count().fetch_add(1, Ordering::Relaxed),
497,512✔
366
                    subclass: Default::default(),
497,512✔
367
                })
497,512✔
368
            }
497,512✔
369
        }
370

371
        impl ShareableBit for $bit_struct {
372
            type Subclass = $subclass_ty;
373
            const DESCRIPTION: &'static str = $bit_desc;
374
        }
375
        impl ManifestableBit for $bit_struct {
376
            fn from_info(val: BitInfo<<$bit_struct as ShareableBit>::Subclass>) -> Self {
4,389,495✔
377
                Self(val)
4,389,495✔
378
            }
4,389,495✔
379
            fn info(&self) -> &BitInfo<<$bit_struct as ShareableBit>::Subclass> {
7,064✔
380
                &self.0
7,064✔
381
            }
7,064✔
382
        }
383

384
        #[doc = concat!("A ", $bit_desc, ", which can be compared between different circuits.")]
385
        #[derive(Debug, Clone, PartialEq, Eq, Hash)]
386
        #[pyclass(subclass, name=$pybit_name, module="qiskit.circuit", extends=PyBit, frozen, eq, hash)]
62,396,258✔
387
        pub struct $pybit_struct($bit_struct);
388
        #[pymethods]
1,322,420✔
389
        impl $pybit_struct {
390
            /// Create a new bit.
391
            #[new]
392
            #[pyo3(signature=(register=None, index=None))]
393
            fn new(register: Option<Bound<$pyreg_struct>>, index: Option<u32>) -> PyResult<(Self, PyBit)> {
3,486✔
394
                match (register, index) {
3,486✔
395
                    (Some(register), Some(index)) => {
226✔
396
                        let register = &register.borrow().0;
226✔
397
                        let bit = register.get(index as usize).ok_or_else(|| {
226✔
398
                            PyIndexError::new_err(format!(
×
399
                                "index {} out of range for size {}", index, register.len()
×
400
                            ))
×
401
                        })?;
226✔
402
                        Ok((Self(bit), PyBit))
226✔
403
                    }
404
                    (None, None) => {
405
                        Ok((Self($bit_struct::new_anonymous()), PyBit))
3,260✔
406
                    }
407
                    _ => {
408
                        Err(PyTypeError::new_err("either both 'register' and 'index' are provided, or neither are"))
×
409
                    }
410
                }
411
            }
3,486✔
412

413
            fn __repr__(slf: Bound<Self>) -> PyResult<String> {
93,674✔
414
                let ob = &slf.borrow().0;
93,674✔
415
                let name = slf.get_type().qualname()?;
93,674✔
416
                match &ob.0 {
93,674✔
417
                    BitInfo::Owned { register, index } => {
92,608✔
418
                        Ok(format!("<{} register=({}, \"{}\"), index={}>", name, register.size, &register.name, index))
92,608✔
419
                    }
420
                    BitInfo::Anonymous { uid, .. } => Ok(format!("<{name} uid={uid}>")),
1,066✔
421
                }
422
            }
93,674✔
423
            fn __copy__(slf: PyRef<Self>) -> PyRef<Self> {
4✔
424
                // Bits are immutable.
4✔
425
                slf
4✔
426
            }
4✔
427
            fn __deepcopy__<'py>(
1,112,214✔
428
                slf: PyRef<'py, Self>,
1,112,214✔
429
                _memo: Bound<'py, PyAny>,
1,112,214✔
430
            ) -> PyRef<'py, Self> {
1,112,214✔
431
                // Everything a bit contains is immutable.
1,112,214✔
432
                slf
1,112,214✔
433
            }
1,112,214✔
434

435
            fn __reduce__(slf: Bound<Self>) -> PyResult<Bound<PyAny>> {
107,192✔
436
                // This is deliberately type-erasing up top, so `AncillaQubit` can override the
107,192✔
437
                // constructor methods.
107,192✔
438
                let ty = slf.get_type();
107,192✔
439
                match &slf.borrow().0 .0 {
107,192✔
440
                    BitInfo::Owned { register, index } => (
106,782✔
441
                        ty.getattr("_from_owned")?,
106,782✔
442
                        (register.name.to_owned(), register.size, index),
106,782✔
443
                    )
106,782✔
444
                        .into_bound_py_any(slf.py()),
106,782✔
445
                    // Don't need to examine the subclass, because it's handled by the overrides of
446
                    // the `_from_anonymous` and `_from_owned` methods.
447
                    BitInfo::Anonymous { uid, .. } => {
410✔
448
                        (ty.getattr("_from_anonymous")?, (uid,)).into_bound_py_any(slf.py())
410✔
449
                    }
450
                }
451
            }
107,192✔
452
            // Used by pickle, overridden in subclasses.
453
            #[staticmethod]
454
            fn _from_anonymous(py: Python, uid: u64) -> PyResult<Bound<PyAny>> {
50✔
455
                Ok(Bound::new(
50✔
456
                    py,
50✔
457
                    PyClassInitializer::from((
50✔
458
                        Self($bit_struct(BitInfo::Anonymous {
50✔
459
                            uid,
50✔
460
                            // Fine to do this, because `AncillaRegister` overrides the method.
50✔
461
                            subclass: Default::default(),
50✔
462
                        })),
50✔
463
                        PyBit,
50✔
464
                    )),
50✔
465
                )?
50✔
466
                .into_any())
50✔
467
            }
50✔
468
            #[staticmethod]
469
            fn _from_owned(
9,262✔
470
                py: Python,
9,262✔
471
                reg_name: String,
9,262✔
472
                reg_size: u32,
9,262✔
473
                index: u32,
9,262✔
474
            ) -> PyResult<Bound<PyAny>> {
9,262✔
475
                // This doesn't feel like the most efficient way - in a big list of owned qubits,
9,262✔
476
                // we'll pickle the register information many times - but good enough for now.
9,262✔
477
                let register = Arc::new(OwningRegisterInfo {
9,262✔
478
                    name: reg_name,
9,262✔
479
                    size: reg_size,
9,262✔
480
                    // Fine to do this, because `AncillaRegister` overrides the method.
9,262✔
481
                    subclass: Default::default(),
9,262✔
482
                });
9,262✔
483
                Ok(Bound::new(
9,262✔
484
                    py,
9,262✔
485
                    PyClassInitializer::from((
9,262✔
486
                        Self($bit_struct(BitInfo::Owned { register, index })),
9,262✔
487
                        PyBit,
9,262✔
488
                    )),
9,262✔
489
                )?
9,262✔
490
                .into_any())
9,262✔
491
            }
9,262✔
492

493
            // Legacy getters to keep Python-space QPY happy.
494
            #[getter]
495
            fn _register(&self) -> Option<$reg_struct> {
102,666✔
496
                match &self.0.0 {
102,666✔
497
                    BitInfo::Owned { register, .. } => {
102,292✔
498
                        Some($reg_struct(Arc::new(RegisterInfo::Owning(register.clone()))))
102,292✔
499
                    }
500
                    BitInfo::Anonymous { .. } => None,
374✔
501
                }
502
            }
102,666✔
503
            #[getter]
504
            fn _index(&self) -> Option<u32> {
42,922✔
505
                match &self.0.0 {
42,922✔
506
                    BitInfo::Owned { index, .. } => Some(*index),
42,858✔
507
                    BitInfo::Anonymous { .. } => None,
64✔
508
                }
509
            }
42,922✔
510
        }
511

512
        impl<'py> FromPyObject<'py> for $bit_struct {
513
            fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
13,882,880✔
514
                Ok(ob.downcast::<$pybit_struct>()?.borrow().0.clone())
13,882,880✔
515
            }
13,882,880✔
516
        }
517
        // The owning impl of `IntoPyObject` needs to be done manually, to better handle
518
        // subclassing.
519
        impl<'a, 'py> IntoPyObject<'py> for &'a $bit_struct {
520
            type Target = <$bit_struct as IntoPyObject<'py>>::Target;
521
            type Output = <$bit_struct as IntoPyObject<'py>>::Output;
522
            type Error = <$bit_struct as IntoPyObject<'py>>::Error;
523

524
            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
31,343,744✔
525
                self.clone().into_pyobject(py)
31,343,744✔
526
            }
31,343,744✔
527
        }
528

529
        /// A Rust-space register object.
530
        #[derive(Clone, Debug, PartialEq, Eq, Hash)]
531
        pub struct $reg_struct(Arc<RegisterInfo<$bit_struct>>);
532
        impl $reg_struct {
533
            #[inline]
534
            fn anonymous_instance_count() -> &'static AtomicU32 {
8,164✔
535
                &$reg_counter_name
8,164✔
536
            }
8,164✔
537

538
            /// Which subclass the register is.
539
            #[inline]
540
            pub fn subclass(&self) -> &<$bit_struct as ShareableBit>::Subclass {
917,886✔
541
                self.0.subclass()
917,886✔
542
            }
917,886✔
543

544
            /// Create a new owning register.
545
            #[inline]
546
            pub fn new_owning<S: Into<String>>(name: S, size: u32) -> Self {
802,770✔
547
                Self(Arc::new(RegisterInfo::Owning(Arc::new(OwningRegisterInfo {
802,770✔
548
                    name: name.into(),
802,770✔
549
                    size,
802,770✔
550
                    subclass: Default::default(),
802,770✔
551
                }))))
802,770✔
552
            }
802,770✔
553

554
            /// Create a new aliasing register.
555
            #[inline]
556
            pub fn new_alias(name: Option<String>, bits: Vec<$bit_struct>) -> Self {
102,222✔
557
                let name = name.unwrap_or_else(|| {
102,222✔
NEW
558
                    format!(
×
NEW
559
                        "{}{}",
×
NEW
560
                        $pyreg_prefix,
×
NEW
561
                        $reg_struct::anonymous_instance_count().fetch_add(1, Ordering::Relaxed)
×
NEW
562
                    )
×
563
                });
102,222✔
564
                Self(Arc::new(RegisterInfo::Alias {
102,222✔
565
                    name,
102,222✔
566
                    bits,
102,222✔
567
                    // This assumes that `B::default()` returns the base class.
102,222✔
568
                    subclass: Default::default(),
102,222✔
569
                }))
102,222✔
570
            }
102,222✔
571

572
            /// Get the name of the register.
573
            #[inline]
574
            pub fn name(&self) -> &str {
189,713✔
575
                self.0.name()
189,713✔
576
            }
189,713✔
577
            /// Get the length of the register.
578
            #[inline]
579
            pub fn len(&self) -> usize {
1,627,407✔
580
                self.0.len()
1,627,407✔
581
            }
1,627,407✔
582
            /// Is the register empty?
583
            #[inline]
584
            pub fn is_empty(&self) -> bool {
×
585
                self.0.is_empty()
×
586
            }
×
587
            /// Get the bit at the given index, if in range.
588
            #[inline]
589
            pub fn get(&self, index: usize) -> Option<$bit_struct> {
1,286,408✔
590
                self.0.get(index)
1,286,408✔
591
            }
1,286,408✔
592
            /// Is this bit in this register?
593
            #[inline]
594
            pub fn contains(&self, bit: &$bit_struct) -> bool {
164✔
595
                self.0.contains(bit)
164✔
596
            }
164✔
597
            /// What of the index of this bit in this register, if any?
598
            #[inline]
599
            pub fn index_of(&self, bit: &$bit_struct) -> Option<usize> {
6,920✔
600
                self.0.index_of(bit)
6,920✔
601
            }
6,920✔
602
            /// Iterate over the bits in the register.
603
            #[inline]
604
            pub fn iter(&self) -> impl ExactSizeIterator<Item = $bit_struct> + '_ {
1,279,622✔
605
                self.0.iter()
1,279,622✔
606
            }
1,279,622✔
607
        }
608

609
        impl Register for $reg_struct {
610
            type Bit = $bit_struct;
611

612
            fn len(&self) -> usize {
×
613
                self.0.len()
×
614
            }
×
615
            fn is_empty(&self)-> bool {
×
616
                self.0.is_empty()
×
617
            }
×
618
            fn name(&self) -> &str {
1,705,302✔
619
                self.0.name()
1,705,302✔
620
            }
1,705,302✔
621
            fn contains(&self, bit: &Self::Bit) -> bool {
×
622
                self.0.contains(bit)
×
623
            }
×
624
            fn bits(&self) -> impl ExactSizeIterator<Item = $bit_struct> {
1,279,612✔
625
                self.iter()
1,279,612✔
626
            }
1,279,612✔
627
            fn get(&self, index: usize) -> Option<Self::Bit> {
×
628
                self.0.get(index)
×
629
            }
×
630
        }
631

632
        impl<'py> FromPyObject<'py> for $reg_struct {
633
            fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
925,176✔
634
                Ok(ob.downcast::<$pyreg_struct>()?.borrow().0.clone())
925,176✔
635
            }
925,176✔
636
        }
637
        // The owning impl of `IntoPyObject` needs to be done manually, to better handle
638
        // subclassing.
639
        impl<'a, 'py> IntoPyObject<'py> for &'a $reg_struct {
640
            type Target = <$reg_struct as IntoPyObject<'py>>::Target;
641
            type Output = <$reg_struct as IntoPyObject<'py>>::Output;
642
            type Error = <$reg_struct as IntoPyObject<'py>>::Error;
643

644
            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
1,858✔
645
                self.clone().into_pyobject(py)
1,858✔
646
            }
1,858✔
647
        }
648

649
        /// Implement a register.
650
        #[pyclass(subclass, name=$pyreg_name, module="qiskit.circuit", extends=PyRegister, frozen, eq, hash, sequence)]
26,490✔
651
        #[derive(Clone, Debug, PartialEq, Eq, Hash)]
652
        pub struct $pyreg_struct($reg_struct);
653

654
        #[pymethods]
2,012,170✔
655
        impl $pyreg_struct {
656
            /// Create a new register.
657
            ///
658
            /// Either the ``size`` or the ``bits`` argument must be provided. If
659
            /// ``size`` is not None, the register will be pre-populated with bits of the
660
            /// correct type.
661
            ///
662
            /// Args:
663
            ///     size (int): Optional. The number of bits to include in the register.
664
            ///     name (str): Optional. The name of the register. If not provided, a
665
            ///         unique name will be auto-generated from the register type.
666
            ///     bits (list[Bit]): Optional. A list of :class:`.Bit` instances to be used to
667
            ///         populate the register.
668
            ///
669
            /// Raises:
670
            ///     CircuitError: if any of:
671
            ///
672
            ///         * both the ``size`` and ``bits`` arguments are provided, or if neither are.
673
            ///         * ``size`` is not valid.
674
            ///         * ``bits`` contained duplicated bits.
675
            ///         * ``bits`` contained bits of an incorrect type.
676
            ///         * ``bits`` exceeds the possible capacity for a register.
677
            #[pyo3(signature=(size=None, name=None, bits=None))]
678
            #[new]
679
            fn py_new(
874,014✔
680
                size: Option<isize>,
874,014✔
681
                name: Option<String>,
874,014✔
682
                bits: Option<Vec<$bit_struct>>,
874,014✔
683
            ) -> PyResult<(Self, PyRegister)> {
874,014✔
684
                let name = name.unwrap_or_else(|| {
874,014✔
685
                    format!(
7,866✔
686
                        "{}{}",
7,866✔
687
                        Self::prefix(),
7,866✔
688
                        $reg_struct::anonymous_instance_count().fetch_add(1, Ordering::Relaxed)
7,866✔
689
                    )
7,866✔
690
                });
874,014✔
691
                match (size, bits) {
874,014✔
692
                    (None, None) | (Some(_), Some(_)) => Err(CircuitError::new_err(
4✔
693
                        "Exactly one of the size or bits arguments can be provided.",
4✔
694
                    )),
4✔
695
                    (Some(size), None) => {
771,784✔
696
                        if size < 0 {
771,784✔
697
                            return Err(CircuitError::new_err(
6✔
698
                                "Register size must be non-negative.",
6✔
699
                            ));
6✔
700
                        }
771,778✔
701
                        let Ok(size) = size.try_into() else {
771,778✔
702
                            return Err(CircuitError::new_err("Register size too large."));
×
703
                        };
704
                        Ok((Self($reg_struct::new_owning(name, size)), PyRegister))
771,778✔
705
                    }
706
                    (None, Some(bits)) => {
102,226✔
707
                        if bits.iter().cloned().collect::<HashSet<_>>().len() != bits.len() {
102,226✔
708
                            return Err(CircuitError::new_err(
4✔
709
                                "Register bits must not be duplicated.",
4✔
710
                            ));
4✔
711
                        }
102,222✔
712
                        Ok((Self($reg_struct::new_alias(Some(name), bits)), PyRegister))
102,222✔
713
                    }
714
                }
715
            }
874,014✔
716

717
            /// The name of the register.
718
            #[getter]
719
            fn get_name(&self) -> &str {
173,464✔
720
                self.0.name()
173,464✔
721
            }
173,464✔
722
            /// The size of the register.
723
            #[getter]
724
            fn get_size(&self) -> usize {
45,292✔
725
                self.0.len()
45,292✔
726
            }
45,292✔
727

728
            fn __repr__(&self) -> String {
82✔
729
                format!("{}({}, '{}')", $pyreg_name, self.0.len(), self.0.name())
82✔
730
            }
82✔
731

732
            fn __contains__(&self, bit: &$pybit_struct) -> bool {
164✔
733
                self.0.contains(&bit.0)
164✔
734
            }
164✔
735

736
            fn __getnewargs__(&self) -> (Option<isize>, Option<String>, Option<Vec<$bit_struct>>) {
430,106✔
737
                match &*self.0.0 {
430,106✔
738
                    RegisterInfo::Owning(reg) => {
425,670✔
739
                        (Some(reg.size as isize), Some(reg.name.to_owned()), None)
425,670✔
740
                    }
741
                    RegisterInfo::Alias { name, bits, .. } => {
4,436✔
742
                        (None, Some(name.clone()), Some(bits.clone()))
4,436✔
743
                    }
744
                }
745
            }
430,106✔
746

747
            // We rely on `__len__` and `__getitem__` for implicit iteration - it's easier than
748
            // defining a new struct ourselves.
749
            fn __len__(&self) -> usize {
191,332✔
750
                self.0.len()
191,332✔
751
            }
191,332✔
752
            fn __getitem__<'py>(&self, ob: Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {
1,390,328✔
753
                let get_inner = |idx| {
1,390,328✔
754
                    self.0.get(idx)
1,286,182✔
755
                        .expect("PySequenceIndex always returns valid indices")
1,286,182✔
756
                };
1,286,182✔
757
                if let Ok(sequence) = ob.extract::<PySequenceIndex>() {
1,390,328✔
758
                    match sequence.with_len(self.0.len())? {
1,389,974✔
759
                        SequenceIndex::Int(idx) => get_inner(idx).into_bound_py_any(ob.py()),
1,129,484✔
760
                        s => {
75,622✔
761
                            Ok(PyList::new(ob.py(), s.into_iter().map(get_inner))?.into_any())
75,622✔
762
                        }
763
                    }
764
                } else if let Ok(list) = ob.downcast::<PyList>() {
354✔
765
                    let out = PyList::empty(ob.py());
354✔
766
                    for item in list.iter() {
686✔
767
                        out.append(get_inner(PySequenceIndex::convert_idx(
686✔
768
                            item.extract()?,
686✔
769
                            self.0.len(),
686✔
770
                        )?))?;
×
771
                    }
772
                    Ok(out.into_any())
354✔
773
                } else {
774
                    Err(PyTypeError::new_err("index must be int, slice or list"))
×
775
                }
776
            }
1,390,328✔
777

778
            /// The index of the given bit in the register.
779
            fn index(&self, bit: Bound<$pybit_struct>) -> PyResult<usize> {
56✔
780
                let bit_inner = bit.borrow();
56✔
781
                self.0.index_of(&bit_inner.0).ok_or_else(|| {
56✔
782
                    match bit.repr() {
×
783
                        Ok(repr) => PyValueError::new_err(format!("Bit {repr} not found in register.")),
×
784
                        Err(err) => err,
×
785
                    }
786
                })
56✔
787
            }
56✔
788

789
            /// Allows for the creation of a new register with a temporary prefix and the
790
            /// same instance counter.
791
            #[pyo3(signature=(size=None, name=None, bits=None))]
792
            #[staticmethod]
793
            fn _new_with_prefix(
6✔
794
                py: Python,
6✔
795
                size: Option<isize>,
6✔
796
                name: Option<String>,
6✔
797
                bits: Option<Vec<$bit_struct>>,
6✔
798
            ) -> PyResult<Py<Self>> {
6✔
799
                let name =
6✔
800
                    format!(
6✔
801
                        "{}{}",
6✔
802
                        name.unwrap_or(Self::prefix().to_string()),
6✔
803
                        $reg_struct::anonymous_instance_count().fetch_add(1, Ordering::Relaxed)
6✔
804
                    );
6✔
805
                Py::new(py, Self::py_new(size, Some(name), bits)?)
6✔
806
            }
6✔
807

808
            #[classattr]
809
            fn prefix() -> &'static str {
7,896✔
810
                $pyreg_prefix
7,896✔
811
            }
7,896✔
812
            #[classattr]
813
            fn bit_type(py: Python) -> Bound<PyType> {
24✔
814
                $pybit_struct::type_object(py)
24✔
815
            }
24✔
816
            #[classattr]
817
            fn instances_count() -> u32 {
24✔
818
                $reg_struct::anonymous_instance_count().load(Ordering::Relaxed)
24✔
819
            }
24✔
820
        }
821
    };
822
}
823

824
/// Which subclass a [ShareableQubit] is.
825
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Default)]
826
pub enum QubitSubclass {
827
    /// The base Python-space ``Qubit`` class.
828
    #[default]
829
    QUBIT,
830
    /// The subclass ``AncillaQubit``.
831
    ANCILLA,
832
}
833
create_bit_object!(
834
    ShareableQubit,
835
    QubitSubclass,
836
    PyQubit,
837
    "Qubit",
838
    "qubit",
839
    QuantumRegister,
840
    PyQuantumRegister,
841
    "QuantumRegister",
842
    "q",
843
    QUBIT_INSTANCES,
844
    QUANTUM_REGISTER_INSTANCES
845
);
846
impl ShareableQubit {
847
    /// Create a new anonymous ancilla qubit.
848
    ///
849
    /// Qubits owned by registers can only be created *by* registers.
850
    pub fn new_anonymous_ancilla() -> Self {
90✔
851
        Self(BitInfo::Anonymous {
90✔
852
            uid: Self::anonymous_instance_count().fetch_add(1, Ordering::Relaxed),
90✔
853
            subclass: QubitSubclass::ANCILLA,
90✔
854
        })
90✔
855
    }
90✔
856

857
    /// Is this qubit an ancilla?
858
    #[inline]
859
    pub fn is_ancilla(&self) -> bool {
35,814,696✔
860
        *self.subclass() == QubitSubclass::ANCILLA
35,814,696✔
861
    }
35,814,696✔
862
}
863

864
/// A qubit used as an ancilla.
865
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
866
#[pyclass(name="AncillaQubit", module="qiskit.circuit", extends=PyQubit, frozen)]
12✔
867
pub struct PyAncillaQubit;
868
#[pymethods]
6,578✔
869
impl PyAncillaQubit {
870
    /// Create a new anonymous ancilla qubit.
871
    #[new]
872
    fn new() -> PyClassInitializer<Self> {
90✔
873
        PyClassInitializer::from(PyBit)
90✔
874
            .add_subclass(PyQubit(ShareableQubit::new_anonymous_ancilla()))
90✔
875
            .add_subclass(Self)
90✔
876
    }
90✔
877

878
    fn __hash__(slf: PyRef<Self>) -> PyResult<isize> {
4,908✔
879
        let py = slf.py();
4,908✔
880
        let qubit: &PyQubit = &slf.into_super();
4,908✔
881
        Bound::new(py, (qubit.clone(), PyBit))?.hash()
4,908✔
882
    }
4,908✔
883

884
    fn __eq__(slf: PyRef<Self>, other: PyRef<Self>) -> bool {
1,658✔
885
        slf.as_super().eq(other.as_super())
1,658✔
886
    }
1,658✔
887

888
    // Pickle overrides.
889
    #[staticmethod]
890
    fn _from_anonymous(py: Python, uid: u64) -> PyResult<Bound<PyAny>> {
×
891
        Ok(Bound::new(
×
892
            py,
×
893
            PyClassInitializer::from(PyBit)
×
894
                .add_subclass(PyQubit(ShareableQubit(BitInfo::Anonymous {
×
895
                    uid,
×
896
                    subclass: QubitSubclass::ANCILLA,
×
897
                })))
×
898
                .add_subclass(PyAncillaQubit),
×
899
        )?
×
900
        .into_any())
×
901
    }
×
902
    #[staticmethod]
903
    fn _from_owned(
×
904
        py: Python,
×
905
        reg_name: String,
×
906
        reg_size: u32,
×
907
        index: u32,
×
908
    ) -> PyResult<Bound<PyAny>> {
×
909
        // This doesn't feel like the most efficient way - in a big list of owned qubits,
×
910
        // we'll pickle the register information many times - but good enough for now.
×
911
        let register = Arc::new(OwningRegisterInfo {
×
912
            name: reg_name,
×
913
            size: reg_size,
×
914
            subclass: QubitSubclass::ANCILLA,
×
915
        });
×
916
        Ok(Bound::new(
×
917
            py,
×
918
            PyClassInitializer::from(PyBit)
×
919
                .add_subclass(PyQubit(ShareableQubit(BitInfo::Owned { register, index })))
×
920
                .add_subclass(PyAncillaQubit),
×
921
        )?
×
922
        .into_any())
×
923
    }
×
924
}
925
impl<'py> IntoPyObject<'py> for ShareableQubit {
926
    type Target = PyAny;
927
    type Output = Bound<'py, PyAny>;
928
    type Error = PyErr;
929

930
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
35,814,586✔
931
        if self.is_ancilla() {
35,814,586✔
932
            Ok(Bound::new(
10,778✔
933
                py,
10,778✔
934
                PyClassInitializer::from(PyBit)
10,778✔
935
                    .add_subclass(PyQubit(self))
10,778✔
936
                    .add_subclass(PyAncillaQubit),
10,778✔
937
            )?
10,778✔
938
            .into_any())
10,778✔
939
        } else {
940
            Ok(Bound::new(py, (PyQubit(self), PyBit))?.into_any())
35,803,808✔
941
        }
942
    }
35,814,586✔
943
}
944

945
impl QuantumRegister {
946
    /// Create a new ancilla register that owns its qubits.
947
    pub fn new_ancilla_owning(name: String, size: u32) -> Self {
636✔
948
        Self(Arc::new(RegisterInfo::Owning(Arc::new(
636✔
949
            OwningRegisterInfo {
636✔
950
                name,
636✔
951
                size,
636✔
952
                subclass: QubitSubclass::ANCILLA,
636✔
953
            },
636✔
954
        ))))
636✔
955
    }
636✔
956

957
    /// Create a new ancilla register that aliases other bits.
958
    ///
959
    /// Returns `None` if not all the bits are ancillas.
960
    pub fn new_ancilla_alias(name: String, bits: Vec<ShareableQubit>) -> Option<Self> {
22✔
961
        bits.iter().all(|bit| bit.is_ancilla()).then(|| {
110✔
962
            Self(Arc::new(RegisterInfo::Alias {
22✔
963
                name,
22✔
964
                bits,
22✔
965
                subclass: QubitSubclass::ANCILLA,
22✔
966
            }))
22✔
967
        })
22✔
968
    }
22✔
969

970
    /// Is this an ancilla register?
971
    ///
972
    /// Non-ancilla registers can still contain ancilla qubits, but not the other way around.
973
    pub fn is_ancilla(&self) -> bool {
917,886✔
974
        *self.subclass() == QubitSubclass::ANCILLA
917,886✔
975
    }
917,886✔
976
}
977
// This isn't intended for use from Rust space.
978
/// Implement an ancilla register.
979
#[pyclass(
12✔
980
    name = "AncillaRegister",
12✔
981
    module = "qiskit.circuit",
12✔
982
    frozen,
12✔
983
    extends=PyQuantumRegister
12✔
984
)]
12✔
985
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
986
pub struct PyAncillaRegister;
987
#[pymethods]
78✔
988
impl PyAncillaRegister {
989
    // Most of the methods are inherited from `QuantumRegister` in Python space.
990

991
    #[pyo3(signature=(size=None, name=None, bits=None))]
992
    #[new]
993
    fn py_new(
664✔
994
        size: Option<isize>,
664✔
995
        name: Option<String>,
664✔
996
        bits: Option<Vec<ShareableQubit>>,
664✔
997
    ) -> PyResult<PyClassInitializer<Self>> {
664✔
998
        let name = name.unwrap_or_else(|| {
664✔
999
            format!(
268✔
1000
                "{}{}",
268✔
1001
                Self::prefix(),
268✔
1002
                QuantumRegister::anonymous_instance_count().fetch_add(1, Ordering::Relaxed)
268✔
1003
            )
268✔
1004
        });
664✔
1005
        let reg = match (size, bits) {
664✔
1006
            (None, None) | (Some(_), Some(_)) => {
1007
                return Err(CircuitError::new_err(
2✔
1008
                    "Exactly one of the size or bits arguments can be provided.",
2✔
1009
                ));
2✔
1010
            }
1011
            (Some(size), None) => {
638✔
1012
                if size < 0 {
638✔
1013
                    return Err(CircuitError::new_err("Register size must be non-negative."));
2✔
1014
                }
636✔
1015
                let Ok(size) = size.try_into() else {
636✔
1016
                    return Err(CircuitError::new_err("Register size too large."));
×
1017
                };
1018
                QuantumRegister::new_ancilla_owning(name, size)
636✔
1019
            }
1020
            (None, Some(bits)) => {
24✔
1021
                if bits.iter().cloned().collect::<HashSet<_>>().len() != bits.len() {
24✔
1022
                    return Err(CircuitError::new_err(
2✔
1023
                        "Register bits must not be duplicated.",
2✔
1024
                    ));
2✔
1025
                }
22✔
1026
                QuantumRegister::new_ancilla_alias(name, bits)
22✔
1027
                    .ok_or_else(|| PyTypeError::new_err("all bits must be AncillaQubit"))?
22✔
1028
            }
1029
        };
1030
        Ok(PyClassInitializer::from(PyRegister)
658✔
1031
            .add_subclass(PyQuantumRegister(reg))
658✔
1032
            .add_subclass(Self))
658✔
1033
    }
664✔
1034

1035
    fn __hash__(slf: PyRef<Self>) -> PyResult<isize> {
×
1036
        let py = slf.py();
×
1037
        let qreg: &PyQuantumRegister = &slf.into_super();
×
1038
        Bound::new(py, (qreg.clone(), PyRegister))?.hash()
×
1039
    }
×
1040

1041
    fn __eq__(slf: PyRef<Self>, other: PyRef<Self>) -> bool {
42✔
1042
        slf.as_super().eq(other.as_super())
30✔
1043
    }
30✔
1044

1045
    #[classattr]
1046
    fn prefix() -> &'static str {
280✔
1047
        "a"
280✔
1048
    }
280✔
1049

1050
    #[classattr]
1051
    fn bit_type(py: Python) -> Bound<PyType> {
12✔
1052
        PyAncillaQubit::type_object(py)
12✔
1053
    }
12✔
1054
}
1055
impl<'py> IntoPyObject<'py> for QuantumRegister {
1056
    type Target = PyAny;
1057
    type Output = Bound<'py, PyAny>;
1058
    type Error = PyErr;
1059

1060
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
917,886✔
1061
        if self.is_ancilla() {
917,886✔
1062
            Ok(Bound::new(
434✔
1063
                py,
434✔
1064
                PyClassInitializer::from(PyRegister)
434✔
1065
                    .add_subclass(PyQuantumRegister(self))
434✔
1066
                    .add_subclass(PyAncillaRegister),
434✔
1067
            )?
434✔
1068
            .into_any())
434✔
1069
        } else {
1070
            Ok(Bound::new(py, (PyQuantumRegister(self), PyRegister))?.into_any())
917,452✔
1071
        }
1072
    }
917,886✔
1073
}
1074

1075
/// Which subclass a [ShareableClbit] is.
1076
///
1077
/// This carries no real data; there's no subclasses of ``Clbit``.  It's mostly used as a data
1078
/// marker and a way to define traits.
1079
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
1080
pub enum ClbitSubclass {
1081
    #[default]
1082
    CLBIT,
1083
}
1084
create_bit_object!(
1085
    ShareableClbit,
1086
    ClbitSubclass,
1087
    PyClbit,
1088
    "Clbit",
1089
    "clbit",
1090
    ClassicalRegister,
1091
    PyClassicalRegister,
1092
    "ClassicalRegister",
1093
    "c",
1094
    CLBIT_INSTANCES,
1095
    CLASSICAL_REGISTER_INSTANCES
1096
);
1097
impl<'py> IntoPyObject<'py> for ShareableClbit {
1098
    type Target = PyClbit;
1099
    type Output = Bound<'py, PyClbit>;
1100
    type Error = PyErr;
1101

1102
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
2,106,136✔
1103
        Bound::new(py, (PyClbit(self), PyBit))
2,106,136✔
1104
    }
2,106,136✔
1105
}
1106

1107
impl<'py> IntoPyObject<'py> for ClassicalRegister {
1108
    type Target = PyClassicalRegister;
1109
    type Output = Bound<'py, PyClassicalRegister>;
1110
    type Error = PyErr;
1111

1112
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
51,082✔
1113
        Bound::new(py, (PyClassicalRegister(self), PyRegister))
51,082✔
1114
    }
51,082✔
1115
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc