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: No polymorphic closures #906

Merged
merged 33 commits into from
Apr 9, 2024
Merged

feat: No polymorphic closures #906

merged 33 commits into from
Apr 9, 2024

Conversation

acl-cqc
Copy link
Contributor

@acl-cqc acl-cqc commented Apr 2, 2024

  • Type::Function now stores only a FunctionType, not a PolyFuncType
  • PolyFuncType remains, for OpDef's and FuncDefn/Decl's
  • EdgeKind::Static now replaced by EdgeKind::Const (a type) EdgeKind::Static (a PolyFuncType)
  • Remove LeafOp::TypeApply, repurpose validation code onto Call
  • Thus, progressively remove all impl Substitutions except for struct SubstValues, which can become Substitution
  • Update spec, introducing "Static" and "Dataflow" edge kinds as broader classes of the other edge kinds, and polymorphic "type schemes" vs monomorphic "Function types".
  • Update serialization schema and add roundtrip test of a Noop operating on a value of function type

fixes #904

This should enable resolving #788 and related capture/closure issues if we forbid edges into a FuncDefn from outside (@doug-q)

BREAKING CHANGE: EdgeKind::{Static -> Const}, add new EdgeKind::Function, Type contains only monomorphic functions, remove TypeApply.

Copy link

codecov bot commented Apr 2, 2024

Codecov Report

Attention: Patch coverage is 72.38806% with 37 lines in your changes are missing coverage. Please review.

Project coverage is 85.46%. Comparing base (100e2cc) to head (1777329).

Files Patch % Lines
hugr/src/hugr/rewrite/replace.rs 0.00% 8 Missing ⚠️
hugr/src/hugr/validate.rs 75.00% 8 Missing ⚠️
hugr/src/ops/constant.rs 53.84% 5 Missing and 1 partial ⚠️
hugr/src/ops/dataflow.rs 72.22% 4 Missing and 1 partial ⚠️
hugr/src/hugr/serialize.rs 62.50% 0 Missing and 3 partials ⚠️
hugr/src/hugr/views/render.rs 78.57% 3 Missing ⚠️
hugr/src/extension.rs 50.00% 1 Missing ⚠️
hugr/src/extension/op_def.rs 0.00% 0 Missing and 1 partial ⚠️
hugr/src/types.rs 95.23% 1 Missing ⚠️
hugr/src/types/poly_func.rs 88.88% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #906      +/-   ##
==========================================
- Coverage   85.63%   85.46%   -0.18%     
==========================================
  Files          78       78              
  Lines       14444    14176     -268     
  Branches    14444    14176     -268     
==========================================
- Hits        12369    12115     -254     
+ Misses       1436     1432       -4     
+ Partials      639      629      -10     
Flag Coverage Δ
rust 85.46% <72.38%> (-0.18%) ⬇️

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.

|| OpTag::Function.is_superset(from_optype.tag()))
{
return Err(InterGraphEdgeError::InvalidConstSrc {
let reqd_optype = match typ {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

TBH I think this check is more of an assertion about the spec, than something we really need to check at runtime; there is no other way to construct nodes with such out-ports, and as such I don't think it's even possible to test the error path here. So I'd be happy to remove both these checks and the relevant error variant....?

/// A reference to a static value definition.
Static(Type),
/// A reference to a static value definition - Const or Function
Static(StaticEdgeData),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the bit I'm least sure about. The other possibility is to have two distinct EdgeKinds (i.e. one new) - ideally I'd call them Const (rather than Static) and Function, or perhaps StaticValue and StaticFunction. We even had ConstE edges in the spec at one point....

Copy link
Collaborator

Choose a reason for hiding this comment

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

I like Const and Function. I think that would make some of the code clearer, versus this hierarchy of edge types. You do comment that many statements about Static edges in the spec apply equally to both kinds, so not entirely sure, but even so a little repetition in the spec may be a price worth paying.

@@ -124,7 +124,9 @@ carry an edge weight:
- `Value` edges carry typed data at runtime. They have a *port* at each end, associated
with the source and target nodes. They have an `AnyType`as an edge weight.
- `Static` edges are similar to `Value` edges but carry static data (knowable at
compilation time). They have a `CopyableType` as an edge weight.
compilation time). These come in two subkinds with different edge weights:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

See also https://github.com/CQCL/hugr/pull/906/files#r1549924162, although there is no requirement to go the same way in the spec as the code. However I found many references to Static edges in the spec that were true for both value and function subkinds!

|| OpTag::Function.is_superset(from_optype.tag()))
{
return Err(InterGraphEdgeError::InvalidConstSrc {
let reqd_optype = match typ {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah I agree if the error path is unreachable we should delete the check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

/// A reference to a static value definition.
Static(Type),
/// A reference to a static value definition - Const or Function
Static(StaticEdgeData),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I like Const and Function. I think that would make some of the code clearer, versus this hierarchy of edge types. You do comment that many statements about Static edges in the spec apply equally to both kinds, so not entirely sure, but even so a little repetition in the spec may be a price worth paying.

```

Note that both TypeArgs of kind both Type and Extensions may also include variables.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
Note that both TypeArgs of kind both Type and Extensions may also include variables.
Note that TypeArgs of kind both Type and Extensions may also include variables.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good, but I realized these lines were just repeating the -- comments in the fragment above, so went with the comments

@ss2165
Copy link
Member

ss2165 commented Apr 5, 2024

quite possible that test coverage wasn't there. I'm out of date on the serialization I think, tagging in @aborgna-q

@aborgna-q
Copy link
Collaborator

My changes only made sure that the schema we are checking against is up-to-date, but the tests remain quite spotty.

@doug-q was working on adding more coverage over all serialisable hugrs.

- `Static` edges are similar to `Value` edges but carry static data (knowable at
compilation time). They have a `CopyableType` as an edge weight.
- `Const` edges are similar to `Value` edges but carry static data (knowable at
compilation time). These has as edge weight a `CopyableType`.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
compilation time). These has as edge weight a `CopyableType`.
compilation time). These have as edge weight a `CopyableType`.

Comment on lines 136 to 137
* *Static* edges are the union of the `Const` and `Function` edges
* *dataflow* edges are the union of `Value` and Static (thus, `Value`, `Const` and `Function`)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
* *Static* edges are the union of the `Const` and `Function` edges
* *dataflow* edges are the union of `Value` and Static (thus, `Value`, `Const` and `Function`)
* *Static* edges are the union of the `Const` and `Function` edges.
* *Dataflow* edges are the union of `Value` and Static (thus, `Value`, `Const` and `Function`).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I guess so. Quite a few existing uses of "dataflow edges" thus also capitalized.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually I was only suggesting to make each bullet here a full sentence, hence the capitalization. But capitalizing Dataflow more generally seems reasonable.

The operation declares the arguments required by the `compute_signature` function as a list
of TypeParams; if this successfully returns a `Function` type, then that may then require
additional TypeParams.
of TypeParams; if this successfully returns a typ scheme, that may have additional TypeParams
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
of TypeParams; if this successfully returns a typ scheme, that may have additional TypeParams
of TypeParams; if this successfully returns a type scheme, that may have additional TypeParams

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ha (thank you!) - maybe I meant a tip scheme, for dividing gratuities between team members

| `LoadConstant` | 0, 1 | +, ✱ | 1, 0 | 0, 0 | 0, 0 | 1, 0 | |
| `Input` | 0, ✱ | 0, ✱ | 0, 0 | 0, 0 | 0, 0 | 1, 0 | |
| `Output` | ✱, 0 | ✱, 0 | 0, 0 | 0, 0 | 0, 0 | 1, 0 | |
| `LeafOp` | ✱, ✱ | ✱, ✱ | ✱, 0 | *, 0 | 0, 0 | 1, 0 | |
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can a LeafOp have Function inputs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good spot! At the time I wasn't really sure what a LeafOp was, and thought it might include some of the other rows such as LoadConstant or Call, hence Static: *,0. However I now see that LeafOp should be MakeTuple, UnpackTuple, Tag, Lift, Noop and extension ops, so indeed, no Const or Function inputs or outputs. Done, thanks :-)

@acl-cqc
Copy link
Contributor Author

acl-cqc commented Apr 8, 2024

Thanks, Alec!

I've added a new roundtrip serialization test with an op on function values, which test was passing on main but failing to satisfy the schema here; and then updated the schema so it passes. So I think everything I originally wanted to include is now in here.

@aborgna-q serial_hugr.py was introduced at v1 in #888 but the version was left at v1 in intervening PRs e.g. #891. I am therefore assuming that I should not be bumping that to v2 here?

@acl-cqc acl-cqc requested a review from cqc-alec April 8, 2024 20:24
@aborgna-q
Copy link
Collaborator

@aborgna-q serial_hugr.py was introduced at v1 in #888 but the version was left at v1 in intervening PRs e.g. #891. I am therefore assuming that I should not be bumping that to v2 here?

Correct. We still haven't released any new (non-alpha) version with the v1 schema, so no need to bump it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I notice that the description of PolyFuncType is identical to that of FunctionType. Perhaps this was a copy-and-paste error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good spot, these were autogenerated from the python which has its own docstrings independent of the rust. I've done some updating of all of these.

@acl-cqc acl-cqc added this pull request to the merge queue Apr 9, 2024
Merged via the queue into main with commit b05dd6b Apr 9, 2024
18 of 19 checks passed
@acl-cqc acl-cqc deleted the feat/no_polymorphic_closures branch April 9, 2024 11:15
github-merge-queue bot pushed a commit that referenced this pull request Apr 15, 2024
## 🤖 New release
* `hugr`: 0.3.0-alpha.1 -> 0.3.0-alpha.2 (⚠️ API breaking changes)

### ⚠️ `hugr` breaking changes

```
--- failure enum_missing: pub enum removed or renamed ---

Description:
A publicly-visible enum cannot be imported by its prior path. A `pub use` may have been removed, or the enum itself 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.30.0/src/lints/enum_missing.ron

Failed in:
  enum hugr::ops::custom::ExternalOp, previously in file /tmp/.tmpZslYkR/hugr/src/ops/custom.rs:20
  enum hugr::ops::leaf::LeafOp, previously in file /tmp/.tmpZslYkR/hugr/src/ops/leaf.rs:21
  enum hugr::ops::LeafOp, previously in file /tmp/.tmpZslYkR/hugr/src/ops/leaf.rs:21

--- failure enum_variant_added: enum variant added on exhaustive enum ---

Description:
A publicly-visible enum without #[non_exhaustive] has a new variant.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#enum-variant-new
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.30.0/src/lints/enum_variant_added.ron

Failed in:
  variant ConstTypeError:NotMonomorphicFunction in /tmp/.tmpoZAGEw/hugr/hugr/src/ops/constant.rs:98
  variant ConstTypeError:NotMonomorphicFunction in /tmp/.tmpoZAGEw/hugr/hugr/src/ops/constant.rs:98
  variant SignatureError:CallIncorrectlyAppliesType in /tmp/.tmpoZAGEw/hugr/hugr/src/extension.rs:172

--- failure enum_variant_missing: pub enum variant removed or renamed ---

Description:
A publicly-visible enum has at least one variant that 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.30.0/src/lints/enum_variant_missing.ron

Failed in:
  variant InterGraphEdgeError::InvalidConstSrc, previously in file /tmp/.tmpZslYkR/hugr/src/hugr/validate.rs:774
  variant OpType::LeafOp, previously in file /tmp/.tmpZslYkR/hugr/src/ops.rs:30
  variant SignatureError::TypeApplyIncorrectCache, previously in file /tmp/.tmpZslYkR/hugr/src/extension.rs:171
  variant EdgeKind::Static, previously in file /tmp/.tmpZslYkR/hugr/src/types.rs:44
  variant ConstTypeError::FunctionTypeMissing, previously in file /tmp/.tmpZslYkR/hugr/src/ops/constant.rs:99
  variant ConstTypeError::FunctionTypeMissing, previously in file /tmp/.tmpZslYkR/hugr/src/ops/constant.rs:99

--- 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.30.0/src/lints/inherent_method_missing.ron

Failed in:
  OpType::as_leaf_op, previously in file /tmp/.tmpZslYkR/hugr/src/ops.rs:103
  OpType::is_leaf_op, previously in file /tmp/.tmpZslYkR/hugr/src/ops.rs:103

--- failure method_parameter_count_changed: pub method parameter count changed ---

Description:
A publicly-visible method now takes a different number of parameters.
        ref: https://doc.rust-lang.org/cargo/reference/semver.html#fn-change-arity
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.30.0/src/lints/method_parameter_count_changed.ron

Failed in:
  hugr::types::PolyFuncType::validate now takes 2 parameters instead of 3, in /tmp/.tmpoZAGEw/hugr/hugr/src/types/poly_func.rs:76

--- failure struct_missing: pub struct removed or renamed ---

Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself 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.30.0/src/lints/struct_missing.ron

Failed in:
  struct hugr::ops::leaf::TypeApplication, previously in file /tmp/.tmpZslYkR/hugr/src/ops/leaf.rs:82
```

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

<blockquote>

## 0.3.0-alpha.2 (2024-04-15)

### Documentation

- Specify direct children in `HugrView::children`
([#921](#921))
- Add logo svg to readme and spec
([#925](#925))

### Features

- [**breaking**] No polymorphic closures
([#906](#906))
- [**breaking**] Flatten `LeafOp`
([#922](#922))

### Refactor

- Combine ExtensionSolutions (no separate closure)
([#884](#884))
- [**breaking**] Merge `CustomOp` and `ExternalOp`.
([#923](#923))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/MarcoIeni/release-plz/).

---------

Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Agustin Borgna <agustin.borgna@quantinuum.com>
This was referenced Apr 15, 2024
github-merge-queue bot pushed a commit that referenced this pull request Apr 15, 2024
🤖 I have created a release *beep* *boop*
---


## 0.1.0 (2024-04-15)


### ⚠ BREAKING CHANGES

* Flatten `LeafOp` ([#922](#922))
* EdgeKind::{Static -> Const}, add new EdgeKind::Function, Type contains
only monomorphic functions, remove TypeApply.
* **py:** Rename package to `hugr`
([#913](#913))

### Features

* Flatten `LeafOp` ([#922](#922))
([3598913](3598913))
* No polymorphic closures
([#906](#906))
([b05dd6b](b05dd6b))
* **py:** Rename package to `hugr`
([#913](#913))
([9fe65db](9fe65db))

---
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: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Agustín Borgna <121866228+aborgna-q@users.noreply.github.com>
aborgna-q added a commit that referenced this pull request Apr 23, 2024
🤖 I have created a release *beep* *boop*
---


## 0.1.0 (2024-04-15)


### ⚠ BREAKING CHANGES

* Flatten `LeafOp` ([#922](#922))
* EdgeKind::{Static -> Const}, add new EdgeKind::Function, Type contains
only monomorphic functions, remove TypeApply.
* **py:** Rename package to `hugr`
([#913](#913))

### Features

* Flatten `LeafOp` ([#922](#922))
([3598913](3598913))
* No polymorphic closures
([#906](#906))
([b05dd6b](b05dd6b))
* **py:** Rename package to `hugr`
([#913](#913))
([9fe65db](9fe65db))

---
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: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Agustín Borgna <121866228+aborgna-q@users.noreply.github.com>
github-merge-queue bot pushed a commit that referenced this pull request Aug 20, 2024
Also some driveby updates e.g. missed in #906.
Closes #1097, #745.
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.

No polymorphic closures
4 participants