Skip to content

feat!: Allow specification of unitary flags with higher order function#1768

Open
nicolaassolini-qntm wants to merge 16 commits into
mainfrom
na/1637-allow-unitary-flag-with-higher-order-function
Open

feat!: Allow specification of unitary flags with higher order function#1768
nicolaassolini-qntm wants to merge 16 commits into
mainfrom
na/1637-allow-unitary-flag-with-higher-order-function

Conversation

@nicolaassolini-qntm
Copy link
Copy Markdown
Contributor

@nicolaassolini-qntm nicolaassolini-qntm commented May 27, 2026

closes #1637

This PR allows higher-order function parameters to specify which unitary modifier contexts they support.

Changes:

  • Adds callable aliases for higher-order functions with unitary capabilities:
    • Unitary[[...], R]
    • Daggerable[[...], R]
    • Powerable[[...], R]
    • Controllable[[...], R]
    • PowerControllable[[...], R]
  • Checks callable unitary flags when passing functions as higher-order arguments.
  • Updates unitary diagnostic rendering and decorator hints.
  • Adds integration and error tests for higher-order callable flag matching.

BREAKING CHANGE: UnitaryCallError.render_flags was removed.
BREAKING CHANGE: CallableTypeDef.name changed from field(default='Callable', init=False) to field(default='Callable', kw_only=True).
BREAKING CHANGE: CallableTypeDef.__init__(name) changed from positional-or-keyword to keyword-only, CallableTypeDef.__init__(defined_at) positional parameter moved from position 3 to position 2, CallableTypeDef.__init__(params) positional parameter moved from position 4 to position 3.
BREAKING CHANGE: Added the field missing_flags to UnitaryCallError.Hint

@nicolaassolini-qntm nicolaassolini-qntm changed the title Na/1637 allow unitary flag with higher order function feat: allow unitary flag with higher order function May 27, 2026
@hugrbot
Copy link
Copy Markdown
Collaborator

hugrbot commented May 27, 2026

This PR contains breaking changes to the public Python API.

Breaking changes summary
guppylang-internals/src/guppylang_internals/engine.py:88: BUILTIN_DEFS_LIST:
Attribute value was changed:
Old: [callable_type_def, self_type_def, tuple_type_def, none_type_def, bool_type_def, nat_type_def, int_type_def, float_type_def, string_type_def, list_type_def, array_type_def, frozenarray_type_def, sized_iter_type_def, option_type_def]
New: [callable_type_def, unitary_type_def, powerable_type_def, daggerable_type_def, controllable_type_def, powerctrlable_type_def, self_type_def, tuple_type_def, none_type_def, bool_type_def, nat_type_def, int_type_def, float_type_def, string_type_def, list_type_def, array_type_def, frozenarray_type_def, sized_iter_type_def, option_type_def]

guppylang-internals/src/guppylang_internals/tys/errors.py:190: UnitaryCallError.span_label:
Attribute value was changed:
Old: 'This function cannot be called in a {render_flags} context'
New: 'This function cannot be called in a {flags} context'

guppylang-internals/src/guppylang_internals/tys/errors.py:0: UnitaryCallError.render_flags:
Public object was removed

guppylang-internals/src/guppylang_internals/tys/errors.py:228: UnitaryCallError.QubitAllocationNote.message:
Attribute value was changed:
Old: 'The function allocates qubits, which is not allowed in a {render_flags} context'
New: 'The function allocates qubits, which is not allowed in a {rendered_flags} context'

guppylang-internals/src/guppylang_internals/tys/errors.py:236: UnitaryCallError.Hint.message:
Attribute value was changed:
Old: 'Consider adding the flag `({render_flags}=True)` to the decorator of the function `{func_name}`'
New: 'Consider adding the flag `({hint_rendering})` to the decorator of the function `{func_name}`'

guppylang-internals/src/guppylang_internals/tys/builtin.py:41: CallableTypeDef.name:
Attribute value was changed:
Old: field(default='Callable', init=False)
New: field(default='Callable', kw_only=True)

guppylang-internals/src/guppylang_internals/tys/builtin.py:0: CallableTypeDef.__init__(name):
Parameter kind was changed:
Old: positional or keyword
New: keyword-only

guppylang-internals/src/guppylang_internals/tys/builtin.py:0: CallableTypeDef.__init__(defined_at):
Positional parameter was moved
Details: position: from 3 to 2 (-1)

guppylang-internals/src/guppylang_internals/tys/builtin.py:0: CallableTypeDef.__init__(params):
Positional parameter was moved
Details: position: from 4 to 3 (-1)


@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

🐰 Bencher Report

Branchna/1637-allow-unitary-flag-with-higher-order-function
TestbedLinux
Click to view all benchmark results
Benchmarkhugr_bytesBenchmark Result
bytes x 1e3
(Result Δ%)
Upper Boundary
bytes x 1e3
(Limit %)
hugr_nodesBenchmark Result
nodes
(Result Δ%)
Upper Boundary
nodes
(Limit %)
tests/benchmarks/test_big_array.py::test_big_array_compile📈 view plot
🚷 view threshold
158.77 x 1e3
(0.00%)Baseline: 158.77 x 1e3
160.36 x 1e3
(99.01%)
📈 view plot
🚷 view threshold
6,641.00
(0.00%)Baseline: 6,641.00
6,707.41
(99.01%)
tests/benchmarks/test_ctrl_flow.py::test_many_ctrl_flow_compile📈 view plot
🚷 view threshold
27.53 x 1e3
(0.00%)Baseline: 27.53 x 1e3
27.81 x 1e3
(99.01%)
📈 view plot
🚷 view threshold
1,074.00
(0.00%)Baseline: 1,074.00
1,084.74
(99.01%)
tests/benchmarks/test_queue_push_pop.py::test_queue_push_benchmark_compile📈 view plot
🚷 view threshold
10.91 x 1e3
(0.00%)Baseline: 10.91 x 1e3
11.02 x 1e3
(99.01%)
📈 view plot
🚷 view threshold
308.00
(0.00%)Baseline: 308.00
311.08
(99.01%)
tests/benchmarks/test_queue_push_pop.py::test_queue_push_pop_benchmark_compile📈 view plot
🚷 view threshold
14.84 x 1e3
(+0.01%)Baseline: 14.84 x 1e3
14.98 x 1e3
(99.02%)
📈 view plot
🚷 view threshold
435.00
(0.00%)Baseline: 435.00
439.35
(99.01%)
🐰 View full continuous benchmarking report in Bencher

@nicolaassolini-qntm nicolaassolini-qntm changed the title feat: allow unitary flag with higher order function feat: Allow specification of unitary flags with higher order function May 27, 2026
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 27, 2026

Codecov Report

❌ Patch coverage is 97.82609% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.00%. Comparing base (95326d4) to head (939c77a).
⚠️ Report is 19 commits behind head on main.

Files with missing lines Patch % Lines
...ls/src/guppylang_internals/checker/expr_checker.py 90.00% 1 Missing ⚠️
...ng-internals/src/guppylang_internals/tys/errors.py 92.85% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1768      +/-   ##
==========================================
- Coverage   93.47%   93.00%   -0.48%     
==========================================
  Files         133      135       +2     
  Lines       12698    13124     +426     
==========================================
+ Hits        11870    12206     +336     
- Misses        828      918      +90     

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

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 27, 2026

Merging this PR will not alter performance

✅ 9 untouched benchmarks


Comparing na/1637-allow-unitary-flag-with-higher-order-function (939c77a) with main (2dc589a)

Open in CodSpeed

@nicolaassolini-qntm nicolaassolini-qntm changed the title feat: Allow specification of unitary flags with higher order function feat!: Allow specification of unitary flags with higher order function May 27, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends Guppy’s higher-order function typing so callable parameters can declare which unitary modifier contexts (dagger/control/power) they support, and enforces those capabilities when passing functions as arguments.

Changes:

  • Adds new callable aliases (Unitary, Daggerable, Powerable, Controllable, PowerControllable) for annotating higher-order function parameters with required unitary flags.
  • Extends type parsing/builtin defs to treat these aliases as Callable-like types that carry unitary_flags.
  • Enforces unitary-flag compatibility during type checking and updates diagnostic rendering + integration/error tests.

Reviewed changes

Copilot reviewed 32 out of 32 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
tests/integration/test_modifier.py Adds integration coverage for higher-order callables requiring specific unitary capabilities.
tests/error/modifier_errors/higher_order_power_controllable_missing_power.py New negative test: callable missing required power flag.
tests/error/modifier_errors/higher_order_power_controllable_missing_power.err Snapshot for missing power flag mismatch diagnostic.
tests/error/modifier_errors/higher_order_power_controllable_missing_control.py New negative test: callable missing required control flag.
tests/error/modifier_errors/higher_order_power_controllable_missing_control.err Snapshot for missing control flag mismatch diagnostic.
tests/error/modifier_errors/higher_order_flag_mismatch2.py New negative test: Unitary required but dagger-only provided.
tests/error/modifier_errors/higher_order_flag_mismatch2.err Snapshot for Unitary vs dagger mismatch diagnostic.
tests/error/modifier_errors/higher_order_flag_mismatch1.py New negative test: Powerable required but dagger-only provided.
tests/error/modifier_errors/higher_order_flag_mismatch1.err Snapshot for power vs dagger mismatch diagnostic.
tests/error/modifier_errors/higher_order_daggerable_missing_flag.py New negative test: Daggerable required but no flags provided.
tests/error/modifier_errors/higher_order_daggerable_missing_flag.err Snapshot for missing dagger capability diagnostic.
tests/error/modifier_errors/higher_order_controllable_missing_flag.py New negative test: Controllable required but dagger-only provided.
tests/error/modifier_errors/higher_order_controllable_missing_flag.err Snapshot for control vs dagger mismatch diagnostic.
tests/error/modifier_errors/flags_nested_combined_outer.err Updates constraint violation snapshots to use more specific combined-flag titles/hints.
tests/error/modifier_errors/flag_unitary_qubit.err Updates note wording for unitary context rendering.
tests/error/modifier_errors/flag_power_qubit2.err Updates note wording for power context rendering.
tests/error/modifier_errors/flag_power_qubit1.err Updates note wording for power context rendering.
tests/error/modifier_errors/flag_multiple_qubit copy.py Adds new negative test for combined modifier context (file naming is unusual).
tests/error/modifier_errors/flag_multiple_qubit copy.err Snapshot for combined control & power constraint violation.
tests/error/modifier_errors/flag_dagger_qubit2.err Updates note wording for dagger context rendering.
tests/error/modifier_errors/flag_dagger_qubit1.err Updates note wording for dagger context rendering.
tests/error/modifier_errors/flag_control_qubit2.err Updates note wording for control context rendering.
tests/error/modifier_errors/flag_control_qubit1.err Updates note wording for control context rendering.
guppylang/src/guppylang/std/lang.py Introduces runtime-erasable generic callable aliases (Unitary, etc.) for user annotations.
guppylang/src/guppylang/std/builtins.py Re-exports the new callable aliases from the standard prelude.
guppylang-internals/src/guppylang_internals/tys/ty.py Adds unitary-flag rendering + subset check helper on UnitaryFlags.
guppylang-internals/src/guppylang_internals/tys/parsing.py Parses the new callable aliases as function types with attached unitary_flags.
guppylang-internals/src/guppylang_internals/tys/errors.py Refactors unitary constraint diagnostic rendering and decorator hint formatting.
guppylang-internals/src/guppylang_internals/tys/builtin.py Extends CallableTypeDef to cover the new callable aliases and registers new builtin defs.
guppylang-internals/src/guppylang_internals/engine.py Registers new builtin callable defs in the engine.
guppylang-internals/src/guppylang_internals/checker/expr_checker.py Enforces unitary-flag compatibility when checking higher-order function argument types.
guppylang-internals/src/guppylang_internals/checker/errors/type_errors.py Adds a dedicated type error for unitary-flag mismatches on function arguments.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread guppylang-internals/src/guppylang_internals/checker/expr_checker.py
Comment thread guppylang-internals/src/guppylang_internals/checker/expr_checker.py
Comment thread guppylang-internals/src/guppylang_internals/tys/ty.py
Comment thread guppylang-internals/src/guppylang_internals/tys/parsing.py
Comment thread guppylang-internals/src/guppylang_internals/tys/parsing.py Outdated
Comment thread guppylang-internals/src/guppylang_internals/tys/builtin.py
Comment thread guppylang-internals/src/guppylang_internals/tys/errors.py
Comment thread tests/error/modifier_errors/flag_multiple_qubit.py
Comment thread guppylang-internals/src/guppylang_internals/checker/expr_checker.py Outdated
@nicolaassolini-qntm nicolaassolini-qntm marked this pull request as ready for review May 27, 2026 12:32
@nicolaassolini-qntm nicolaassolini-qntm requested a review from a team as a code owner May 27, 2026 12:32
@nicolaassolini-qntm nicolaassolini-qntm marked this pull request as draft May 27, 2026 12:46

This comment was marked as low quality.

@nicolaassolini-qntm nicolaassolini-qntm marked this pull request as ready for review May 27, 2026 13:33
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.

[Feature]: Allow unitary flag with higher order function

4 participants