Skip to content

Conversation

@denialhaag
Copy link
Member

@denialhaag denialhaag commented Dec 9, 2025

Description

This PR fully replaces pybind11 with nanobind. This change will allow us to ship stable ABI wheels, saving us PyPI space.

Checklist:

  • The pull request only contains commits that are focused and relevant to this change.
  • I have added appropriate tests that cover the new/changed functionality.
  • I have updated the documentation to reflect these changes.
  • I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.
  • I have added migration instructions to the upgrade guide (if needed).
  • The changes follow the project's style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks.
  • I have reviewed my own code changes.

@denialhaag denialhaag self-assigned this Dec 9, 2025
@denialhaag denialhaag added refactor Anything related to code refactoring c++ Anything related to C++ code python Anything related to Python code labels Dec 9, 2025
@codecov
Copy link

codecov bot commented Dec 9, 2025

Codecov Report

❌ Patch coverage is 97.46835% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
include/mqt-core/ir/operations/IfElseOperation.hpp 92.3% 1 Missing ⚠️
src/ir/operations/IfElseOperation.cpp 98.4% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
… bindings

Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
bindings/dd/register_dd_package.cpp (2)

50-58: nb::int_ in variant may still cause issues with std::set ordering.

The Control type alias uses std::variant<qc::Control, nb::int_>. Past review comments flagged that nb::int_ lacks well-defined C++ ordering semantics, which could cause issues when Controls (a std::set<Control>) attempts to order variants containing nb::int_ values.

The past comment indicated this was "addressed" by switching to std::uint32_t, but the current code still shows nb::int_. Please verify:

  1. If this is intentional and the ordering works correctly in practice
  2. Or if the change to std::uint32_t should still be applied
#!/bin/bash
# Check if there are other binding files that use std::uint32_t instead of nb::int_ for Control
rg "using Control = std::variant" bindings/ -A 1

471-476: Consider adding documentation clarifying identity() is package-agnostic.

As noted in past review comments, the class-level note warns about mixing DDs from different packages being undefined behavior, but identity() returns a special terminal that is package-independent. Consider adding a note to clarify this exception.

Suggested docstring enhancement
   dd.def_static("identity", &dd::Package::makeIdent,
                 R"pb(Create the DD for the identity matrix :math:`I`.

+Notes:
+    The returned DD is the global one-terminal (identity) and is package-agnostic.
+    It can safely be used with any DDPackage instance, even though other DDs must
+    not be mixed across different DDPackage objects.
+
 Returns:
     The DD for the identity matrix.)pb");
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf279dd and 5ff3329.

📒 Files selected for processing (23)
  • .clang-tidy
  • bindings/.clang-tidy
  • bindings/dd/register_dd.cpp
  • bindings/dd/register_dd_package.cpp
  • bindings/dd/register_matrix_dds.cpp
  • bindings/dd/register_vector_dds.cpp
  • bindings/fomac/fomac.cpp
  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
  • bindings/ir/symbolic/register_expression.cpp
  • bindings/na/CMakeLists.txt
  • bindings/na/register_fomac.cpp
  • include/mqt-core/ir/operations/IfElseOperation.hpp
  • noxfile.py
  • pyproject.toml
  • python/mqt/core/dd.pyi
  • python/mqt/core/fomac.pyi
  • python/mqt/core/ir/__init__.pyi
  • python/mqt/core/ir/operations.pyi
  • src/ir/operations/IfElseOperation.cpp
  • src/qdmi/dd/Device.cpp
  • src/qir/runtime/Runtime.cpp
  • test/qir/runtime/test_qir_runtime.cpp
🧰 Additional context used
🧠 Learnings (42)
📓 Common learnings
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:17.023Z
Learning: In the munich-quantum-toolkit/core repository, stub files (.pyi) are auto-generated by nanobind's stubgen tool and should not be manually modified for style preferences, as changes would be overwritten during regeneration.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:54.428Z
Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:00.998Z
Learning: In the munich-quantum-toolkit/core repository's nanobind bindings, use `.sig("...")` on parameter arguments that have vector or container defaults (e.g., `"sites"_a.sig("...") = std::vector<fomac::Session::Device::Site>{}`) to prevent exposing mutable defaults in the Python API, which would be flagged as a code smell by Python linters. This pattern is preferred over removing `.sig("...")` even though it shows `...` in the stub signature.
📚 Learning: 2025-12-17T11:32:53.683Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:83-86
Timestamp: 2025-12-17T11:32:53.683Z
Learning: In the mlir directory of the munich-quantum-toolkit/core repository, the clang-tidy configuration (mlir/.clang-tidy) prefers marking free functions as `static` over placing them in anonymous namespaces. The configuration enables `llvm-prefer-static-over-anonymous-namespace` and disables `misc-use-anonymous-namespace`. Types/classes should still use anonymous namespaces, but free functions should use explicit `static` linkage.

Applied to files:

  • bindings/.clang-tidy
  • .clang-tidy
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-11-24T10:19:41.147Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1326
File: python/mqt/core/__init__.py:22-22
Timestamp: 2025-11-24T10:19:41.147Z
Learning: In the munich-quantum-toolkit/core repository, Ruff is configured with 'ALL' rules enabled by default, and only specific rules are selectively disabled. When reviewing changes that enable previously-disabled rules (like PLC0415), noqa directives for those rules become necessary and should be retained.

Applied to files:

  • bindings/.clang-tidy
  • bindings/dd/register_dd_package.cpp
  • python/mqt/core/ir/operations.pyi
  • bindings/ir/register_quantum_computation.cpp
  • python/mqt/core/ir/__init__.pyi
📚 Learning: 2025-12-14T15:23:54.712Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: docs/conf.py:110-130
Timestamp: 2025-12-14T15:23:54.712Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the Ruff configuration has 'ALL' rules enabled with only specific rules disabled. PLR6301 (no-self-use) is active, so `# noqa: PLR6301` directives are necessary for methods that don't use self, even if Ruff reports RUF100 warnings suggesting the directive is unused.

Applied to files:

  • bindings/.clang-tidy
  • bindings/dd/register_dd_package.cpp
  • python/mqt/core/ir/operations.pyi
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-11-27T21:26:39.677Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qmap PR: 846
File: python/mqt/qmap/plugins/qiskit/sc/load_calibration.py:34-34
Timestamp: 2025-11-27T21:26:39.677Z
Learning: In the qmap project, the Ruff linter has the "PL" (pylint) rule category enabled, which includes PLC0415 (import-outside-top-level). Therefore, `# noqa: PLC0415` directives on lazy imports are appropriate and necessary, not unused.

Applied to files:

  • bindings/.clang-tidy
📚 Learning: 2025-12-15T01:59:17.023Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:17.023Z
Learning: In the munich-quantum-toolkit/core repository, stub files (.pyi) are auto-generated by nanobind's stubgen tool and should not be manually modified for style preferences, as changes would be overwritten during regeneration.

Applied to files:

  • noxfile.py
  • bindings/fomac/fomac.cpp
  • bindings/dd/register_matrix_dds.cpp
  • bindings/na/CMakeLists.txt
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-15T01:54:22.129Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.

Applied to files:

  • noxfile.py
  • pyproject.toml
  • python/mqt/core/dd.pyi
  • python/mqt/core/ir/operations.pyi
  • bindings/na/CMakeLists.txt
  • python/mqt/core/fomac.pyi
  • python/mqt/core/ir/__init__.pyi
📚 Learning: 2025-12-07T01:21:27.544Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.

Applied to files:

  • noxfile.py
  • pyproject.toml
  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
  • bindings/dd/register_vector_dds.cpp
  • bindings/fomac/fomac.cpp
  • bindings/dd/register_matrix_dds.cpp
  • python/mqt/core/ir/operations.pyi
  • bindings/dd/register_dd.cpp
  • bindings/na/CMakeLists.txt
  • bindings/ir/register_quantum_computation.cpp
  • python/mqt/core/fomac.pyi
  • python/mqt/core/ir/__init__.pyi
📚 Learning: 2025-12-13T20:08:45.549Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/qmap PR: 862
File: pyproject.toml:65-66
Timestamp: 2025-12-13T20:08:45.549Z
Learning: In the qmap project (pyproject.toml), maintain broad compatibility with dependencies across supported Python versions. Avoid artificially raising minimum version requirements unless there's a specific need (e.g., to guarantee binary wheel availability for certain Python versions, or to access required features). The goal is to keep the software as broadly compatible as possible with the rest of the ecosystem.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-10-10T08:09:54.528Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1246
File: bindings/CMakeLists.txt:0-0
Timestamp: 2025-10-10T08:09:54.528Z
Learning: In the Munich Quantum Toolkit (MQT) Core project, scikit-build-core is configured with `wheel.install-dir = "mqt/core"` in pyproject.toml, which automatically prefixes all CMake `DESTINATION` paths with `mqt/core/` during wheel installation. Therefore, CMake install destinations are relative to the `mqt/core` package namespace, not `site-packages`.

Applied to files:

  • pyproject.toml
  • bindings/na/CMakeLists.txt
📚 Learning: 2025-10-10T08:10:16.394Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1246
File: test/python/na/test_na_fomac.py:35-0
Timestamp: 2025-10-10T08:10:16.394Z
Learning: In the munich-quantum-toolkit/core repository, scikit-build-core is configured with `wheel.install-dir = "mqt/core"` in pyproject.toml, which means CMake `install()` commands with `DESTINATION <path>` install files relative to `mqt/core/` in the wheel, making them accessible via `files("mqt.core").joinpath("<path>")`.

Applied to files:

  • pyproject.toml
  • bindings/na/CMakeLists.txt
📚 Learning: 2025-10-11T19:39:32.050Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/debugger PR: 160
File: pyproject.toml:54-54
Timestamp: 2025-10-11T19:39:32.050Z
Learning: Qiskit packages use cp39-abi3 wheels (stable ABI) which are forward-compatible with Python 3.9+ including Python 3.14, even if the package classifiers don't explicitly list Python 3.14 support.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-10-09T22:15:59.924Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1246
File: pyproject.toml:340-341
Timestamp: 2025-10-09T22:15:59.924Z
Learning: Qiskit publishes ABI3 wheels (e.g., cp39-abi3) that are forward-compatible with newer Python versions including Python 3.14, so no explicit Python 3.14 wheels are required for qiskit to work on Python 3.14.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-10-13T00:03:08.078Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/debugger PR: 160
File: pyproject.toml:252-256
Timestamp: 2025-10-13T00:03:08.078Z
Learning: In uv's `override-dependencies`, multiple entries for the same package with different environment markers (or one without a marker and one with a specific marker) can coexist. uv correctly resolves these by applying the appropriate constraint based on the active Python version. For example, `["symengine>=0.11,<0.14", "symengine>=0.14.1; python_version >= '3.14'"]` is valid and will apply the second constraint on Python 3.14+.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-11-28T14:33:15.199Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1337
File: pyproject.toml:351-351
Timestamp: 2025-11-28T14:33:15.199Z
Learning: In the munich-quantum-toolkit/core repository, the dev dependency "ty==0.0.1a27" is intentionally pinned to an exact pre-release version. This dependency is used by the `ty-check` pre-commit hook (via `uv run --only-dev ty check`), and the exact pin ensures all developers run the same version, preventing unexpected issues from updates since ty is in alpha and changing rapidly.

Applied to files:

  • pyproject.toml
📚 Learning: 2025-12-15T01:54:18.630Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:18.630Z
Learning: In munich-quantum-toolkit/core, for C++ binding files under the bindings directory (any nested path), add Python docstrings directly in the binding code using the R"pb(...)pb" syntax. Do not maintain docstrings in stub files (.pyi); instead, keep stubs auto-generated by the script: bindings/generate-stubs.sh. This replaces the previous pybind11 approach where docstrings were kept in stubs. Ensure the binding code reflects accurate Python docstrings and that the stub generation script runs to refresh the .pyi files.

Applied to files:

  • bindings/na/register_fomac.cpp
  • bindings/ir/symbolic/register_expression.cpp
  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
  • bindings/dd/register_vector_dds.cpp
  • bindings/fomac/fomac.cpp
  • bindings/dd/register_matrix_dds.cpp
  • bindings/dd/register_dd.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-19T00:05:41.711Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:41.711Z
Learning: In nanobind bindings (munich-quantum-toolkit/core), lifetime management differs from pybind11. After migrating to nanobind, nb::keep_alive<nurse, patient>() does not exist. For methods that return objects which reference the parent’s internal state (e.g., Session::getDevices returning Device objects dependent on the Session), use nb::rv_policy::reference_internal when binding those methods. This ensures the parent (Session) stays alive while its children (Device) exist. Apply this pattern in binding code under bindings/ (e.g., bindings/fomac/fomac.cpp and similar) wherever return values depend on the parent.

Applied to files:

  • bindings/na/register_fomac.cpp
  • bindings/ir/symbolic/register_expression.cpp
  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
  • bindings/dd/register_vector_dds.cpp
  • bindings/fomac/fomac.cpp
  • bindings/dd/register_matrix_dds.cpp
  • bindings/dd/register_dd.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-21T22:35:00.998Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:00.998Z
Learning: In munich-quantum-toolkit/core, for nanobind bindings, when a parameter has a mutable default (e.g., a vector or container default), use .sig("...") on that parameter (e.g., some_arg.sig("...") = std::vector<...>{}) to prevent exposing mutable defaults in the Python API. This is preferred over removing .sig(...) since removing it would still show the default in the stub. Apply this pattern to similar binding parameters across the repository (bindings/**/, not just this file) to keep Python bindings safe from linter warnings and maintainable.

Applied to files:

  • bindings/na/register_fomac.cpp
  • bindings/ir/symbolic/register_expression.cpp
  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
  • bindings/dd/register_vector_dds.cpp
  • bindings/fomac/fomac.cpp
  • bindings/dd/register_matrix_dds.cpp
  • bindings/dd/register_dd.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-11-05T07:42:45.507Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/error_handling_test.cpp:118-194
Timestamp: 2025-11-05T07:42:45.507Z
Learning: In the munich-quantum-toolkit/core QDMI device API, session parameters can only be set before calling `device_session_init()`. Once a session is initialized, any attempt to set a parameter returns `QDMI_ERROR_BADSTATE`. Since `SessionGuard` (in test/qdmi/dd/helpers/test_utils.hpp) automatically initializes the session in its constructor, tests that need to verify session parameter setting behavior before initialization must allocate a separate uninitialized session rather than reusing the `SessionGuard`'s session.

Applied to files:

  • bindings/na/register_fomac.cpp
  • bindings/fomac/fomac.cpp
📚 Learning: 2025-12-07T09:10:31.836Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: src/qdmi/sc/Device.cpp:97-102
Timestamp: 2025-12-07T09:10:31.836Z
Learning: In the munich-quantum-toolkit/core repository, duplication of QDMI-related macros (such as IS_INVALID_ARGUMENT) across device implementations (e.g., in src/qdmi/sc/Device.cpp and src/qdmi/dd/Device.cpp) is acceptable as a temporary measure. The preferred long-term solution is to upstream these macros to the QDMI repository rather than creating local shared headers, so they can be reused across all dependent projects.

Applied to files:

  • bindings/na/register_fomac.cpp
  • bindings/dd/register_dd_package.cpp
  • bindings/fomac/fomac.cpp
  • src/qdmi/dd/Device.cpp
  • bindings/dd/register_dd.cpp
  • bindings/ir/register_quantum_computation.cpp
  • python/mqt/core/fomac.pyi
  • python/mqt/core/ir/__init__.pyi
📚 Learning: 2025-11-04T14:28:32.371Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_backend.py:0-0
Timestamp: 2025-11-04T14:28:32.371Z
Learning: In the munich-quantum-toolkit/core repository, at least one FoMaC device is always available during testing, so skip logic for missing devices in QDMI Qiskit backend tests is not necessary.

Applied to files:

  • bindings/na/register_fomac.cpp
  • bindings/fomac/fomac.cpp
📚 Learning: 2025-12-15T15:17:25.469Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:424-456
Timestamp: 2025-12-15T15:17:25.469Z
Learning: The Control class in munich-quantum-toolkit/core should be immutable (no setters for qubit and type_ properties) because Control objects are used in sets throughout the API (controls property, add_controls, remove_controls methods), and hashable+mutable objects in sets lead to incorrect lookups.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
  • bindings/ir/register_quantum_computation.cpp
  • python/mqt/core/ir/__init__.pyi
📚 Learning: 2025-12-14T17:02:02.997Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp:187-210
Timestamp: 2025-12-14T17:02:02.997Z
Learning: In the Flux dialect builder (mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp), the coding style relies on implicit conversion from Value to ValueRange in ctrl() calls (e.g., `ctrl(control, {}, ...)` instead of `ctrl(ValueRange{control}, ValueRange{}, ...)`). This pattern is used consistently throughout all macro-generated methods and should be maintained for consistency.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-08T12:44:05.883Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:60-70
Timestamp: 2025-12-08T12:44:05.883Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The RemoveTrivialCtrl pattern correctly only checks getNumPosControls() when determining if a CtrlOp should be removed.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
  • python/mqt/core/ir/operations.pyi
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-08T23:58:09.648Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:80-100
Timestamp: 2025-12-08T23:58:09.648Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), quartz.ctrl uses reference semantics and does not return values, unlike flux.ctrl which uses value semantics and returns transformed qubits. When inlining a GPhaseOp in the CtrlInlineGPhase pattern, it's correct to create POp operations for positive controls and erase the CtrlOp without collecting or replacing result values.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
  • python/mqt/core/ir/operations.pyi
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-08T23:16:20.680Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp:78-101
Timestamp: 2025-12-08T23:16:20.680Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The CtrlInlineGPhase canonicalization pattern correctly only checks getNumPosControls() and processes only positive controls when inlining a GPhaseOp.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-05T17:45:37.602Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1360
File: .github/workflows/reusable-mlir-tests.yml:40-43
Timestamp: 2025-12-05T17:45:37.602Z
Learning: In the munich-quantum-toolkit/core repository, patch releases of LLVM dependencies don't require documentation updates, changelog entries, or additional tests beyond what's validated by passing CI checks.

Applied to files:

  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-11-03T23:09:26.881Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1287
File: test/qdmi/dd/CMakeLists.txt:9-21
Timestamp: 2025-11-03T23:09:26.881Z
Learning: The CMake functions `generate_device_defs_executable` and `generate_prefixed_qdmi_headers` used in QDMI device test CMakeLists.txt files are provided by the external QDMI library (fetched via FetchContent from https://github.com/Munich-Quantum-Software-Stack/qdmi.git), specifically in the cmake/PrefixHandling.cmake module of the QDMI repository.

Applied to files:

  • bindings/fomac/fomac.cpp
📚 Learning: 2025-11-20T18:19:31.857Z
Learnt from: lsschmid
Repo: munich-quantum-toolkit/qmap PR: 832
File: src/hybridmap/HybridNeutralAtomMapper.cpp:1679-1715
Timestamp: 2025-11-20T18:19:31.857Z
Learning: In src/hybridmap/HybridNeutralAtomMapper.cpp, the compareSwapAndBridge and compareShuttlingAndFlyingAncilla methods intentionally use division by zero to produce infinity when distance reductions are zero or negative. This infinity value marks that option as highly unfavorable in cost comparisons, which is the intended behavior rather than a bug.

Applied to files:

  • bindings/dd/register_matrix_dds.cpp
📚 Learning: 2025-10-17T11:09:50.147Z
Learnt from: marcelwa
Repo: munich-quantum-toolkit/core PR: 1243
File: test/python/qdmi/qiskit/test_qdmi_qiskit_site_handling.py:162-173
Timestamp: 2025-10-17T11:09:50.147Z
Learning: For QDMI tests that reference a specific named device via fixture (e.g., "MQT NA Default QDMI Device"), it is acceptable to hard-code device-specific values such as zone counts and indices, as these tests are intentionally coupled to that device's structure and serve as structural invariant checks.

Applied to files:

  • src/qdmi/dd/Device.cpp
📚 Learning: 2025-12-15T01:59:08.167Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:08.167Z
Learning: In the munich-quantum-toolkit/core repository, all stub files (.pyi) generated by nanobind's stubgen should not be edited for style; any changes will be overwritten during regeneration. Treat these files as generated artifacts—make changes in the source (.py or interfaces) and re-run stubgen to update the .pyi files. This pattern applies to all .pyi files under python/mqt/core.

Applied to files:

  • python/mqt/core/dd.pyi
  • python/mqt/core/ir/operations.pyi
  • python/mqt/core/fomac.pyi
  • python/mqt/core/ir/__init__.pyi
📚 Learning: 2025-10-09T13:13:51.224Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:171-180
Timestamp: 2025-10-09T13:13:51.224Z
Learning: In MQT Core MLIR, UnitaryInterface operations guarantee 1-1 correspondence between input and output qubits in the same order. When cloning or modifying unitary operations (e.g., removing controls), this correspondence is maintained by construction, so yielding getAllInQubits() in else-branches matches the result types from the operation's outputs.

Applied to files:

  • python/mqt/core/ir/operations.pyi
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-08T14:55:43.899Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp:78-100
Timestamp: 2025-12-08T14:55:43.899Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp), GPhaseOp is a zero-target operation (global phase). When a CtrlOp wraps a GPhaseOp, it only has control qubits and no targets. The CtrlInlineGPhase canonicalization pattern correctly produces outputs only for the positive controls, not targets.

Applied to files:

  • python/mqt/core/ir/operations.pyi
📚 Learning: 2025-12-15T15:17:17.477Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:424-456
Timestamp: 2025-12-15T15:17:17.477Z
Learning: In python/mqt/core/ir/operations.pyi, mark the Control class as immutable: expose qubit and type_ as read-only attributes (no setters) so Control objects remain hashable and stable when used in sets (e.g., through controls, add_controls, remove_controls). Implement this by using a frozen dataclass or by defining properties with no setters and a consistent __hash__ that relies on qubit and type_. Do not provide mutating methods that modify qubit or type_. If mutability is needed for other fields, separate identity from state; ensure qubit and type_ are immutable.

Applied to files:

  • python/mqt/core/ir/operations.pyi
📚 Learning: 2025-12-08T23:44:44.157Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Operations/StandardGates/PhaseOp.cpp:0-0
Timestamp: 2025-12-08T23:44:44.157Z
Learning: In MLIR code (mlir/ directories), avoid using const qualifiers on core MLIR data types like Value, Type, Attribute, Operation*, Block*, Region*, etc. in function parameters and signatures. MLIR's design rationale explicitly discourages const for these types. See https://mlir.llvm.org/docs/Rationale/UsageOfConst/ for details.

Applied to files:

  • python/mqt/core/ir/operations.pyi
📚 Learning: 2025-12-21T22:35:00.998Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:00.998Z
Learning: In the munich-quantum-toolkit/core repository's nanobind bindings, use `.sig("...")` on parameter arguments that have vector or container defaults (e.g., `"sites"_a.sig("...") = std::vector<fomac::Session::Device::Site>{}`) to prevent exposing mutable defaults in the Python API, which would be flagged as a code smell by Python linters. This pattern is preferred over removing `.sig("...")` even though it shows `...` in the stub signature.

Applied to files:

  • python/mqt/core/ir/operations.pyi
  • python/mqt/core/fomac.pyi
  • python/mqt/core/ir/__init__.pyi
📚 Learning: 2025-12-05T15:57:39.701Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 3
File: lib/Conversion/CatalystQuantumToMQTOpt/CMakeLists.txt:22-25
Timestamp: 2025-12-05T15:57:39.701Z
Learning: The munich-quantum-toolkit projects (core and core-plugins-catalyst) use `file(GLOB_RECURSE ...)` patterns in CMakeLists.txt files to collect header files, following an established convention in the parent repository for consistency across the codebase.

Applied to files:

  • bindings/na/CMakeLists.txt
📚 Learning: 2025-11-01T15:57:31.153Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1283
File: src/qir/runtime/QIR.cpp:196-201
Timestamp: 2025-11-01T15:57:31.153Z
Learning: In the QIR runtime (src/qir/runtime/QIR.cpp), the PRX gate (__quantum__qis__prx__body) is an alias for the R gate (Phased X-Rotation) and should call runtime.apply<qc::R>(theta, phi, qubit), not runtime.apply<qc::RX>() which is a single-parameter rotation gate.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
  • python/mqt/core/ir/__init__.pyi
📚 Learning: 2025-10-09T13:20:11.483Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/test/Dialect/MQTOpt/Transforms/lift-measurements.mlir:269-288
Timestamp: 2025-10-09T13:20:11.483Z
Learning: In the MQT MLIR dialect, the `rz` gate should not be included in the `DIAGONAL_GATES` set for the `ReplaceBasisStateControlsWithIfPattern` because its operator matrix does not have the required shape | 1 0 | / | 0 x | for the targets-as-controls optimization. It is only included in `LiftMeasurementsAboveGatesPatterns` where the matrix structure requirement differs.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-10T02:20:01.189Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/QIR/Builder/QIRProgramBuilder.cpp:0-0
Timestamp: 2025-12-10T02:20:01.189Z
Learning: In QIRProgramBuilder::measure(Value, int64_t), the intentional design prevents duplicate measurements: the early return when `registerResultMap.find(key)` succeeds avoids generating multiple `mz` calls to the same classical bit index and ensures output recording contains only one entry per index. This implements an "override" semantic where repeated measurements to the same resultIndex reuse the cached pointer without additional side effects.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-19T00:05:54.428Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:54.428Z
Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.

Applied to files:

  • python/mqt/core/fomac.pyi
📚 Learning: 2025-10-07T15:30:42.946Z
Learnt from: MatthiasReumann
Repo: munich-quantum-toolkit/core PR: 1237
File: mlir/include/mlir/Dialect/MQTOpt/Transforms/Transpilation/Layout.h:219-231
Timestamp: 2025-10-07T15:30:42.946Z
Learning: In the Layout class for MLIR quantum routing (mlir/include/mlir/Dialect/MQTOpt/Transforms/Transpilation/Layout.h), the swap method intentionally does NOT swap the hw fields in QubitInfo. This is correct because SSA values represent quantum states at fixed hardware locations, and only their program index associations change during a SWAP gate. The hw field indicates where an SSA value physically resides and remains constant.

Applied to files:

  • python/mqt/core/ir/__init__.pyi
🧬 Code graph analysis (8)
bindings/na/register_fomac.cpp (1)
python/mqt/core/na/fomac.pyi (3)
  • width (38-39)
  • height (42-43)
  • origin (49-50)
src/ir/operations/IfElseOperation.cpp (1)
include/mqt-core/ir/operations/IfElseOperation.hpp (7)
  • IfElseOperation (40-43)
  • IfElseOperation (45-47)
  • IfElseOperation (49-49)
  • op (51-51)
  • op (93-94)
  • op (95-95)
  • op (166-166)
bindings/dd/register_vector_dds.cpp (2)
bindings/dd/register_dd.cpp (1)
  • getVector (38-38)
include/mqt-core/dd/Export.hpp (1)
  • export2Dot (337-339)
src/qdmi/dd/Device.cpp (3)
include/mqt-core/qdmi/Driver.hpp (1)
  • site (250-251)
src/qdmi/sc/Device.cpp (1)
  • site (247-247)
include/mqt-core/qdmi/dd/Device.hpp (1)
  • site (169-171)
python/mqt/core/dd.pyi (3)
python/mqt/core/ir/registers.pyi (4)
  • size (30-31)
  • size (34-34)
  • size (69-70)
  • size (73-73)
python/mqt/core/ir/__init__.pyi (3)
  • Permutation (18-87)
  • invert (189-190)
  • QuantumComputation (89-2068)
python/mqt/core/ir/operations.pyi (4)
  • Operation (373-531)
  • NonUnitaryOperation (669-689)
  • IfElseOperation (814-883)
  • invert (526-527)
python/mqt/core/ir/operations.pyi (5)
include/mqt-core/ir/operations/Operation.hpp (13)
  • i (173-173)
  • t (95-95)
  • t (95-95)
  • p (127-127)
  • p (127-127)
  • Operation (48-48)
  • Operation (49-49)
  • Operation (50-50)
  • Operation (55-55)
  • Operation (55-55)
  • targets (61-61)
  • controls (67-67)
  • parameter (78-78)
python/mqt/core/ir/symbolic.pyi (3)
  • name (24-25)
  • Expression (77-155)
  • Variable (12-31)
python/mqt/core/ir/registers.pyi (3)
  • name (20-21)
  • name (59-60)
  • ClassicalRegister (48-85)
src/ir/operations/StandardOperation.cpp (7)
  • StandardOperation (196-202)
  • StandardOperation (204-210)
  • StandardOperation (212-217)
  • StandardOperation (219-224)
  • StandardOperation (226-231)
  • StandardOperation (233-238)
  • StandardOperation (241-244)
include/mqt-core/ir/operations/IfElseOperation.hpp (3)
  • IfElseOperation (40-43)
  • IfElseOperation (45-47)
  • IfElseOperation (49-49)
python/mqt/core/fomac.pyi (2)
python/mqt/core/na/fomac.pyi (3)
  • Device (11-106)
  • t1 (87-88)
  • t2 (91-92)
python/mqt/core/ir/operations.pyi (2)
  • name (375-376)
  • Operation (373-531)
python/mqt/core/ir/__init__.pyi (3)
python/mqt/core/ir/operations.pyi (7)
  • controls (399-404)
  • controls (407-407)
  • Control (344-371)
  • targets (385-390)
  • targets (393-393)
  • name (375-376)
  • OpType (17-342)
python/mqt/core/ir/symbolic.pyi (4)
  • name (24-25)
  • variables (117-118)
  • Variable (12-31)
  • Expression (77-155)
python/mqt/core/ir/registers.pyi (4)
  • name (20-21)
  • name (59-60)
  • QuantumRegister (9-46)
  • ClassicalRegister (48-85)
🪛 Cppcheck (2.18.0)
bindings/na/register_fomac.cpp

[information] 11-11: Include file

(missingInclude)


[information] 12-12: Include file

(missingInclude)


[information] 13-13: Include file

(missingInclude)


[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[style] 38-38: The function 'registerFomac' is never used.

(unusedFunction)

bindings/ir/symbolic/register_expression.cpp

[information] 14-14: Include file

(missingIncludeSystem)


[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[style] 30-30: The function 'registerExpression' is never used.

(unusedFunction)

bindings/ir/register_permutation.cpp

[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[style] 52-52: The function 'registerPermutation' is never used.

(unusedFunction)

bindings/dd/register_dd_package.cpp

[information] 17-17: Include file

(missingInclude)


[information] 18-18: Include file

(missingInclude)


[information] 19-19: Include file

(missingInclude)


[information] 20-20: Include file

(missingInclude)


[information] 21-21: Include file

(missingInclude)


[information] 22-22: Include file

(missingInclude)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 32-32: Include file

(missingIncludeSystem)


[information] 33-33: Include file

(missingIncludeSystem)


[information] 34-34: Include file

(missingIncludeSystem)


[information] 35-35: Include file

(missingIncludeSystem)


[information] 36-36: Include file

(missingIncludeSystem)


[information] 37-37: Include file

(missingIncludeSystem)


[information] 38-38: Include file

(missingIncludeSystem)


[information] 39-39: Include file

(missingIncludeSystem)


[information] 40-40: Include file

(missingIncludeSystem)


[information] 41-41: Include file

(missingIncludeSystem)


[information] 42-42: Include file

(missingIncludeSystem)


[information] 43-43: Include file

(missingIncludeSystem)


[style] 136-136: The function 'registerDDPackage' is never used.

(unusedFunction)


[error] 458-458: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 647-647: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 667-667: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 832-832: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 853-853: Boolean value assigned to pointer.

(assignBoolToPointer)

src/ir/operations/IfElseOperation.cpp

[information] Limiting analysis of branches. Use --check-level=exhaustive to analyze all branches.

(normalCheckLevelMaxBranches)


[information] Limiting analysis of branches. Use --check-level=exhaustive to analyze all branches.

(normalCheckLevelMaxBranches)


[information] Limiting analysis of branches. Use --check-level=exhaustive to analyze all branches.

(normalCheckLevelMaxBranches)


[information] Limiting analysis of branches. Use --check-level=exhaustive to analyze all branches.

(normalCheckLevelMaxBranches)


[information] Limiting analysis of branches. Use --check-level=exhaustive to analyze all branches.

(normalCheckLevelMaxBranches)

bindings/dd/register_vector_dds.cpp

[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[error] 114-114: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 114-114: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 114-114: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 115-115: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 115-115: Boolean value assigned to pointer.

(assignBoolToPointer)


[style] 49-49: The function 'registerVectorDDs' is never used.

(unusedFunction)


[error] 140-140: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 140-140: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 141-141: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 141-141: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 141-141: Boolean value assigned to pointer.

(assignBoolToPointer)

bindings/fomac/fomac.cpp

[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[error] 34-34: syntax error

(syntaxError)

bindings/dd/register_matrix_dds.cpp

[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[error] 78-78: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 126-126: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 126-126: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 126-126: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 127-127: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 127-127: Boolean value assigned to pointer.

(assignBoolToPointer)


[style] 68-68: The function 'registerMatrixDDs' is never used.

(unusedFunction)


[error] 152-152: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 152-152: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 153-153: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 153-153: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 153-153: Boolean value assigned to pointer.

(assignBoolToPointer)

bindings/dd/register_dd.cpp

[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[error] 43-43: syntax error

(syntaxError)

bindings/ir/register_quantum_computation.cpp

[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 32-32: Include file

(missingIncludeSystem)


[information] 33-33: Include file

(missingIncludeSystem)


[information] 34-34: Include file

(missingIncludeSystem)


[information] 35-35: Include file

(missingIncludeSystem)


[information] 36-36: Include file

(missingIncludeSystem)


[information] 37-37: Include file

(missingIncludeSystem)


[information] 38-38: Include file

(missingIncludeSystem)


[information] 39-39: Include file

(missingIncludeSystem)


[information] 40-40: Include file

(missingIncludeSystem)


[style] 51-51: The function 'registerQuantumComputation' is never used.

(unusedFunction)


[error] 2008-2008: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 2179-2179: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 2199-2199: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 2226-2226: Boolean value assigned to pointer.

(assignBoolToPointer)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: 🚀 CD (windows-11-arm) / 🎡 windows-11-arm
  • GitHub Check: 🐍 Test (windows-2022) / 🐍 windows-2022
  • GitHub Check: 🐍 Test (ubuntu-24.04) / 🐍 ubuntu-24.04
  • GitHub Check: 🇨‌ Test 🏁 (windows-11-arm, msvc, Release) / 🏁 windows-11-arm msvc Release
  • GitHub Check: 🇨‌ Test 🐧 (ubuntu-24.04, gcc, Release) / 🐧 ubuntu-24.04 gcc Release
  • GitHub Check: 🇨‌ Test 🏁 (windows-2022, msvc, Debug) / 🏁 windows-2022 msvc Debug
  • GitHub Check: 🇨‌ Test 🏁 (windows-2022, msvc, Release) / 🏁 windows-2022 msvc Release
  • GitHub Check: 🇨‌ Coverage / 📈 Coverage
  • GitHub Check: 🐍⚛️ (windows-2022) / 🐍⚛️ windows-2022
  • GitHub Check: 🐍⚛️ (ubuntu-24.04) / 🐍⚛️ ubuntu-24.04

Signed-off-by: burgholzer <burgholzer@me.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ff3329 and cf79be3.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • bindings/dd/register_dd.cpp
  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
  • python/mqt/core/dd.pyi
  • src/qir/runtime/Runtime.cpp
🧰 Additional context used
🧠 Learnings (24)
📓 Common learnings
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:17.023Z
Learning: In the munich-quantum-toolkit/core repository, stub files (.pyi) are auto-generated by nanobind's stubgen tool and should not be manually modified for style preferences, as changes would be overwritten during regeneration.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:54.428Z
Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:08.572Z
Learning: In the munich-quantum-toolkit/core repository's nanobind bindings, use `.sig("...")` on parameter arguments that have vector or container defaults (e.g., `"sites"_a.sig("...") = std::vector<fomac::Session::Device::Site>{}`) to prevent exposing mutable defaults in the Python API, which would be flagged as a code smell by Python linters. This pattern is preferred over removing `.sig("...")` even though it shows `...` in the stub signature.
📚 Learning: 2025-12-15T01:54:22.129Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.

Applied to files:

  • CHANGELOG.md
  • python/mqt/core/dd.pyi
📚 Learning: 2025-10-14T14:37:38.047Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/yaqs PR: 212
File: CHANGELOG.md:12-15
Timestamp: 2025-10-14T14:37:38.047Z
Learning: In the munich-quantum-toolkit/yaqs project, changelog entries follow the template: "- $TITLE ([#$NUMBER]($URL)) ([**AUTHOR**](https://github.com/$AUTHOR))". Issue references should not be included in changelog entries; the PR number is sufficient for traceability.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-12-05T17:45:37.602Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1360
File: .github/workflows/reusable-mlir-tests.yml:40-43
Timestamp: 2025-12-05T17:45:37.602Z
Learning: In the munich-quantum-toolkit/core repository, patch releases of LLVM dependencies don't require documentation updates, changelog entries, or additional tests beyond what's validated by passing CI checks.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-12-01T11:00:40.342Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 1
File: CHANGELOG.md:18-18
Timestamp: 2025-12-01T11:00:40.342Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the CHANGELOG.md intentionally references the parent MQT Core repository's release notes (https://github.com/munich-quantum-toolkit/core/releases) because the plugin repository is based on work performed in the parent repository.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-12-15T01:54:18.630Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:18.630Z
Learning: In munich-quantum-toolkit/core, for C++ binding files under the bindings directory (any nested path), add Python docstrings directly in the binding code using the R"pb(...)pb" syntax. Do not maintain docstrings in stub files (.pyi); instead, keep stubs auto-generated by the script: bindings/generate-stubs.sh. This replaces the previous pybind11 approach where docstrings were kept in stubs. Ensure the binding code reflects accurate Python docstrings and that the stub generation script runs to refresh the .pyi files.

Applied to files:

  • bindings/dd/register_dd.cpp
  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-07T01:21:27.544Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.

Applied to files:

  • bindings/dd/register_dd.cpp
  • python/mqt/core/dd.pyi
  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-19T00:05:41.711Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:41.711Z
Learning: In nanobind bindings (munich-quantum-toolkit/core), lifetime management differs from pybind11. After migrating to nanobind, nb::keep_alive<nurse, patient>() does not exist. For methods that return objects which reference the parent’s internal state (e.g., Session::getDevices returning Device objects dependent on the Session), use nb::rv_policy::reference_internal when binding those methods. This ensures the parent (Session) stays alive while its children (Device) exist. Apply this pattern in binding code under bindings/ (e.g., bindings/fomac/fomac.cpp and similar) wherever return values depend on the parent.

Applied to files:

  • bindings/dd/register_dd.cpp
  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-07T09:10:31.836Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: src/qdmi/sc/Device.cpp:97-102
Timestamp: 2025-12-07T09:10:31.836Z
Learning: In the munich-quantum-toolkit/core repository, duplication of QDMI-related macros (such as IS_INVALID_ARGUMENT) across device implementations (e.g., in src/qdmi/sc/Device.cpp and src/qdmi/dd/Device.cpp) is acceptable as a temporary measure. The preferred long-term solution is to upstream these macros to the QDMI repository rather than creating local shared headers, so they can be reused across all dependent projects.

Applied to files:

  • bindings/dd/register_dd.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-21T22:35:00.998Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:00.998Z
Learning: In munich-quantum-toolkit/core, for nanobind bindings, when a parameter has a mutable default (e.g., a vector or container default), use .sig("...") on that parameter (e.g., some_arg.sig("...") = std::vector<...>{}) to prevent exposing mutable defaults in the Python API. This is preferred over removing .sig(...) since removing it would still show the default in the stub. Apply this pattern to similar binding parameters across the repository (bindings/**/, not just this file) to keep Python bindings safe from linter warnings and maintainable.

Applied to files:

  • bindings/dd/register_dd.cpp
  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-21T22:35:08.572Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:08.572Z
Learning: In the munich-quantum-toolkit/core repository's nanobind bindings, use `.sig("...")` on parameter arguments that have vector or container defaults (e.g., `"sites"_a.sig("...") = std::vector<fomac::Session::Device::Site>{}`) to prevent exposing mutable defaults in the Python API, which would be flagged as a code smell by Python linters. This pattern is preferred over removing `.sig("...")` even though it shows `...` in the stub signature.

Applied to files:

  • python/mqt/core/dd.pyi
📚 Learning: 2025-12-15T01:59:08.167Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:08.167Z
Learning: In the munich-quantum-toolkit/core repository, all stub files (.pyi) generated by nanobind's stubgen should not be edited for style; any changes will be overwritten during regeneration. Treat these files as generated artifacts—make changes in the source (.py or interfaces) and re-run stubgen to update the .pyi files. This pattern applies to all .pyi files under python/mqt/core.

Applied to files:

  • python/mqt/core/dd.pyi
📚 Learning: 2025-12-15T15:17:25.469Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:424-456
Timestamp: 2025-12-15T15:17:25.469Z
Learning: The Control class in munich-quantum-toolkit/core should be immutable (no setters for qubit and type_ properties) because Control objects are used in sets throughout the API (controls property, add_controls, remove_controls methods), and hashable+mutable objects in sets lead to incorrect lookups.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-14T17:02:02.997Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp:187-210
Timestamp: 2025-12-14T17:02:02.997Z
Learning: In the Flux dialect builder (mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp), the coding style relies on implicit conversion from Value to ValueRange in ctrl() calls (e.g., `ctrl(control, {}, ...)` instead of `ctrl(ValueRange{control}, ValueRange{}, ...)`). This pattern is used consistently throughout all macro-generated methods and should be maintained for consistency.

Applied to files:

  • bindings/ir/register_permutation.cpp
📚 Learning: 2025-12-08T12:44:05.883Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:60-70
Timestamp: 2025-12-08T12:44:05.883Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The RemoveTrivialCtrl pattern correctly only checks getNumPosControls() when determining if a CtrlOp should be removed.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-08T23:58:09.648Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:80-100
Timestamp: 2025-12-08T23:58:09.648Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), quartz.ctrl uses reference semantics and does not return values, unlike flux.ctrl which uses value semantics and returns transformed qubits. When inlining a GPhaseOp in the CtrlInlineGPhase pattern, it's correct to create POp operations for positive controls and erase the CtrlOp without collecting or replacing result values.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-08T23:16:20.680Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp:78-101
Timestamp: 2025-12-08T23:16:20.680Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The CtrlInlineGPhase canonicalization pattern correctly only checks getNumPosControls() and processes only positive controls when inlining a GPhaseOp.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-15T01:59:17.023Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:17.023Z
Learning: In the munich-quantum-toolkit/core repository, stub files (.pyi) are auto-generated by nanobind's stubgen tool and should not be manually modified for style preferences, as changes would be overwritten during regeneration.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-11-01T15:57:31.153Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1283
File: src/qir/runtime/QIR.cpp:196-201
Timestamp: 2025-11-01T15:57:31.153Z
Learning: In the QIR runtime (src/qir/runtime/QIR.cpp), the PRX gate (__quantum__qis__prx__body) is an alias for the R gate (Phased X-Rotation) and should call runtime.apply<qc::R>(theta, phi, qubit), not runtime.apply<qc::RX>() which is a single-parameter rotation gate.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-10-09T13:20:11.483Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/test/Dialect/MQTOpt/Transforms/lift-measurements.mlir:269-288
Timestamp: 2025-10-09T13:20:11.483Z
Learning: In the MQT MLIR dialect, the `rz` gate should not be included in the `DIAGONAL_GATES` set for the `ReplaceBasisStateControlsWithIfPattern` because its operator matrix does not have the required shape | 1 0 | / | 0 x | for the targets-as-controls optimization. It is only included in `LiftMeasurementsAboveGatesPatterns` where the matrix structure requirement differs.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-11-24T10:19:41.147Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1326
File: python/mqt/core/__init__.py:22-22
Timestamp: 2025-11-24T10:19:41.147Z
Learning: In the munich-quantum-toolkit/core repository, Ruff is configured with 'ALL' rules enabled by default, and only specific rules are selectively disabled. When reviewing changes that enable previously-disabled rules (like PLC0415), noqa directives for those rules become necessary and should be retained.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-14T15:23:54.712Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: docs/conf.py:110-130
Timestamp: 2025-12-14T15:23:54.712Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the Ruff configuration has 'ALL' rules enabled with only specific rules disabled. PLR6301 (no-self-use) is active, so `# noqa: PLR6301` directives are necessary for methods that don't use self, even if Ruff reports RUF100 warnings suggesting the directive is unused.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-12-10T02:20:01.189Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/QIR/Builder/QIRProgramBuilder.cpp:0-0
Timestamp: 2025-12-10T02:20:01.189Z
Learning: In QIRProgramBuilder::measure(Value, int64_t), the intentional design prevents duplicate measurements: the early return when `registerResultMap.find(key)` succeeds avoids generating multiple `mz` calls to the same classical bit index and ensures output recording contains only one entry per index. This implements an "override" semantic where repeated measurements to the same resultIndex reuse the cached pointer without additional side effects.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
📚 Learning: 2025-10-09T13:13:51.224Z
Learnt from: DRovara
Repo: munich-quantum-toolkit/core PR: 1108
File: mlir/lib/Dialect/MQTOpt/Transforms/ReplaceBasisStateControlsWithIfPattern.cpp:171-180
Timestamp: 2025-10-09T13:13:51.224Z
Learning: In MQT Core MLIR, UnitaryInterface operations guarantee 1-1 correspondence between input and output qubits in the same order. When cloning or modifying unitary operations (e.g., removing controls), this correspondence is maintained by construction, so yielding getAllInQubits() in else-branches matches the result types from the operation's outputs.

Applied to files:

  • bindings/ir/register_quantum_computation.cpp
🧬 Code graph analysis (3)
bindings/dd/register_dd.cpp (2)
bindings/dd/register_vector_dds.cpp (2)
  • getVector (37-46)
  • getVector (37-37)
bindings/dd/register_matrix_dds.cpp (2)
  • getMatrix (36-65)
  • getMatrix (36-37)
bindings/ir/register_permutation.cpp (1)
python/mqt/core/ir/__init__.pyi (4)
  • p (1055-1064)
  • apply (32-40)
  • apply (43-51)
  • r (1142-1153)
bindings/ir/register_quantum_computation.cpp (1)
python/mqt/core/ir/__init__.pyi (25)
  • i (526-534)
  • gphase (1821-1829)
  • invert (189-190)
  • ci (536-545)
  • x (558-566)
  • y (590-598)
  • h (654-662)
  • ch (664-673)
  • s (686-694)
  • t (750-758)
  • ct (760-769)
  • v (814-822)
  • p (1055-1064)
  • r (1142-1153)
  • u (1193-1210)
  • cu (1212-1231)
  • barrier (1879-1880)
  • barrier (1883-1888)
  • barrier (1891-1896)
  • if_ (1937-1955)
  • if_ (1958-1978)
  • if_ (1981-2001)
  • if_ (2004-2022)
  • if_ (2025-2045)
  • if_ (2048-2068)
🪛 Cppcheck (2.18.0)
src/qir/runtime/Runtime.cpp

[information] 13-13: Include file

(missingInclude)

bindings/dd/register_dd.cpp

[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[error] 43-43: syntax error

(syntaxError)

bindings/ir/register_permutation.cpp

[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[style] 50-50: The function 'registerPermutation' is never used.

(unusedFunction)

bindings/ir/register_quantum_computation.cpp

[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 32-32: Include file

(missingIncludeSystem)


[information] 33-33: Include file

(missingIncludeSystem)


[information] 34-34: Include file

(missingIncludeSystem)


[information] 35-35: Include file

(missingIncludeSystem)


[information] 36-36: Include file

(missingIncludeSystem)


[information] 37-37: Include file

(missingIncludeSystem)


[style] 48-48: The function 'registerQuantumComputation' is never used.

(unusedFunction)


[error] 2005-2005: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 2176-2176: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 2196-2196: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 2223-2223: Boolean value assigned to pointer.

(assignBoolToPointer)

🔇 Additional comments (24)
bindings/dd/register_dd.cpp (8)

22-25: LGTM! Nanobind includes are correctly structured.

The include headers are properly migrated from pybind11 to nanobind. The NOLINT comments appropriately suppress misc-include-cleaner warnings for STL binding headers that are needed for implicit type conversions.


37-41: LGTM! Type aliases are correctly defined.

The Vector and Matrix type aliases using nb::ndarray with numpy backend and appropriate dimensionality match the implementations in register_vector_dds.cpp and register_matrix_dds.cpp.


43-53: LGTM! Module initialization follows nanobind conventions.

The NB_MODULE macro, module import for mqt.core.ir, and registration calls are correctly structured. The static analysis syntax error on line 43 is a false positive—Cppcheck doesn't understand the nanobind macro.


55-81: LGTM! The sample function binding is well-documented.

The docstring comprehensively documents the function behavior, parameters, and return value. Based on learnings, docstrings are now added directly in C++ binding code using R"pb(...)pb" syntax.


83-108: LGTM! The simulate_statevector binding is correct.

Memory management is sound: the unique_ptr<dd::Package> is local to the lambda and destroyed after getVector returns. Since getVector creates an ndarray with capsule-owned data (per the relevant code snippet), the returned array safely owns its memory independent of the Package lifetime.


110-139: LGTM! The build_unitary binding is correct.

Same memory management pattern as simulate_statevector—the dd::Package is local and getMatrix returns an ndarray with capsule-owned data.


141-157: LGTM! Direct binding of dd::simulate.

The docstring appropriately documents the reference counting semantics for both initial_state and the return value, which is important for users managing DD lifetimes.


159-184: LGTM! The build_functionality binding is correct.

The lambda correctly delegates to either buildFunctionalityRecursive or buildFunctionality based on the recursive flag.

CHANGELOG.md (1)

291-291: LGTM! PR link reference added correctly.

The link definition follows the established format and is properly sorted by PR number.

bindings/ir/register_quantum_computation.cpp (1)

48-2243: LGTM! Excellent nanobind migration.

The migration from pybind11 to nanobind has been completed successfully. All previous review comments have been addressed:

✅ Lambda captures are safe (captured by value)
✅ Docstrings are accurate and embedded in C++ bindings
✅ Type hints properly specified with nb::sig
✅ Previous typos and bugs have been fixed
✅ Consistent binding patterns throughout
✅ Comprehensive documentation with LaTeX math

The code follows nanobind best practices and maintains consistency across all operation bindings.

Note on static analysis: The cppcheck warnings about "Boolean value assigned to pointer" (lines 2005, 2176, 2196, 2223) are false positives—these are nanobind's argument binding syntax, not actual pointer assignments.

Based on learnings, this file correctly embeds docstrings in the C++ binding code using R"pb(...)pb" syntax, and stub files are auto-generated by the bindings/generate-stubs.sh script.

python/mqt/core/dd.pyi (6)

20-101: VectorDD class looks well-structured.

The class provides a clean API for vector decision diagrams with proper type annotations using Annotated[NDArray[np.complex128], {"shape": ...}]. The docstrings are comprehensive and correctly document the methods.

Minor note: Line 71 (colored: Whether to use colored edge weights) is missing a trailing period, while line 96 has one. Since this is an auto-generated stub file, this would need to be fixed in the C++ binding docstrings and regenerated via bindings/generate-stubs.sh. Based on learnings, stub files should not be edited directly.


103-197: MatrixDD class is well-implemented.

The class provides symmetric API to VectorDD for matrix decision diagrams. The is_identity method with up_to_global_phase parameter is a useful addition. The previously flagged backtick mismatch issue at line 133 has been fixed.


199-770: DDPackage class provides comprehensive DD management API.

The class is well-documented with clear separation of concerns:

  • State and gate creation methods with proper precondition documentation
  • Memory management methods (inc_ref_*, dec_ref_*, garbage_collect) with clear notes about caller responsibilities
  • Arithmetic operations with explicit notes about reference count management
  • The Notes: sections consistently document when reference count management is automatic vs manual

The previously flagged double period issue (line 355) and the expectation value math (lines 698-712) have been confirmed as addressed/correct.


772-799: BasisStates enum is correctly defined.

The LaTeX formatting issues from previous reviews have been fixed. All docstrings now properly use raw strings with correct \rangle syntax for the computational and superposition basis states.


835-859: Cross-reference issue from previous review has been fixed.

The docstrings now correctly reference :meth:~mqt.core.dd.VectorDD.get_vector (line 837) and `:meth:`~mqt.core.dd.MatrixDD.get_matrix (line 859) instead of the non-existent Vector and Matrix classes that were flagged in the previous review.


801-908: Module-level functions are well-documented with clear usage guidance.

The functions provide a good API design:

  • sample and simulate_statevector are convenience functions for common use cases
  • simulate and build_functionality provide lower-level DD-based operations for advanced users
  • Documentation clearly explains when each function is appropriate and what limitations apply (e.g., measurement support, memory considerations)
  • The Notes: sections properly guide users to more efficient alternatives for large quantum computations
bindings/ir/register_permutation.cpp (5)

35-45: Excellent validation helper!

The nbIntToQubit helper correctly validates both negative and out-of-range indices before converting to qc::Qubit. This addresses the previous critical concerns about wraparound.


61-74: Dict constructor correctly validates indices.

The constructor properly validates both keys and values using nbIntToQubit, preventing negative or out-of-range indices from entering the permutation. This addresses previous concerns.


147-154: Iterator correctly keeps permutation alive.

The __iter__ binding now includes nb::keep_alive<0, 1>(), ensuring the Permutation object remains alive while its iterator is in use. This matches the pattern used in items() and prevents potential use-after-free issues.


76-96: Apply methods correctly migrated to nanobind.

The apply overloads use nb::overload_cast appropriately for the const-qualified methods, and the inline docstrings follow the project's nanobind migration pattern.


50-199: Well-executed nanobind migration with comprehensive docstrings.

The migration from pybind11 to nanobind is well-structured:

  • ✅ Previous critical issues addressed (negative validation helper, KeyError semantics, iterator keep-alive)
  • ✅ Docstrings correctly placed inline in C++ per project standards
  • ✅ Proper use of nanobind idioms (nb::overload_cast, nb::self, nb::sig)
  • ✅ Type safety with nb::typed<nb::dict, nb::int_, nb::int_>

The one remaining issue is the item access methods not using the nbIntToQubit validation helper (see separate comment).

Based on learnings, docstrings are now in C++ binding code and stubs are auto-generated.

src/qir/runtime/Runtime.cpp (3)

13-13: LGTM: Include addition is necessary for type cast.

The new include provides the dd::Qubit type definition required for the explicit cast on line 94.


103-103: Remove concern - namespace removal is correct and intentional.

The makeZeroState call at line 103 correctly relies on ADL (Argument-Dependent Lookup) for function resolution. Since ADL looks up unqualified function names in the namespaces of their arguments, the second argument *dd of type dd::Package& ensures the dd namespace is searched, where makeZeroState is declared. The change is intentional (only one call modified), compiles successfully, and passes CI.


94-94: Explicit cast is type-safe; verify dd::Qubit range to prevent silent truncation.

The explicit cast to dd::Qubit improves type safety. dd::Qubit is defined as std::uint16_t, which can represent qubit indices 0–65535. The cast at line 94 converts a std::uint64_t value (d) to this 16-bit type—a narrowing conversion that could silently truncate if d exceeds this range. The DDDefinitions documentation acknowledges this limitation, noting that std::uint16_t can address up to 65536 qubits, and suggests increasing to std::uint32_t if more qubits are needed. While current quantum simulators operate well within this limit, consider adding a runtime assertion or comment documenting this constraint to prevent silent data loss in future use cases.

Signed-off-by: burgholzer <burgholzer@me.com>
… and clarity

Signed-off-by: burgholzer <burgholzer@me.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
bindings/dd/register_dd_package.cpp (1)

17-17: Remove unused include ir/Definitions.hpp.

This include was flagged by the linter as unused and marked as addressed in previous review rounds, but the line is still present in the code. The file doesn't directly use symbols from Definitions.hpp.

🔎 Proposed fix
-#include "ir/Definitions.hpp"

Based on learnings, the stubgen tool auto-generates .pyi files, so this cleanup won't affect stub files.

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf79be3 and 0e7be5d.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • bindings/dd/register_dd_package.cpp
  • bindings/ir/register_permutation.cpp
🧰 Additional context used
🧠 Learnings (18)
📓 Common learnings
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:9-16
Timestamp: 2025-12-15T01:59:17.023Z
Learning: In the munich-quantum-toolkit/core repository, stub files (.pyi) are auto-generated by nanobind's stubgen tool and should not be manually modified for style preferences, as changes would be overwritten during regeneration.
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:54.428Z
Learning: In the munich-quantum-toolkit/core repository after migrating to nanobind, lifetime management differs from pybind11: `nb::keep_alive<nurse, patient>()` does not exist in nanobind. Instead, use `nb::rv_policy::reference_internal` when binding methods that return objects referencing internal state of the parent object (e.g., Session::getDevices returning Device objects that depend on the Session). This tells nanobind to keep the parent alive while children exist.
📚 Learning: 2025-12-15T01:54:22.129Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:22.129Z
Learning: In the munich-quantum-toolkit/core repository, after migrating to nanobind, docstrings for Python bindings are now added directly in the C++ binding code (using R"pb(...)pb" syntax) and stub files (.pyi) are auto-generated using the `bindings/generate-stubs.sh` script. This replaces the previous pybind11 approach where docstrings were manually maintained in stub files.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-10-14T14:37:38.047Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/yaqs PR: 212
File: CHANGELOG.md:12-15
Timestamp: 2025-10-14T14:37:38.047Z
Learning: In the munich-quantum-toolkit/yaqs project, changelog entries follow the template: "- $TITLE ([#$NUMBER]($URL)) ([**AUTHOR**](https://github.com/$AUTHOR))". Issue references should not be included in changelog entries; the PR number is sufficient for traceability.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-12-05T17:45:37.602Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1360
File: .github/workflows/reusable-mlir-tests.yml:40-43
Timestamp: 2025-12-05T17:45:37.602Z
Learning: In the munich-quantum-toolkit/core repository, patch releases of LLVM dependencies don't require documentation updates, changelog entries, or additional tests beyond what's validated by passing CI checks.

Applied to files:

  • CHANGELOG.md
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-01T11:00:40.342Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 1
File: CHANGELOG.md:18-18
Timestamp: 2025-12-01T11:00:40.342Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the CHANGELOG.md intentionally references the parent MQT Core repository's release notes (https://github.com/munich-quantum-toolkit/core/releases) because the plugin repository is based on work performed in the parent repository.

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-12-15T01:54:18.630Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/dd/register_matrix_dds.cpp:64-109
Timestamp: 2025-12-15T01:54:18.630Z
Learning: In munich-quantum-toolkit/core, for C++ binding files under the bindings directory (any nested path), add Python docstrings directly in the binding code using the R"pb(...)pb" syntax. Do not maintain docstrings in stub files (.pyi); instead, keep stubs auto-generated by the script: bindings/generate-stubs.sh. This replaces the previous pybind11 approach where docstrings were kept in stubs. Ensure the binding code reflects accurate Python docstrings and that the stub generation script runs to refresh the .pyi files.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-07T01:21:27.544Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: bindings/fomac/fomac.cpp:227-264
Timestamp: 2025-12-07T01:21:27.544Z
Learning: In the munich-quantum-toolkit/core repository, docstrings for Python bindings are added to the corresponding stub files (.pyi) rather than directly in the pybind11 C++ bindings code. This practice may change if the project adopts nanobind with automatic stub generation.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-21T22:35:00.998Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:348-364
Timestamp: 2025-12-21T22:35:00.998Z
Learning: In munich-quantum-toolkit/core, for nanobind bindings, when a parameter has a mutable default (e.g., a vector or container default), use .sig("...") on that parameter (e.g., some_arg.sig("...") = std::vector<...>{}) to prevent exposing mutable defaults in the Python API. This is preferred over removing .sig(...) since removing it would still show the default in the stub. Apply this pattern to similar binding parameters across the repository (bindings/**/, not just this file) to keep Python bindings safe from linter warnings and maintainable.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-19T00:05:41.711Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1383
File: bindings/fomac/fomac.cpp:111-116
Timestamp: 2025-12-19T00:05:41.711Z
Learning: In nanobind bindings (munich-quantum-toolkit/core), lifetime management differs from pybind11. After migrating to nanobind, nb::keep_alive<nurse, patient>() does not exist. For methods that return objects which reference the parent’s internal state (e.g., Session::getDevices returning Device objects dependent on the Session), use nb::rv_policy::reference_internal when binding those methods. This ensures the parent (Session) stays alive while its children (Device) exist. Apply this pattern in binding code under bindings/ (e.g., bindings/fomac/fomac.cpp and similar) wherever return values depend on the parent.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-15T15:17:25.469Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1383
File: python/mqt/core/ir/operations.pyi:424-456
Timestamp: 2025-12-15T15:17:25.469Z
Learning: The Control class in munich-quantum-toolkit/core should be immutable (no setters for qubit and type_ properties) because Control objects are used in sets throughout the API (controls property, add_controls, remove_controls methods), and hashable+mutable objects in sets lead to incorrect lookups.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-14T17:02:02.997Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp:187-210
Timestamp: 2025-12-14T17:02:02.997Z
Learning: In the Flux dialect builder (mlir/lib/Dialect/Flux/Builder/FluxProgramBuilder.cpp), the coding style relies on implicit conversion from Value to ValueRange in ctrl() calls (e.g., `ctrl(control, {}, ...)` instead of `ctrl(ValueRange{control}, ValueRange{}, ...)`). This pattern is used consistently throughout all macro-generated methods and should be maintained for consistency.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-08T12:44:05.883Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:60-70
Timestamp: 2025-12-08T12:44:05.883Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The RemoveTrivialCtrl pattern correctly only checks getNumPosControls() when determining if a CtrlOp should be removed.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-08T23:58:09.648Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp:80-100
Timestamp: 2025-12-08T23:58:09.648Z
Learning: In the Quartz dialect (mlir/lib/Dialect/Quartz/IR/Modifiers/CtrlOp.cpp), quartz.ctrl uses reference semantics and does not return values, unlike flux.ctrl which uses value semantics and returns transformed qubits. When inlining a GPhaseOp in the CtrlInlineGPhase pattern, it's correct to create POp operations for positive controls and erase the CtrlOp without collecting or replacing result values.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-08T23:16:20.680Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp:78-101
Timestamp: 2025-12-08T23:16:20.680Z
Learning: In the Flux dialect (mlir/lib/Dialect/Flux/IR/Modifiers/CtrlOp.cpp), negative controls are not supported at the current stage. The CtrlInlineGPhase canonicalization pattern correctly only checks getNumPosControls() and processes only positive controls when inlining a GPhaseOp.

Applied to files:

  • bindings/ir/register_permutation.cpp
  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-11-24T10:19:41.147Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1326
File: python/mqt/core/__init__.py:22-22
Timestamp: 2025-11-24T10:19:41.147Z
Learning: In the munich-quantum-toolkit/core repository, Ruff is configured with 'ALL' rules enabled by default, and only specific rules are selectively disabled. When reviewing changes that enable previously-disabled rules (like PLC0415), noqa directives for those rules become necessary and should be retained.

Applied to files:

  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-14T15:23:54.712Z
Learnt from: flowerthrower
Repo: munich-quantum-toolkit/core-plugins-catalyst PR: 23
File: docs/conf.py:110-130
Timestamp: 2025-12-14T15:23:54.712Z
Learning: In the munich-quantum-toolkit/core-plugins-catalyst repository, the Ruff configuration has 'ALL' rules enabled with only specific rules disabled. PLR6301 (no-self-use) is active, so `# noqa: PLR6301` directives are necessary for methods that don't use self, even if Ruff reports RUF100 warnings suggesting the directive is unused.

Applied to files:

  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-17T11:32:53.683Z
Learnt from: denialhaag
Repo: munich-quantum-toolkit/core PR: 1264
File: mlir/lib/Dialect/MQTOpt/Transforms/Transpilation/LayeredUnit.cpp:83-86
Timestamp: 2025-12-17T11:32:53.683Z
Learning: In the mlir directory of the munich-quantum-toolkit/core repository, the clang-tidy configuration (mlir/.clang-tidy) prefers marking free functions as `static` over placing them in anonymous namespaces. The configuration enables `llvm-prefer-static-over-anonymous-namespace` and disables `misc-use-anonymous-namespace`. Types/classes should still use anonymous namespaces, but free functions should use explicit `static` linkage.

Applied to files:

  • bindings/dd/register_dd_package.cpp
📚 Learning: 2025-12-07T09:10:31.836Z
Learnt from: burgholzer
Repo: munich-quantum-toolkit/core PR: 1355
File: src/qdmi/sc/Device.cpp:97-102
Timestamp: 2025-12-07T09:10:31.836Z
Learning: In the munich-quantum-toolkit/core repository, duplication of QDMI-related macros (such as IS_INVALID_ARGUMENT) across device implementations (e.g., in src/qdmi/sc/Device.cpp and src/qdmi/dd/Device.cpp) is acceptable as a temporary measure. The preferred long-term solution is to upstream these macros to the QDMI repository rather than creating local shared headers, so they can be reused across all dependent projects.

Applied to files:

  • bindings/dd/register_dd_package.cpp
🧬 Code graph analysis (1)
bindings/ir/register_permutation.cpp (1)
python/mqt/core/ir/__init__.pyi (4)
  • p (1055-1064)
  • apply (32-40)
  • apply (43-51)
  • r (1142-1153)
🪛 Cppcheck (2.18.0)
bindings/ir/register_permutation.cpp

[information] 15-15: Include file

(missingIncludeSystem)


[information] 16-16: Include file

(missingIncludeSystem)


[information] 17-17: Include file

(missingIncludeSystem)


[information] 18-18: Include file

(missingIncludeSystem)


[information] 19-19: Include file

(missingIncludeSystem)


[information] 20-20: Include file

(missingIncludeSystem)


[information] 21-21: Include file

(missingIncludeSystem)


[information] 22-22: Include file

(missingIncludeSystem)


[information] 23-23: Include file

(missingIncludeSystem)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[style] 50-50: The function 'registerPermutation' is never used.

(unusedFunction)

bindings/dd/register_dd_package.cpp

[information] 17-17: Include file

(missingInclude)


[information] 18-18: Include file

(missingInclude)


[information] 19-19: Include file

(missingInclude)


[information] 20-20: Include file

(missingInclude)


[information] 21-21: Include file

(missingInclude)


[information] 22-22: Include file

(missingInclude)


[information] 24-24: Include file

(missingIncludeSystem)


[information] 25-25: Include file

(missingIncludeSystem)


[information] 26-26: Include file

(missingIncludeSystem)


[information] 27-27: Include file

(missingIncludeSystem)


[information] 28-28: Include file

(missingIncludeSystem)


[information] 29-29: Include file

(missingIncludeSystem)


[information] 30-30: Include file

(missingIncludeSystem)


[information] 31-31: Include file

(missingIncludeSystem)


[information] 32-32: Include file

(missingIncludeSystem)


[information] 33-33: Include file

(missingIncludeSystem)


[information] 34-34: Include file

(missingIncludeSystem)


[information] 35-35: Include file

(missingIncludeSystem)


[information] 36-36: Include file

(missingIncludeSystem)


[information] 37-37: Include file

(missingIncludeSystem)


[information] 38-38: Include file

(missingIncludeSystem)


[information] 39-39: Include file

(missingIncludeSystem)


[information] 40-40: Include file

(missingIncludeSystem)


[style] 103-103: The function 'registerDDPackage' is never used.

(unusedFunction)


[error] 425-425: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 635-635: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 655-655: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 820-820: Boolean value assigned to pointer.

(assignBoolToPointer)


[error] 841-841: Boolean value assigned to pointer.

(assignBoolToPointer)

🔇 Additional comments (6)
CHANGELOG.md (1)

28-30: Changelog entries are well-formatted and the previous capitalization inconsistency has been resolved.

The three new entries for the nanobind migration, stable ABI wheels, and mqt.core.na submodule are properly formatted with consistent capitalization, appropriate emojis, PR references, and author attributions. The PR link reference has been correctly added to the links section.

Also applies to: 291-291

bindings/ir/register_permutation.cpp (5)

35-45: LGTM! Robust input validation for qubit indices.

The nbIntToQubit helper correctly validates negative indices and overflow before converting to qc::Qubit. This addresses the validation concerns from previous reviews and is consistently applied throughout the bindings.


61-74: LGTM! Dictionary constructor with proper validation.

The __init__ from dict correctly validates both keys and values using nbIntToQubit, ensuring negative indices and overflow are caught. The use of placement new and move semantics is appropriate for nanobind constructors.


116-148: LGTM! Item mutation methods with proper validation and error handling.

Both __setitem__ and __delitem__ correctly validate inputs via nbIntToQubit. The __delitem__ implementation properly raises KeyError with a descriptive message for missing keys, matching Python's MutableMapping semantics.


50-100: LGTM! Class binding setup and methods follow nanobind best practices.

The class binding, constructors, and methods (apply, clear) are correctly implemented:

  • Proper nb::class_ with descriptive signature and docstring
  • apply overloads use nb::overload_cast with nb::const_ for const member functions
  • Clear docstrings using raw string literals
  • Default constructor appropriately bound

Based on learnings: docstrings are now directly in C++ binding code (R"pb(...)pb" syntax) with stub files auto-generated.


150-204: LGTM! Remaining bindings complete the MutableMapping interface.

The remaining bindings are correctly implemented:

  • __len__ bound to size()
  • Equality operators using nb::self with explicit signatures
  • __str__ and __repr__ with proper formatting
  • Implicit conversion from nb::dict to qc::Permutation

All components work together to provide a complete Python MutableMapping[int, int] interface.

Signed-off-by: burgholzer <burgholzer@me.com>
Copy link
Member

@burgholzer burgholzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @denialhaag for all the work here.
I invested some time on my own to polish this further.
Most importantly, I streamlined the stub generation workflow and removed the std::variant hack for dealing with controls.

This should be good to go now. I am waiting for #1397 to go in before merging the main branch into this one here one last time.

# Conflicts:
#	.github/workflows/cd.yml
#	.github/workflows/ci.yml
#	.github/workflows/upstream.yml
#	uv.lock
Signed-off-by: burgholzer <burgholzer@me.com>
@burgholzer burgholzer merged commit aba0f0e into main Dec 22, 2025
43 checks passed
@burgholzer burgholzer deleted the nanobind branch December 22, 2025 08:59
burgholzer added a commit that referenced this pull request Jan 8, 2026
## Description

This PR fully replaces `pybind11` with `nanobind`. This change will
allow us to ship stable ABI wheels, saving us PyPI space.

## Checklist:

- [x] The pull request only contains commits that are focused and
relevant to this change.
- [x] ~I have added appropriate tests that cover the new/changed
functionality.~
- [x] I have updated the documentation to reflect these changes.
- [x] I have added entries to the changelog for any noteworthy
additions, changes, fixes, or removals.
- [x] I have added migration instructions to the upgrade guide (if
needed).
- [x] The changes follow the project's style guidelines and introduce no
new warnings.
- [x] The changes are fully tested and pass the CI checks.
- [x] I have reviewed my own code changes.

---------

Signed-off-by: Daniel Haag <121057143+denialhaag@users.noreply.github.com>
Signed-off-by: burgholzer <burgholzer@me.com>
Co-authored-by: burgholzer <burgholzer@me.com>
(cherry picked from commit aba0f0e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Anything related to C++ code packaging Anything related to Python packaging python Anything related to Python code refactor Anything related to code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants