Skip to content

feat!: Bump hugr to 0.25.0#1325

Merged
aborgna-q merged 37 commits intomainfrom
ab/bump-hugr-0.25
Dec 30, 2025
Merged

feat!: Bump hugr to 0.25.0#1325
aborgna-q merged 37 commits intomainfrom
ab/bump-hugr-0.25

Conversation

@aborgna-q
Copy link
Copy Markdown
Collaborator

@aborgna-q aborgna-q commented Dec 16, 2025

BREAKING CHANGE: Bumped hugr dependency to 0.25.0
BREAKING CHANGE: Bumped pyo3 dependency to 0.27.2

(Currently pinned to a commit in hugr main, will mark as ready once hugr is released)

@codecov
Copy link
Copy Markdown

codecov bot commented Dec 16, 2025

Codecov Report

❌ Patch coverage is 85.62874% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.69%. Comparing base (09f5fa9) to head (14dda69).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
qis-compiler/rust/lib.rs 0.00% 5 Missing ⚠️
tket/src/passes/commutation.rs 0.00% 4 Missing ⚠️
tket-qsystem/src/replace_bools.rs 90.00% 2 Missing and 1 partial ⚠️
qis-compiler/rust/array.rs 0.00% 2 Missing ⚠️
tket/src/circuit/command.rs 0.00% 2 Missing ⚠️
qis-compiler/rust/utils.rs 0.00% 1 Missing ⚠️
tket-qsystem/src/llvm/qsystem.rs 80.00% 1 Missing ⚠️
tket-qsystem/src/lower_drops.rs 80.00% 0 Missing and 1 partial ⚠️
tket/src/circuit.rs 66.66% 1 Missing ⚠️
...ket/src/modifier/modifier_resolver/array_modify.rs 0.00% 1 Missing ⚠️
... and 3 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1325      +/-   ##
==========================================
- Coverage   79.70%   79.69%   -0.02%     
==========================================
  Files         160      158       -2     
  Lines       20595    20440     -155     
  Branches    19629    19474     -155     
==========================================
- Hits        16415    16289     -126     
+ Misses       3198     3171      -27     
+ Partials      982      980       -2     
Flag Coverage Δ
python 92.92% <ø> (ø)
qis-compiler 100.00% <ø> (ø)
rust 79.01% <85.62%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 121 to 126
.insert_hugr(hugr.module_root(), func_def)
.inserted_entrypoint;
lowerer.replace_op(&op, NodeTemplate::Call(func_node, vec![]));
// TODO: Call is deprecated. We should use LinkedHugr instead.
#[expect(deprecated)]
lowerer.set_replace_op(&op, NodeTemplate::Call(func_node, vec![]));
}
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Currently a TODO, should we update it before merging?

Copy link
Copy Markdown
Contributor

@acl-cqc acl-cqc Dec 24, 2025

Choose a reason for hiding this comment

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

It doesn't look that hard, given we have the func_def just above, but happy to leave, up to you. (If you want to fix, then I can give you a hand, you need a Hugr with a call node entrypoint, plus either func_def or a matching FuncDecl if you insert func_def above. Oh, and make sure the function in func_def is marked Visibility::Public!) Following #1333 we'll mark the new function private after linking so it can be removed (e.g. if no such op is ever lowered, or by LLVM after inlining) although I think we'll not RemoveDeadFuncs it ourselves (as RDF was earlier)...

Copy link
Copy Markdown
Collaborator Author

@aborgna-q aborgna-q Dec 29, 2025

Choose a reason for hiding this comment

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

I was able to remove the other deprecated call, but doing the same thing here fails due to untranslated temp ops.
I guess it's because the hugrs inside the templates are not being translated in time when multiple lowerers are defined together...

8fa7eb6

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My quick read of the test lead me to expect something using LinkedHugr here:

ReplaceOps::Barrier(barrier) => {
// Handle barrier replacements
barrier_funcs.insert_runtime_barrier(hugr, node, barrier)?;
}

Copy link
Copy Markdown
Contributor

@acl-cqc acl-cqc left a comment

Choose a reason for hiding this comment

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

Ok so I am nervous of merging this without the nondeterminism bug solved; at the very least, we need to backup the branch so it isn't deleted by squash-merge, noting the "last deterministic commit".

I presume you want to merge before #1333 and then that can follow afterwards, and I guess that's ok as it's only a code-size regression.

But I'd also be happy to leave this as approved+mergable, but not merged, until such time as we desperately need it, and see whether that happens or we manage to fix the nondeterminism bug first....

let mut b = ModuleBuilder::with_hugr(func_def);
let call = {
let mut f = b
.define_function_vis("", func_signature, Visibility::Private)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

fwiw Private is default if you do just define_function, but fine for explicitness

let mut call_hugr = b.finish_hugr().unwrap();
call_hugr.set_entrypoint(call.node());

NodeTemplate::LinkedHugr(Box::new(call_hugr), NameLinkingPolicy::default())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NameLinkingPolicy::default will mean that if you insert the call-hugr more than once, you'll get an error that it's not sure which (existing or new) FuncDefn to use (it only wants to keep one and doesn't realize they are the same)...options are

  • Use default().on_multiple_defn(OnMultiDefn::UseTarget or UseSource)
  • Add a FuncDecl only, and then link in the FuncDefn once only either before or after ReplaceTypes

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reverted this commit, but will take that into account for the follow up PR

{
// TODO: Remove "llvm" feature gate once `inline_constant_functions` is moved to
// `hugr-passes`. See https://github.com/quantinuum/hugr/issues/2419
// TODO: We still want to run this as long as deserialized hugrs are allowed to contain Value::Function
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

OIC, current implementation is in hugr::llvm, right. But no LLVM dependency there, so we could move it to hugr-passes. But we're just gonna delete it instead, right....

Ok, I guess there is nothing we can really do here, we have to leave it inside the #[cfg(feature = "llvm")]

Comment on lines 121 to 126
.insert_hugr(hugr.module_root(), func_def)
.inserted_entrypoint;
lowerer.replace_op(&op, NodeTemplate::Call(func_node, vec![]));
// TODO: Call is deprecated. We should use LinkedHugr instead.
#[expect(deprecated)]
lowerer.set_replace_op(&op, NodeTemplate::Call(func_node, vec![]));
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My quick read of the test lead me to expect something using LinkedHugr here:

ReplaceOps::Barrier(barrier) => {
// Handle barrier replacements
barrier_funcs.insert_runtime_barrier(hugr, node, barrier)?;
}

Copy link
Copy Markdown
Contributor

@acl-cqc acl-cqc left a comment

Choose a reason for hiding this comment

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

Ok, leaving both NodeTemplate::Calls in, and with the tests re-enabled, looks good - please go ahead ;-)

@aborgna-q aborgna-q enabled auto-merge December 30, 2025 17:26
@aborgna-q aborgna-q disabled auto-merge December 30, 2025 17:31
@aborgna-q aborgna-q enabled auto-merge December 30, 2025 17:33
@aborgna-q aborgna-q added this pull request to the merge queue Dec 30, 2025
Merged via the queue into main with commit 29b1ae5 Dec 30, 2025
24 checks passed
@aborgna-q aborgna-q deleted the ab/bump-hugr-0.25 branch December 30, 2025 17:45
@hugrbot hugrbot mentioned this pull request Dec 29, 2025
github-merge-queue bot pushed a commit to Quantinuum/hugr that referenced this pull request Dec 30, 2025
I think this fixes the [nondeterminism
observed](Quantinuum/tket2#1325 (comment))
in tket2#1325. (I updated tket2/Cargo.toml to use this branch, then ran
`uv clean && uv pip install --reinstall tket selene-hugr-qis-compiler &&
uv sync` and that changed tests from failing to passing).

Not sure I completely understand the mechanism - this appears to change
only the order in which we add (all the outgoing edges from a node) for
each node (not the order of outgoing edges for each), which AFAICS
should have no effect. But....let's try....
@aborgna-q aborgna-q restored the ab/bump-hugr-0.25 branch December 30, 2025 20:47
@aborgna-q aborgna-q deleted the ab/bump-hugr-0.25 branch December 30, 2025 20:52
github-merge-queue bot pushed a commit that referenced this pull request Jan 5, 2026
Depends on the unreleased `hugr 0.25.0`

Requires #1325
github-merge-queue bot pushed a commit that referenced this pull request Jan 6, 2026
So following #1325 I was finally able to (/finally succeeded) in
evaluating the effect of Quantinuum/hugr#2749 on
guppy tests. (There was some question on that PR as to whether we needed
to add new facility, see #2766; here is the data.)

Three tests were affected (indeed the same ones as were broken and then
fixed by Quantinuum/hugr#2779 but that is a
separate issue). The sizes of the LLVM output as follows:

| | Original (hugr 0.24.3) | Hugr
0.25+[fix](Quantinuum/hugr#2779) | Hugr
0.25+[fix](Quantinuum/hugr#2779) + this PR |
|----|----|----|----|
| [new test](Quantinuum/guppylang#1411) | 9568 |
11856 | 9888 |
| basic_type | 10224 | 11616 | 10400 |
| notebook2 | 15680 | 17184 | 15936 |
| notebook5 (Hugr 1) | 10832 | 12304 | 11072 |
| notebook5 (Hugr 2) | 10480 | 11840 | 10656 |

Inspection of the hugrs in the middle row revealed the helper functions
from Quantinuum/hugr#2749 were indeed present in
the LLVM output as `define` (not `define private`). Hence, this PR,
following which LLVM is able to remove the `define`s. (I have not looked
into the remaining +2-3% increase. (The numbers include many other
changes between hugr-0.24.3 and hugr-0.25.0.)
github-merge-queue bot pushed a commit that referenced this pull request Jan 15, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.12.14](tket-py-v0.12.13...tket-py-v0.12.14)
(2026-01-15)


### Features

* make PytketHugrPass store a list of passes
([#1360](#1360))
([498dd3a](498dd3a))
* Reduced glibc version requirement to 2.34
([#1327](#1327))
([498dd3a](498dd3a))
* Remove order edges in NormalizeGuppy pass
([#1326](#1326))
([dbfffd5](dbfffd5)),
closes [#1325](#1325)
* Use constant folding by default on NormalizeGuppy
([#1323](#1323))
([6f11024](6f11024))


### Bug Fixes

* Incorrect manylinux version in linux wheels
([#1327](#1327))
([498dd3a](498dd3a))
* Wrongly reused qubit IDs in pytket encoding
([#1358](#1358))
([498dd3a](498dd3a))


### Documentation

* update example notebook after Guppy optimization fixes
([#1357](#1357))
([7487e3a](7487e3a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: Agustín Borgna <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Feb 3, 2026
## 🤖 New release

* `tket`: 0.16.0 -> 0.17.0 (✓ API compatible changes)
* `tket-qsystem`: 0.22.0 -> 0.23.0 (✓ API compatible changes)

<details><summary><i><b>Changelog</b></i></summary><p>

## `tket`

<blockquote>

##
[0.17.0](tket-v0.16.0...tket-v0.17.0)
- 2026-02-02

### Bug Fixes

- *(encoded-circ)* Track unsupported wires between input and output
([#1224](#1224))
- Multiple fixes to the pytket encoder
([#1226](#1226))
- Don't use opgroup in pytket barrier encoding
([#1251](#1251))
- guppy_to_circuit always returns num_operations = 0
([#1200](#1200))
- *(pytket-decoder)* Avoid QAllocating and immediately freeing qubits
([#1256](#1256))
- Encoding of opaque subgraphs with no associated qubit/bit
([#1295](#1295))
- [**breaking**] Don't rely on command params for pytket barriers
([#1298](#1298))
- Track output qubits in CircuitInfo
([#1304](#1304))
- Wrongly reused qubit IDs in pytket encoding
([#1358](#1358))

### New Features

- Deprecate local find_tuple_unpack rewrite
([#1188](#1188))
- Add CopyableExpressionAST
([#1209](#1209))
- `NormalizeGuppy` pass to simplify generated structure
([#1220](#1220))
- [**breaking**] pytket EncodedCircuit struct for in-place pytket
optimisation ([#1211](#1211))
- [**breaking**] Interval is independent of resource IDs and scope
position ([#1205](#1205))
- Don't translate usizes to pytket
([#1241](#1241))
- BorrowSquashPass to elide redundant borrow/return ops
([#1159](#1159))
- [**breaking**] Bump hugr to 0.25.0
([#1325](#1325))
- Remove order edges in NormalizeGuppy pass
([#1326](#1326))
- [**breaking**] Remove deprecated unpack tuple pass
([#1387](#1387))

### Refactor

- Remove contain_qubits, use TypeUnpacker
([#1283](#1283))
- [**breaking**] Replace Subcircuit with SiblingSubgraph
([#1288](#1288))
- *(metadata)* [**breaking**] Migrate all metadata keys onto the new
metadata traits ([#1328](#1328))
</blockquote>

## `tket-qsystem`

<blockquote>

##
[0.23.0](tket-qsystem-v0.22.0...tket-qsystem-v0.23.0)
- 2026-02-02

### Bug Fixes

- [**breaking**] Don't rely on command params for pytket barriers
([#1298](#1298))
- Wrongly reused qubit IDs in pytket encoding
([#1358](#1358))

### New Features

- `NormalizeGuppy` pass to simplify generated structure
([#1220](#1220))
- Allow running arbitrary serializable pytket passes on hugrs
([#1266](#1266))
- BorrowSquashPass to elide redundant borrow/return ops
([#1159](#1159))
- [**breaking**] Bump hugr to 0.25.0
([#1325](#1325))
- Remove order edges in NormalizeGuppy pass
([#1326](#1326))
- hide new public funcs introduced by linearization
([#1333](#1333))

### Testing

- regenerate guppy_opt examples, and count gates
([#1249](#1249))
- run pytket on guppy_opt tests, measure (very limited) success
([#1250](#1250))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
@hugrbot hugrbot mentioned this pull request Feb 5, 2026
potatoboiler pushed a commit to potatoboiler/tket2 that referenced this pull request Mar 23, 2026
Reverted in Quantinuum#1325 due to a bug in hugr, now fixed in `0.25.2`.

The change in `unpack_container` seems to cause issues since we are not
lowering operations defined in the templates themselves recursively.

---------

Co-authored-by: Alan Lawrence <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants