Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Inout arguments #311

Merged
merged 15 commits into from
Aug 22, 2024
Merged

feat: Inout arguments #311

merged 15 commits into from
Aug 22, 2024

Conversation

mark-koch
Copy link
Collaborator

@mark-koch mark-koch commented Jul 24, 2024

This is the dev branch for the inout argument feature (tracked by #282).

The idea is to allow explicit @inout annotations on function arguments that "give back" the passed value after the function returns:

@guppy
def foo(q: qubit @inout) -> None: ...

@guppy
def bar(q1: qubit @inout, q2: qubit @inout) -> bool: ...

@guppy
def main() -> None:
   q1, q2 = qubit(), qubit()
   foo(q1)          # Desugars to `q1 = foo(q1)`
   x = bar(q1, q2)  # Desugars to `q1, q2, x = bar(q1, q2)`
   y = bar(q1, q1)  # Error: Linearity violation, q1 used twice

To enable this, we need to enforce that @inout arguments are not moved in the body of the function (apart from passing them in another @inout position). This means that the argument will always be bound to the same name and never aliased which allows us to desugar @inout functions like

@guppy
def bar(q1: qubit, q2: qubit) -> bool:
   [body]
   return [expr]

into

@guppy
def bar(q1: qubit, q2: qubit) -> tuple[qubit, qubit, bool]:
   [body]
   return q1, q2, [expr]  # Linearity checker needs to ensure that q1, q2 are unused

Note that we only allow @inout annotations on linear types, since they would be useless for classical ones (unless we also implement an ownership system for classical values). Supporting them would make the checking logic more complicated without providing any meaningful benefit.

Tracked PRs:

@mark-koch mark-koch mentioned this pull request Jul 24, 2024
11 tasks
@codecov-commenter
Copy link

codecov-commenter commented Jul 24, 2024

Codecov Report

Attention: Patch coverage is 98.00797% with 5 lines in your changes missing coverage. Please review.

Project coverage is 92.50%. Comparing base (536abf9) to head (288146b).

Files Patch % Lines
guppylang/tys/parsing.py 91.37% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #311      +/-   ##
==========================================
+ Coverage   92.32%   92.50%   +0.18%     
==========================================
  Files          48       48              
  Lines        5014     5177     +163     
==========================================
+ Hits         4629     4789     +160     
- Misses        385      388       +3     

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

Adds a new `InputFlags` enum that is paired up with each input in
`FunctionType`. See #311 for context.

Closes #313
github-merge-queue bot pushed a commit that referenced this pull request Jul 29, 2024
To support working on dev branches like #311
mark-koch and others added 11 commits August 12, 2024 08:59
Implicitly reassign places after a call in an `@inout` position. See
#311 for context.

* Store `InputFlags` in `Variable` so we can find out if a variable is
`@inout` during linearity checking
* Pass globals to the `BBLinearityChecker` so we can lookup function
signatures to figure out if they contain inout args
* Handle `LocalCall` and `GlobalCall` nodes in `BBLinearityChecker` to
reassign inout places

Notes:

* Tests involving the result function are failing due to #320
* Some of the error messages in this PR are not ideal. I want to adress
that in a separate PR so this one doesn't get too big (see #318)
* Hugr validation is skipped in the tests for now until we have updated
the lowering code (see #317)

Closes #317
Closes #319.

* `CallableCompiledDef.compile_call` now additionally returns a list of
inout ports that were passed through the function
* Similarly, there is now a `CustomInoutCallCompiler` that does the
same. The original `CustomCallCompiler` still exists, but always returns
an empty inout list
* `ExprCompiler` now updates the `Place -> Port` mapping for inout
arguments after a call (see `ExprCompiler._update_inout_ports` helper
method)
* Enabled validation for the inout integration tests

Notes:
* This PR doesn't handle tensor calls with inout arguments (see #330)
* `CustomInoutCallCompiler` isn't used yet since the prelude doesn't use
`@inout` yet
Closes #332

Most of the diff are tests, so don't be scared :D

Updates to the checking logic are:

* Update dataflow analysis to mark inout arguments as implicitly used in
the exit BB
* The use in the exit BB is a special `InoutReturnSentinel` AST node
defined in `nodes.py`
* Update linearity checker to disallow usage of inout varaiables except
for `@inout` positions
* Add special error message for fields that are moved out of an inout
argument but not moved back before returning

Notes:
* Test validation is disabled until #333
* Shadowing of inout arguments will get a better error message in #338
Closes #333

* Refactor treatment of return variables: Before, we had special logic
to detect return variables to prevent them from being reordered.
However, I realised that it's easier to detect jumps to the exit BB and
just skip signature sorting in that case. This immediately generalised
to inout variables that are outputted.
* Update function compilation to also output inout arguments after the
regular returns
* Enable Hugr validation for the tests
@mark-koch mark-koch requested a review from ss2165 August 22, 2024 07:59
@mark-koch mark-koch marked this pull request as ready for review August 22, 2024 07:59
@mark-koch mark-koch requested a review from a team as a code owner August 22, 2024 07:59
Copy link
Member

@ss2165 ss2165 left a comment

Choose a reason for hiding this comment

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

🔥 🔥 🔥 🔥

big fan of the diligent tracking

@mark-koch mark-koch added this pull request to the merge queue Aug 22, 2024
Merged via the queue into main with commit 060649b Aug 22, 2024
3 checks passed
@mark-koch mark-koch deleted the feat/inout branch August 22, 2024 08:42
github-merge-queue bot pushed a commit that referenced this pull request Sep 11, 2024
🤖 I have created a release *beep* *boop*
---


## [0.10.0](v0.9.0...v0.10.0)
(2024-09-11)


### ⚠ BREAKING CHANGES

* Bumped the `hugr` dependency to `0.8.0`
* `GuppyModule.load` no longer loads the content of modules but instead
just brings the name of the module into scope. Use
`GuppyModule.load_all` to get the old behaviour.
* Removed `guppylang.hugr_builder.hugr.Hugr`, compiling a module returns
a `hugr.Package` instead.

### Features

* Add `__version__` field to guppylang
([#473](#473))
([b996c62](b996c62))
* Add angle type ([#449](#449))
([12e41e0](12e41e0))
* Add array literals
([#446](#446))
([a255c02](a255c02))
* Add equality test for booleans
([#394](#394))
([dd702ce](dd702ce)),
closes [#363](#363)
* Add pi constant ([#451](#451))
([9d35a78](9d35a78))
* Add qualified imports and make them the default
([#443](#443))
([553ec51](553ec51))
* Allow calling of methods
([#440](#440))
([5a59da3](5a59da3))
* Allow imports of function definitions and aliased imports
([#432](#432))
([e23b666](e23b666))
* Array indexing ([#415](#415))
([2199b48](2199b48)),
closes [#421](#421)
[#422](#422)
[#447](#447)
* Inout arguments ([#311](#311))
([060649b](060649b)),
closes [#315](#315)
[#316](#316)
[#349](#349)
[#344](#344)
[#321](#321)
[#331](#331)
[#350](#350)
[#340](#340)
[#351](#351)
* range() with single-argument
([#452](#452))
([d05f369](d05f369))
* Skip checking of redefined functions
([#457](#457))
([7f9ad32](7f9ad32))
* Support `nat`/`int` ↔ `bool` cast operations
([#459](#459))
([3b778c3](3b778c3))
* Use `hugr-cli` for validation
([#455](#455))
([1d0667b](1d0667b))
* Use cell name instead of file for notebook errors
([#382](#382))
([d542601](d542601))
* Use the hugr builder
([536abf9](536abf9))


### Bug Fixes

* Fix and update demo notebook
([#376](#376))
([23b2a15](23b2a15))
* Fix linearity checking bug
([#441](#441))
([0b8ea21](0b8ea21))
* Fix struct definitions in notebooks
([#374](#374))
([b009465](b009465))


### Documentation

* Update readme, `cargo build` instead of `--extra validation`
([#471](#471))
([c2a4c86](c2a4c86))


### Miscellaneous Chores

* Update hugr to `0.8.0`
([#454](#454))
([b02e0d0](b02e0d0))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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