Skip to content

feat: InlineHint metadata#1532

Merged
aborgna-q merged 5 commits into
mainfrom
ab/inline-funcs-meta
May 18, 2026
Merged

feat: InlineHint metadata#1532
aborgna-q merged 5 commits into
mainfrom
ab/inline-funcs-meta

Conversation

@aborgna-q

Copy link
Copy Markdown
Collaborator

Follow up to Quantinuum/hugr#1524. Defines a metadata value for hinting the compiler on which functions to inline.

Part of #1804.

Note that this definition is rust-only. We still need to add exports for all tket metadata definitions on the python bindings.

Guppy issue/PR (they'll need to be updated):

@aborgna-q aborgna-q requested a review from acl-cqc April 21, 2026 10:37
@aborgna-q aborgna-q requested a review from a team as a code owner April 21, 2026 10:37
@codecov

codecov Bot commented Apr 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.36364% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.24%. Comparing base (1bfef9a) to head (dcdc717).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
tket-py/tket/metadata.py 80.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1532      +/-   ##
==========================================
+ Coverage   84.05%   84.24%   +0.19%     
==========================================
  Files         189      189              
  Lines       29358    29778     +420     
  Branches    28174    28581     +407     
==========================================
+ Hits        24677    25087     +410     
- Misses       3501     3502       +1     
- Partials     1180     1189       +9     
Flag Coverage Δ
python 90.60% <80.00%> (-0.16%) ⬇️
qis-compiler 91.66% <ø> (ø)
rust 83.97% <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.

@acl-cqc acl-cqc left a comment

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.

Ok let's combine functionality (not necessarily PRs) here with #1449.
I've updated that to use a similar metadata (there without the Never, with #[non_exhaustive], and I called it InlineAnnotation rather than hint, but at least it's in the same place ;-)).
Noting that #1524 uses inline_acyclic which will mean any function on a cycle will not be inlined at all (cycles are removed from graph rather than merely broken), I think #1449 handles the "Always" bit better, so that can be run first as a separate pass.

Thus, either (a) put this in first, but without the Always option (to be added in 1449); or (b) let's get #1449 in first and then this can add the Never option. I don't really mind which way around, and I think #1449 can be marked ready now (probably for a random reviewer? But you might want to check over the annotation).

WRT this PR:

  • I am also unsure about "follow_hints=False" still respecting the "Never" hint; are we sure it shouldn't follow that too? (Otherwise, follow_hints will do nothing when Always is removed. One could say "Always is not a hint" but an annotation, iow it's correct for "follow_hints" to have no effect until we add some InlineAnnotation::XYZHint).
  • Would be nice to add to the heuristic here that (non-preserved?) functions with only one call "are always small enough" ;)
  • I haven't checked what you're doing here, but I note it's quite tricksy doing inlining respecting PassScope::EntrypointXXX :(

@acl-cqc

acl-cqc commented May 6, 2026

Copy link
Copy Markdown
Contributor

If we'd rather put this in with the algorithm as here, which I think is ok....

  • Do we want to combine metadata for this pass and chore: devenv update hugr#1449?
    • If so, I think it should be "InlineAnnotation" and the variants that are hints should be called XyzHint, or something like that. (Does it live in tket.hint.... ?) e.g. your "always" is a hint, not a command.
    • Otherwise, we could have both InlineAnnotation and InlineHint....
  • "Always" would be better as "BestEffort" or "Best" or "Max" or something like that, with actually "always" handled by chore: devenv update hugr#1449. (Really "Always" here means "Trust me I am small enough")
  • "follow"ing hints (default true) would be better as "ignore hints" (default false).
    • Should probably apply uniformly to both never and (pseudo-)always?

@aborgna-q

Copy link
Copy Markdown
Collaborator Author
  • Renamed metadata::InlineHint to metadata::InlineAnnotation. It's now #[non_exhaustive].
  • Renamed the metadata key from tket.hint.inline to just tket.inline.
  • Removed InlineAnnotation::Always and added a BestEffort (encoded as best_effort).
  • Removed the follow_inline_hints flag from the inline funcs pass. It's less confusing now.

I think that should combine well with your PR now?

@aborgna-q aborgna-q requested a review from acl-cqc May 12, 2026 14:11
@hugrbot

hugrbot commented May 13, 2026

Copy link
Copy Markdown
Collaborator

This PR contains breaking changes to the public Rust API.
Please deprecate the old API instead (if possible), or mark the PR with a ! to indicate a breaking change.

cargo-semver-checks summary
    Building tket v0.18.0 (current)
     Built [  44.904s] (current)
   Parsing tket v0.18.0 (current)
    Parsed [   0.122s] (current)
  Building tket v0.18.0 (baseline)
     Built [  43.016s] (baseline)
   Parsing tket v0.18.0 (baseline)
    Parsed [   0.103s] (baseline)
  Checking tket v0.18.0 -> v0.18.0 (assume minor change)
   Checked [   0.149s] 196 checks: 195 pass, 1 fail, 0 warn, 56 skip

--- failure inherent_method_missing: pub method removed or renamed ---

Description:
A publicly-visible method or associated fn is no longer available under its prior name. It may have been renamed or removed entirely.
      ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
     impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.47.0/src/lints/inherent_method_missing.ron

Failed in:
InlineFunctionsPass::follow_inline_hints, previously in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/passes/inline_funcs.rs:84
InlineFunctionsPass::follow_inline_hints, previously in file /home/runner/work/tket2/tket2/BASELINE_BRANCH/tket/src/passes/inline_funcs.rs:84

   Summary semver requires new major version: 1 major and 0 minor checks failed
  Finished [  90.364s] tket
  Building tket-qec v0.1.0 (current)
     Built [  37.566s] (current)
   Parsing tket-qec v0.1.0 (current)
    Parsed [   0.006s] (current)
  Building tket-qec v0.1.0 (baseline)
     Built [  37.678s] (baseline)
   Parsing tket-qec v0.1.0 (baseline)
    Parsed [   0.006s] (baseline)
  Checking tket-qec v0.1.0 -> v0.1.0 (assume minor change)
   Checked [   0.015s] 196 checks: 196 pass, 56 skip
   Summary no semver update required
  Finished [  76.898s] tket-qec
  Building tket-qsystem v0.24.0 (current)
     Built [  44.416s] (current)
   Parsing tket-qsystem v0.24.0 (current)
    Parsed [   0.026s] (current)
  Building tket-qsystem v0.24.0 (baseline)
     Built [  44.180s] (baseline)
   Parsing tket-qsystem v0.24.0 (baseline)
    Parsed [   0.026s] (baseline)
  Checking tket-qsystem v0.24.0 -> v0.24.0 (assume minor change)
   Checked [   0.059s] 196 checks: 196 pass, 56 skip
   Summary no semver update required
  Finished [  90.285s] tket-qsystem

@acl-cqc acl-cqc left a comment

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.

Thanks Agustin, looks good to me

Comment thread tket-py/tket/metadata.py Outdated
Values:
- "never": Never inline this function.
- "best_effort":
Inline the function if we know it won't produce an invalid Hugr.

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.

Suggested change
Inline the function if we know it won't produce an invalid Hugr.
Inline the function if possible

or "as much as the compiler is able."

I don't know that infinitely big Hugrs are invalid. I mean, we can't validate them, but if we had infinite memory and address space, validation won't throw an error... ;)

Comment thread tket-py/tket/metadata.py Outdated
- "never": Never inline this function.
- "best_effort":
Inline the function if we know it won't produce an invalid Hugr.
This is a best effort option; the compiler may choose not to inline

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.

Suggested change
This is a best effort option; the compiler may choose not to inline
Whilst this is no guarantees (the compiler may choose not to inline
functions with this annotation), the compiler should aim to inline whenever possible, ignoring any restrictions due to finite quantities

Or "ignoring quantitative restrictions" or something like that

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.

I'd be cautious of promising what the compiler will do here.
We don't want to be limited by the metadata restrictions when updating the compiler inlining pass.

Comment thread tket-py/tket/metadata.py Outdated
KEY = _metadata.MAX_QUBITS_HINT


class InlineAnnotationValue(Enum):

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.

Just wondering if it's possible to use a Literal["never","best_effort"] instead of this Enum? That might be much simpler?

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.

Yeah, for a public API it may be simpler to do strings. Updated.

@aborgna-q aborgna-q enabled auto-merge May 18, 2026 14:46
@aborgna-q aborgna-q added this pull request to the merge queue May 18, 2026
Merged via the queue into main with commit e7949c2 May 18, 2026
23 of 24 checks passed
@aborgna-q aborgna-q deleted the ab/inline-funcs-meta branch May 18, 2026 14:56
This was referenced May 18, 2026
jpacold pushed a commit to jpacold/tket2 that referenced this pull request May 23, 2026
)

We should also add a metadata for inline hints either here or in
Quantinuum#1532, whichever gets merged
second.
jpacold pushed a commit to jpacold/tket2 that referenced this pull request May 23, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.13.1](Quantinuum/tket2@tket-py-v0.13.0...tket-py-v0.13.1)
(2026-05-19)


### Features

* Add python definitions for the TKET metadata keys
([Quantinuum#1535](Quantinuum#1535))
([1bfef9a](Quantinuum@1bfef9a))
* Clean Up by Deleting Unconnected Nodes after Modifier Solve
([Quantinuum#1557](Quantinuum#1557))
([d706867](Quantinuum@d706867))
* expose the QSystemPass to Python
([Quantinuum#1556](Quantinuum#1556))
([394a610](Quantinuum@394a610))
* InlineFunctionsPass
([Quantinuum#1524](Quantinuum#1524))
([f40dcef](Quantinuum@f40dcef))
* InlineHint metadata
([Quantinuum#1532](Quantinuum#1532))
([e7949c2](Quantinuum@e7949c2))


### Bug Fixes

* Apply modifiers through function calls
([Quantinuum#1531](Quantinuum#1531))
([6a13f0c](Quantinuum@6a13f0c))
* Incorrect matching of pytket parameters to unsupported graph ports
([Quantinuum#1561](Quantinuum#1561))
([4fc5a25](Quantinuum@4fc5a25))
* Passes with Nested Modifier
([Quantinuum#1546](Quantinuum#1546))
([bf6df51](Quantinuum@bf6df51))
* Update examples link in README.md
([Quantinuum#1506](Quantinuum#1506))
([9a25ec8](Quantinuum@9a25ec8))


### Documentation

* Simplify package description.
([Quantinuum#1547](Quantinuum#1547))
([54e855f](Quantinuum@54e855f))

---
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 <agustin.borgna@quantinuum.com>
@hugrbot hugrbot mentioned this pull request Jun 1, 2026
nrdcid pushed a commit to nrdcid/tket2 that referenced this pull request Jun 4, 2026
## 🤖 New release

* `tket`: 0.18.0 -> 0.19.0 (✓ API compatible changes)
* `tket-qsystem`: 0.24.0 -> 0.25.0 (✓ API compatible changes)

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

## `tket`

<blockquote>

##
[0.19.0](Quantinuum/tket2@tket-v0.18.0...tket-v0.19.0)
- 2026-05-28

### Bug Fixes

- Apply modifiers through function calls
([Quantinuum#1531](Quantinuum#1531))
- Incorrect matching of pytket parameters to unsupported graph ports
([Quantinuum#1561](Quantinuum#1561))
- [**breaking**] Passes with Nested Modifier
([Quantinuum#1546](Quantinuum#1546))
- bug in hugr building when `control` modifiers are nested
([Quantinuum#1550](Quantinuum#1550))
- Multiple fixes to the pytket encoder
([Quantinuum#1566](Quantinuum#1566))
- [**breaking**] Replace non-deterministic iterations on hash maps
([Quantinuum#1582](Quantinuum#1582))
- Set inputs of functions loaded as values to top during dataflow
analysis ([Quantinuum#1595](Quantinuum#1595))
- Using indexes inside dagger modifier
([Quantinuum#1588](Quantinuum#1588))
- address Miri unsoundness by installing nextest and skipping FFI/long
running tests ([Quantinuum#1565](Quantinuum#1565))
- skip test_nested_array to resolve miri unsoundness
([Quantinuum#1623](Quantinuum#1623))

### New Features

- *(const-fold)* combine Consts for each out-port; write prepopulated
inputs ([Quantinuum#1489](Quantinuum#1489))
- InlineFunctionsPass
([Quantinuum#1524](Quantinuum#1524))
- upgrade to hugr v0.27.1
([Quantinuum#1568](Quantinuum#1568))
- [**breaking**] Ignore empty circuits when encoding Hugr regions into
pytket ([Quantinuum#1562](Quantinuum#1562))
- Add python definitions for the TKET metadata keys
([Quantinuum#1535](Quantinuum#1535))
- Clean Up by Deleting Unconnected Nodes after Modifier Solve
([Quantinuum#1557](Quantinuum#1557))
- InlineHint metadata
([Quantinuum#1532](Quantinuum#1532))
- Allowing control flow in `control`
([Quantinuum#1603](Quantinuum#1603))

### Performance

- Improve modifier resolver pass by visiting nodes in a set
([Quantinuum#1621](Quantinuum#1621))
- Avoid string formatting in Hugr op hashing
([Quantinuum#1624](Quantinuum#1624))

### Refactor

- Replace portgraph toposort in CommandIterator with node vector
([Quantinuum#1608](Quantinuum#1608))
- [**breaking**] Deprecate commands iterator
([Quantinuum#1611](Quantinuum#1611))

### Testing

- Pin guppy version in example files, fix test
([Quantinuum#1534](Quantinuum#1534))
- Skip slow modifier test
([Quantinuum#1587](Quantinuum#1587))
- Add modifier test for subscripted control qubits
([Quantinuum#1601](Quantinuum#1601))
</blockquote>

## `tket-qsystem`

<blockquote>

##
[0.25.0](Quantinuum/tket2@tket-qsystem-v0.24.0...tket-qsystem-v0.25.0)
- 2026-05-28

### Bug Fixes

- Multiple fixes to the pytket encoder
([Quantinuum#1566](Quantinuum#1566))
- [**breaking**] Replace non-deterministic iterations on hash maps
([Quantinuum#1582](Quantinuum#1582))

### New Features

- expose the QSystemPass to Python
([Quantinuum#1556](Quantinuum#1556))
- upgrade to hugr v0.27.1
([Quantinuum#1568](Quantinuum#1568))
- [**breaking**] Ignore empty circuits when encoding Hugr regions into
pytket ([Quantinuum#1562](Quantinuum#1562))
- *(qsystem)* [**breaking**] multiple platform extensions
([Quantinuum#1567](Quantinuum#1567))

### Refactor

- [**breaking**] Deprecate commands iterator
([Quantinuum#1611](Quantinuum#1611))

### Testing

- Pin guppy version in example files, fix test
([Quantinuum#1534](Quantinuum#1534))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
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