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

Qiskit / qiskit / 18104357474

29 Sep 2025 04:22PM UTC coverage: 88.301% (-0.006%) from 88.307%
18104357474

push

github

web-flow
Bump Rust edition to edition 2024 (#14876)

* Bump Rust edition to edition 2024

Now that our MSRV is set to be 1.85 this enables us to use the new rust
edition 2024. While there are some behavior changes especially around
temporaries, drop order, etc there are also some nice QoL improvements
to using the new edition. This commit opts in to using the new edition,
runs cargo fix on the repository to auto update a lot of the code,
fixes the compilation errors after this, and then cleans up the code.
The details on what changes in rust edition 2024 can be found here:

https://doc.rust-lang.org/nightly/edition-guide/rust-2024/index.html

For right now the cargo fmt rules are left on edition 2021 to minimize
the diff size here. We will do that change in a follow up PR as it will
be a larger diff that we likely want to add to the git blame exclude
list.

* Fix clippy issue

* Undo conversions of `if let`

`cargo fix --edition` converts all `if let` into corresponding `match`
statements, because the drop order changed slightly.  We do not rely on
the old drop order in any cases, so in general we can remove all those
changes.  This commit leaves a couple in place where the `match`
statement resulted in neater code.

* Avoid wildcard `match` statements

* Fix clippy complaints

* Run formatter

---------

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>

70 of 89 new or added lines in 18 files covered. (78.65%)

18 existing lines in 4 files now uncovered.

92857 of 105160 relevant lines covered (88.3%)

1168674.65 hits per line

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

59.52
/crates/cext/src/transpiler/transpile_function.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
use std::ffi::c_char;
13
use std::ffi::CString;
14

15
use qiskit_circuit::circuit_data::CircuitData;
16
use qiskit_transpiler::target::Target;
17

18
use qiskit_transpiler::transpile;
19
use qiskit_transpiler::transpile_layout::TranspileLayout;
20

21
use crate::exit_codes::ExitCode;
22
use crate::pointers::const_ptr_as_ref;
23

24
/// The container result object from ``qk_transpile``
25
///
26
/// When the transpiler successfully compiles a quantum circuit for a given target it
27
/// returns the transpiled circuit and the layout. The ``qk_transpile`` function will
28
/// write pointers to the fields in this struct when it successfully executes, you can
29
/// initialize this struct with null pointers or leave them unset as the values are never
30
/// read by ``qk_transpile`` and only written to. After calling ``qk_transpile`` you are
31
/// responsible for calling ``qk_circuit_free`` and ``qk_transpile_layout_free`` on the
32
/// members of this struct.
33
#[repr(C)]
34
pub struct TranspileResult {
35
    circuit: *mut CircuitData,
36
    layout: *mut TranspileLayout,
37
}
38

39
/// The options for running the transpiler
40
#[repr(C)]
41
pub struct TranspileOptions {
42
    /// The optimization level to run the transpiler with. Valid values are 0, 1, 2, or 3.
43
    optimization_level: u8,
44
    /// The seed for the transpiler. If set to a negative number this means no seed will be
45
    /// set and the RNGs used in the transpiler will be seeded from system entropy.
46
    seed: i64,
47
    /// The approximation degree a heurstic dial where 1.0 means no approximation (up to numerical
48
    /// tolerance) and 0.0 means the maximum approximation. A `NAN` value indicates that
49
    /// approximation is allowed up to the reported error rate for an operation in the target.
50
    approximation_degree: f64,
51
}
52

53
impl Default for TranspileOptions {
54
    fn default() -> Self {
8✔
55
        TranspileOptions {
8✔
56
            optimization_level: 2,
8✔
57
            seed: -1,
8✔
58
            approximation_degree: 1.0,
8✔
59
        }
8✔
60
    }
8✔
61
}
62

63
/// @ingroup QkTranspiler
64
///
65
/// Generate transpiler options defaults
66
///
67
/// This function generates a QkTranspileOptions with the default settings
68
/// This currently is ``optimization_level`` 2, no seed, and no approximation.
69
#[unsafe(no_mangle)]
70
#[cfg(feature = "cbinding")]
71
pub extern "C" fn qk_transpiler_default_options() -> TranspileOptions {
4✔
72
    TranspileOptions::default()
4✔
73
}
4✔
74

75
/// @ingroup QkTranspiler
76
/// Transpile a single circuit.
77
///
78
/// The Qiskit transpiler is a quantum circuit compiler that rewrites a given
79
/// input circuit to match the constraints of a QPU and optimizes the circuit
80
/// for execution. This function should only be used with circuits constructed
81
/// using Qiskit's C API. It makes assumptions on the circuit only using features exposed via C,
82
/// if you are in a mixed Python and C environment it is typically better to invoke the transpiler
83
/// via Python.
84
///
85
/// This function is multithreaded internally and will launch a thread pool
86
/// with threads equal to the number of CPUs reported by the operating system by default.
87
/// This will include logical cores on CPUs with simultaneous multithreading. You can tune the
88
/// number of threads with the ``RAYON_NUM_THREADS`` environment variable. For example, setting
89
/// ``RAYON_NUM_THREADS=4`` would limit the thread pool to 4 threads.
90
///
91
/// @param circuit A pointer to the circuit to run the transpiler on.
92
/// @param target A pointer to the target to compile the circuit for.
93
/// @param options A pointer to an options object that defines user options. If this is a null
94
///   pointer the default values will be used. See ``qk_transpile_default_options``
95
///   for more details on the default values.
96
/// @param result A pointer to the memory location of the transpiler result. On a successful
97
///   execution (return code 0) the output of the transpiler will be written to the pointer. The
98
///   members of the result struct are owned by the caller and you are responsible for freeing
99
///   the members using the respective free functions.
100
/// @param error A pointer to a pointer with an nul terminated string with an error description.
101
///   If the transpiler fails a pointer to the string with the error description will be written
102
///   to this pointer. That pointer needs to be freed with ``qk_str_free```. This can be a null
103
///   pointer in which case the error will not be written out.
104
///
105
/// @returns The return code for the transpiler, ``QkExitCode_Success`` means success and all
106
///   other values indicate an error.
107
///
108
/// # Safety
109
///
110
/// Behavior is undefined if ``circuit``, ``target``, or ``result``, are not valid, non-null
111
/// pointers to a ``QkCircuit``, ``QkTarget``, or ``QkTranspileResult`` respectively.
112
/// ``options`` must be a valid pointer a to a ``QkTranspileOptions`` or ``NULL`.
113
/// ``error`` must be a valid pointer to a ``char`` pointer or ``NULL``.
114
#[unsafe(no_mangle)]
115
#[cfg(feature = "cbinding")]
116
pub unsafe extern "C" fn qk_transpile(
24✔
117
    qc: *const CircuitData,
24✔
118
    target: *const Target,
24✔
119
    options: *const TranspileOptions,
24✔
120
    result: *mut TranspileResult,
24✔
121
    error: *mut *mut c_char,
24✔
122
) -> ExitCode {
24✔
123
    // SAFETY: Per documentation, the pointer is non-null and aligned.
124
    let qc = unsafe { const_ptr_as_ref(qc) };
24✔
125
    let target = unsafe { const_ptr_as_ref(target) };
24✔
126
    let options = if options.is_null() {
24✔
127
        &TranspileOptions::default()
4✔
128
    } else {
129
        // SAFETY: We checked the pointer is not null, then, per documentation, it is a valid
130
        // and aligned pointer.
131
        unsafe { const_ptr_as_ref(options) }
20✔
132
    };
133

134
    if !(0..=3u8).contains(&options.optimization_level) {
24✔
135
        panic!(
×
136
            "Invalid optimization level specified {}",
×
137
            options.optimization_level
138
        );
139
    }
24✔
140

141
    let seed = if options.seed < 0 {
24✔
142
        None
4✔
143
    } else {
144
        Some(options.seed as u64)
20✔
145
    };
146
    let approximation_degree = if options.approximation_degree.is_nan() {
24✔
147
        None
×
148
    } else {
149
        if !(0.0..=1.0).contains(&options.approximation_degree) {
24✔
NEW
150
            panic!(
×
NEW
151
                "Invalid value provided for approximation degree, only NAN or values between 0.0 and 1.0 inclusive are valid"
×
152
            );
153
        }
24✔
154
        Some(options.approximation_degree)
24✔
155
    };
156

157
    if let Some(target_qubits) = target.num_qubits {
24✔
158
        if target_qubits < qc.num_qubits() as u32 {
24✔
159
            if !error.is_null() {
×
160
                unsafe {
×
161
                    *error = CString::new(format!(
×
162
                        "Insufficient qubits in target: {}, the circuit uses {}",
×
163
                        target_qubits,
×
164
                        qc.num_qubits()
×
165
                    ))
×
166
                    .unwrap()
×
167
                    .into_raw();
×
168
                }
×
169
            }
×
170
            return ExitCode::TranspilerError;
×
171
        }
24✔
172
    }
×
173

174
    match transpile(
24✔
175
        qc,
24✔
176
        target,
24✔
177
        options.optimization_level.into(),
24✔
178
        approximation_degree,
24✔
179
        seed,
24✔
180
    ) {
24✔
181
        Ok(transpile_result) => {
24✔
182
            unsafe {
24✔
183
                *result = TranspileResult {
24✔
184
                    circuit: Box::into_raw(Box::new(transpile_result.0)),
24✔
185
                    layout: Box::into_raw(Box::new(transpile_result.1)),
24✔
186
                };
24✔
187
            }
24✔
188
            ExitCode::Success
24✔
189
        }
190
        Err(e) => {
×
191
            if !error.is_null() {
×
192
                unsafe {
×
193
                    // Right now we return a backtrace of the error. This at least gives a hint as to
×
194
                    // which pass failed when we have rust errors normalized we can actually have error
×
195
                    // messages which are user facing. But most likely this will be a PyErr and panic
×
196
                    // when trying to extract the string.
×
197
                    *error = CString::new(format!(
×
198
                        "Transpilation failed with this backtrace: {}",
×
199
                        e.backtrace()
×
200
                    ))
×
201
                    .unwrap()
×
202
                    .into_raw();
×
203
                }
×
204
            }
×
205
            ExitCode::TranspilerError
×
206
        }
207
    }
208
}
24✔
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

© 2026 Coveralls, Inc