Skip to content

refactor(metadata)!: Migrate all metadata keys onto the new metadata traits#1328

Merged
maximilianruesch merged 31 commits intomainfrom
mr/feat/migrate-metadata
Jan 15, 2026
Merged

refactor(metadata)!: Migrate all metadata keys onto the new metadata traits#1328
maximilianruesch merged 31 commits intomainfrom
mr/feat/migrate-metadata

Conversation

@maximilianruesch
Copy link
Copy Markdown
Contributor

@maximilianruesch maximilianruesch commented Dec 19, 2025

Migrates all metadata keys (that I know of) in tket to use the new metadata traits introduced in HUGR, and unifies them to be in one file. This includes some debugging metadata, unitary flags, etc. Finally, some trivial fixes / simplifications are added that come as a convenience of the new metadata system.

I would still argue that this is a refactor, even though a breaking refactor seems contradictional.

Related to Quantinuum/guppylang#1378

BREAKING CHANGE: Renamed the "unitary" key to contain the TKET prefix as is standard with all other metadata keys.

@codecov
Copy link
Copy Markdown

codecov bot commented Dec 19, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.59%. Comparing base (7487e3a) to head (f48f09b).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1328      +/-   ##
==========================================
- Coverage   79.77%   79.59%   -0.19%     
==========================================
  Files         158      158              
  Lines       20509    20505       -4     
  Branches    19542    19538       -4     
==========================================
- Hits        16362    16321      -41     
- Misses       3168     3203      +35     
- Partials      979      981       +2     
Flag Coverage Δ
python 92.93% <ø> (ø)
qis-compiler 100.00% <ø> (ø)
rust 78.91% <100.00%> (-0.20%) ⬇️

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.

@aborgna-q aborgna-q force-pushed the ab/bump-hugr-0.25 branch 3 times, most recently from 3b4efbe to c7a2221 Compare December 30, 2025 16:59
Base automatically changed from ab/bump-hugr-0.25 to main December 30, 2025 17:45
@maximilianruesch maximilianruesch marked this pull request as ready for review January 13, 2026 11:09
@maximilianruesch maximilianruesch requested a review from a team as a code owner January 13, 2026 11:09
@ss2165
Copy link
Copy Markdown
Member

ss2165 commented Jan 14, 2026

Ensure the "BREAKING CHANGE: " notice is always at the bottom of the description

.set_metadata::<metadata::Phase>(node, &serialcirc.phase);
dfg.hugr_mut()
.set_metadata_any(node, METADATA_Q_REGISTERS, json!(serialcirc.qubits));
.set_metadata::<metadata::QubitRegisters>(node, serialcirc.qubits.clone()); // TODO Do we find something better than clone?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not clear what this todo means

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The question is whether we find something that avoids the clone, whether it is inevitable, or whether it should be cheap enough to remain. Might be the last case if it is a small vec of ints.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Outcome: The clone here is not avoidable without major changes to the function interface, and it seems to be cheap. It shall be fine.

hugr.entrypoint(),
METADATA_INPUT_PARAMETERS,
serde_json::json!(["alpha", "beta"]),
vec![String::from("alpha"), String::from("beta")],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: "".to_string() is standard and a bit more concise

@@ -0,0 +1,75 @@
//! (Incomplete) Collection of metadata keys used throughout tket.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what's missing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Seems to be an oversight, the collection was previously incomplete, but now every key should be in here.


/// Metadata key for the number of qubits that a HUGR node expects to be required for execution.
///
/// This value is only valid when set at the entrypoint function node. TODO discuss this
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

discuss?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Outcome: The comment will be removed. We will not enforce any constraints.

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MaxQubits;
impl Metadata for MaxQubits {
const KEY: &'static str = "TKET.expected_qubits"; // TODO think about this name really hard
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this doesn't line up with the name of the struct or what is used in released guppy

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Also a source of discussion, since we want to rename the key. We now have yet another opportunity to rename it, before we use it in tket somewhere.

Alternatively, we could decide that we only want to introduce the key when we actually use it in tket, but we should decide on a name pretty soon imo.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Outcome: Guppy uses tket.hint.max_qubits, so we will use that.

pub struct MaxQubits;
impl Metadata for MaxQubits {
const KEY: &'static str = "TKET.expected_qubits"; // TODO think about this name really hard
type Type<'hugr> = u32;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

is the 'hugr lifetime annotation required if it is not used?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, since the trait specifies Type to have a generic lifetime parameter and that must be specified as far as I know, even if unused. It can have any name, but for consistency I chose 'hugr


/// Metadata key for flagging unitarity constraints on a HUGR node
///
/// See crate::modifier::ModifierFlags TODO discuss this
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

discuss?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Leftover, will be removed.

type Type<'hugr> = u8;
}

// Metadata keys migrated from TKET1
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// Metadata keys migrated from TKET1
// Metadata keys used for TKET1 compatibility

@hugrbot
Copy link
Copy Markdown
Collaborator

hugrbot commented Jan 14, 2026

This PR contains breaking changes to the public Rust API.

cargo-semver-checks summary
    Building tket v0.16.0 (current)
     Built [  45.587s] (current)
   Parsing tket v0.16.0 (current)
    Parsed [   0.105s] (current)
  Building tket v0.16.0 (baseline)
     Built [  43.919s] (baseline)
   Parsing tket v0.16.0 (baseline)
    Parsed [   0.086s] (baseline)
  Checking tket v0.16.0 -> v0.16.0 (assume minor change)
   Checked [   0.081s] 159 checks: 158 pass, 1 fail, 0 warn, 41 skip

--- failure pub_module_level_const_missing: pub module-level const is missing ---

Description:
A public const is missing or renamed
      ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
     impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.45.0/src/lints/pub_module_level_const_missing.ron

Failed in:
METADATA_Q_REGISTERS in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/serialize/pytket.rs:52
METADATA_INPUT_PARAMETERS in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/serialize/pytket.rs:58
METADATA_REWRITES in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/rewrite/trace.rs:14
METADATA_PREFIX in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/serialize/pytket.rs:48
METADATA_OPGROUP in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/serialize/pytket.rs:56
METADATA_B_REGISTERS in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/serialize/pytket.rs:54
METADATA_PHASE in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/serialize/pytket.rs:50

   Summary semver requires new major version: 1 major and 0 minor checks failed
  Finished [  91.863s] tket
  Building tket-qsystem v0.22.0 (current)
     Built [  45.784s] (current)
   Parsing tket-qsystem v0.22.0 (current)
    Parsed [   0.029s] (current)
  Building tket-qsystem v0.22.0 (baseline)
     Built [  45.631s] (baseline)
   Parsing tket-qsystem v0.22.0 (baseline)
    Parsed [   0.029s] (baseline)
  Checking tket-qsystem v0.22.0 -> v0.22.0 (assume minor change)
   Checked [   0.047s] 159 checks: 159 pass, 41 skip
   Summary no semver update required
  Finished [  93.583s] tket-qsystem

@maximilianruesch maximilianruesch added this pull request to the merge queue Jan 15, 2026
Merged via the queue into main with commit 60ce5e2 Jan 15, 2026
24 checks passed
@maximilianruesch maximilianruesch deleted the mr/feat/migrate-metadata branch January 15, 2026 14:37
@hugrbot hugrbot mentioned this pull request Jan 15, 2026
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
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.

4 participants