Skip to content

♻️ Return owned errors at native boundaries - #2545

Open
burgholzer wants to merge 2 commits into
mainfrom
codex/fix-mlir-exception-boundaries
Open

burgholzer wants to merge 2 commits into
mainfrom
codex/fix-mlir-exception-boundaries

Conversation

@burgholzer

@burgholzer burgholzer commented Sep 12, 2026 •

Copy link
Copy Markdown
Member

🤖 AI text below 🤖

Description

Return owned llvm::Expected<T> and llvm::Error for recoverable native failures. Factories replace fallible constructors; infallible operations retain values or void, and successful absence uses optional<T>. MLIR keeps context diagnostics, captured as owned errors at native compiler boundaries. Python preserves exception categories through a common nanobind adapter; QDMI C interfaces preserve status codes and local logging.

Based directly on main after #2839, #2840, and #2846 merged. This PR contains the remaining DD, QDMI, compiler, and QIR error APIs, their consumers, and exception/RTTI policy. It preserves DD parsing grammar and numeric error categories, uses the merged LLVM I/O paths, and adds no shared diagnostic runtime or forced shared-Core build. Driver allocation recovery and worker host exception boundaries remain where needed.

DD algorithms, the QDMI C++ client, and benchmarks link statically into consumers so LLVM error type IDs stay with their handlers. Python shares only the canonical DD constant objects. On MSVC, DD retains exception support for std::regex because _HAS_EXCEPTIONS changes STL exception vtable layouts. QIR floating-point records use nonthrowing shortest formatting.

Validation

  • Clang 23 / LLVM 23.1 release with ThinLTO and mold: 4,108 native tests passed. Python 3.14: 2,090 tests passed, including QIR runner integration.
  • The formerly failing DD target passes all 224 tests in both Clang Debug and GCC coverage builds. A standalone Debug probe reproduced the missing-RTTI link failure before the fix.
  • A private-LLVM shared-library probe reproduces the cross-image error abort; the same-image variant preserves the error message. Symbol inspection confirms Python's DD shared library exports only its three constants.
  • The floating-point record regression rejects a six-digit precision mutation. Exact checks retain signed zero, precision, extreme finite values, infinity, and NaN.
  • Executable Sphinx/Doxygen documentation, generated-link checks, whole-file C++ lint, and repository lint passed. Generated binding interfaces are unchanged.

Commits are signed and verified. Windows/macOS execution still requires hosted validation; no hardware jobs or performance claims.

AI assistance: Codex implemented and locally validated the refactor. Human review remains required.

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.
  • 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.

If PR contains AI-assisted content:

  • Any agent that created, edited, or submitted GitHub content was explicitly authorized for that scope, as required by our AI Usage Guidelines.
  • Every agent-authored or agent-edited public text body begins with the visible disclosure 🤖 *AI text below* 🤖 (titles are exempt).
  • I have disclosed AI assistance in the PR description.
  • I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

@burgholzer burgholzer added fix Fix for something that isn't working c++ Anything related to C++ code MLIR Anything related to MLIR QDMI Anything related to QDMI labels Sep 12, 2026
@burgholzer burgholzer self-assigned this Sep 12, 2026
@burgholzer
burgholzer force-pushed the codex/fix-mlir-exception-boundaries branch from 18f186e to e95a1ee Compare September 12, 2026 11:05
@burgholzer burgholzer added this to the v4.1.0 - QDMI 1.4 / MQSF milestone Sep 12, 2026
@mergify mergify Bot added the conflict label Sep 12, 2026
@burgholzer
burgholzer force-pushed the codex/fix-mlir-exception-boundaries branch from c5bdf1b to 46025a6 Compare September 12, 2026 11:55
@mergify mergify Bot removed the conflict label Sep 12, 2026
@codecov

codecov Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

@burgholzer burgholzer changed the title 🐛 Preserve MLIR exception diagnostics on macOS 🐛 Return QDMI and benchmark errors before MLIR Sep 12, 2026
@burgholzer
burgholzer force-pushed the codex/fix-mlir-exception-boundaries branch 2 times, most recently from f410460 to bb0ae82 Compare September 12, 2026 12:59
@mergify mergify Bot added the conflict label Sep 14, 2026
@burgholzer
burgholzer force-pushed the codex/fix-mlir-exception-boundaries branch from bb0ae82 to f7553f5 Compare September 14, 2026 18:08
@mergify mergify Bot removed the conflict label Sep 14, 2026
@burgholzer burgholzer mentioned this pull request Sep 14, 2026
10 tasks done
@burgholzer burgholzer changed the title 🐛 Return QDMI and benchmark errors before MLIR ♻️ Return explicit errors across native Core APIs Sep 19, 2026
@mergify mergify Bot added the conflict label Sep 19, 2026
@burgholzer
burgholzer force-pushed the codex/fix-mlir-exception-boundaries branch from 0e7e58b to 501b3b9 Compare September 19, 2026 19:35
@mergify mergify Bot removed the conflict label Sep 19, 2026
@burgholzer burgholzer changed the title ♻️ Return explicit errors across native Core APIs ♻️ Unify native results and isolate DDSIM execution Sep 22, 2026
@burgholzer
burgholzer force-pushed the codex/fix-mlir-exception-boundaries branch from 1a125ca to c5f0dd5 Compare September 22, 2026 20:24
@mergify mergify Bot added the conflict label Sep 22, 2026
@burgholzer
burgholzer force-pushed the codex/fix-mlir-exception-boundaries branch from 8c8deda to f33d8d8 Compare September 22, 2026 23:09
@mergify mergify Bot removed the conflict label Sep 22, 2026
@burgholzer

Copy link
Copy Markdown
Member Author

@burgholzer

I went through all files again and I think it looks quite good now. From my end, this could be merged after a final sanity check from your side.

Will try to get through this either today or tomorrow (more likely).

@simon1hofmann

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖
Confirmed review finding: the vector DD deserializer accepts skipped qubit levels, but single-qubit measurement now treats their absence as an assertion failure. This turns a previously recoverable error into a Python process abort.
At 461590d, this reproduces SIGABRT in Package::determineMeasurementProbabilities:

from mqt.core.dd import DDPackage, VectorDD

p = DDPackage(3)
v = VectorDD.from_bytes(p, b"1\n1\n0 2 (-1 1) ()\n", False)
p.inc_ref_vec(v)
p.measure_collapsing(v, 0)

Fixed in b028fd09d. The shared deserializer now rejects nonzero vector edges that skip qubit levels or reach a terminal above qubit zero. Zero-weight edges and valid skipped identity levels in matrix DDs remain supported. Python raises ValueError during deserialization.
The new tests fail before the fix and pass afterward. Native regression coverage exercises premature terminals and skipped intermediate levels in both text and binary input, and confirms that matrix reductions still round-trip.
Validation: 3,977 native tests passed with one expected skip; all 66 Python DD tests passed; repository lint passed on both branches. Local C++ lint could not run because clang-tidy 23 is unavailable, so hosted CI must validate that check.
The fix is also included in stacked PR #2476, preserving its planned toolchain configuration.

This feels a bit arbitrary. The DD package does not support skipped levels for Vector DDs. Never has, likely never will. Are we sure this is a clean solution here?

They were not supported before as well, but probably still makes sense to have that guard.

@burgholzer
burgholzer force-pushed the codex/qdmi-multi-program-adoption branch from d741493 to 45409bd Compare October 7, 2026 15:44
@mergify mergify Bot added the conflict label Oct 7, 2026
@burgholzer
burgholzer force-pushed the codex/qdmi-multi-program-adoption branch 4 times, most recently from 6bf57c8 to 753428e Compare October 7, 2026 17:50
@burgholzer
burgholzer removed this pull request from stack #2677 October 8, 2026 10:52
@burgholzer
burgholzer force-pushed the codex/qdmi-multi-program-adoption branch 3 times, most recently from 2ed02a6 to ab2a1e4 Compare October 8, 2026 13:26
@burgholzer
burgholzer force-pushed the codex/qdmi-multi-program-adoption branch 3 times, most recently from d9c02f6 to 97c8326 Compare October 9, 2026 10:35
@simon1hofmann simon1hofmann removed this from the v4.1.0 - QDMI 1.4 / MQSF milestone Oct 9, 2026
@burgholzer

Copy link
Copy Markdown
Member Author

@simon1hofmann @denialhaag I have extracted quite a few things from here to separate PRs and have tried to continuously updated the implementation here with regard to main.
In principle, this would be ready to go in, but I am a bit hesitant to make such big changes right in front of the release.
How about we tackle this one first thing first after the 4.1 release, which gives us an entire release cycle to polish the implementation?

@simon1hofmann

Copy link
Copy Markdown
Contributor

@simon1hofmann @denialhaag I have extracted quite a few things from here to separate PRs and have tried to continuously updated the implementation here with regard to main. In principle, this would be ready to go in, but I am a bit hesitant to make such big changes right in front of the release. How about we tackle this one first thing first after the 4.1 release, which gives us an entire release cycle to polish the implementation?

Sounds good to me! Also helps us to push out some more improvement from 4.1 to 4.2 😄

@denialhaag

Copy link
Copy Markdown
Member

Agreed!

burgholzer and others added 2 commits October 25, 2026 17:29
Build on the LLVM JSON and separate QDMI/DD I/O changes. Use Expected
and Error for recoverable native failures, factories for fallible
construction, and common nanobind conversion for Python exceptions.
Keep MLIR diagnostics local and preserve QDMI C status boundaries.

Remove diagnostic forwarding and follow LLVM's exception/RTTI policy
where native algorithms no longer throw. Keep driver allocation recovery
and worker host boundaries. Preserve DD text grammar and Python numeric
syntax, range and structural error categories.

Windows DLL LLVM error identity remains a merge requirement; this commit
does not add a custom runtime to conceal that unresolved boundary.

Co-authored-by: Daniel Haag <121057143+denialhaag@users.noreply.github.com>
Signed-off-by: Lukas Burgholzer <burgholzer@me.com>
Assisted-by: GPT-6 via Codex
Link DD algorithms and the QDMI C++ client statically so errors retain
the LLVM type identity of their handlers. Share only canonical DD
constants between Python modules. Keep MSVC regex exception layouts
compatible and use nonthrowing shortest QIR floating-point formatting.

Avoid inline ErrorList RTTI in the DD regression test and cover exact
floating-point records, including a precision mutation check.

Assisted-by: GPT-6 via Codex

This branch has not been deployed

No deployments
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 fix Fix for something that isn't working MLIR Anything related to MLIR QDMI Anything related to QDMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants