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: make FuncDecl/FuncDefn polymorphic #692

Merged
merged 28 commits into from
Nov 21, 2023
Merged

feat: make FuncDecl/FuncDefn polymorphic #692

merged 28 commits into from
Nov 21, 2023

Conversation

acl-cqc
Copy link
Contributor

@acl-cqc acl-cqc commented Nov 14, 2023

  • Change FuncDecl and FuncDefn from storing FunctionType to PolyFuncType
  • Change declare_function and other builder methods to take PolyFuncType rather than Signature. The input-extensions of the Signature were only used for the FuncDefn node itself and it seems saner, and tests pass ok, for the builder to set the input-extensions of the FuncDefn node itself to pure==empty in all cases. Note this makes bug: Two call nodes for the same function must have matching resources #695 slightly even more severe, but I feel we should just take this into account when fixing that bug.
    • Much of the bulk of the PR is thus changing (someFunctionType).pure() to .into()...
  • Restructure validation. Break out the op-type specific checks that type args were declared, into a hierarchical traversal (rather than iterating over the Hugr's nodes), so they can gather binders from the nearest enclosing FuncDefn (potentially several levels above in the hierarchy). Move validate_port (and hence validate_edge) here because ports/edges inside a FuncDefn may have types using its parameters.
    • Also do not allow Static edges to refer to TVs declared outside. (The Static edge from a polymorphic FuncDefn contains a PolyFuncType i.e. declaring its own type vars, so they are not free.)
  • Update OpDef to properly check_args etc. reflecting that we may need to pass some args to the binary function and then more args to the returned PolyFuncType.
    • Also drop impl TypeParametrised for OpDef
  • Add TypeArgs to Call, and builder fn call(); also give the latter an ExtensionRegistry argument
  • Finally add impl From<TypeBound> for TypeParam, which we probably should have done much earlier.

@acl-cqc acl-cqc changed the base branch from main to fix/funcdefn-inference November 14, 2023 20:17
pub fn check_args(&self, args: &[TypeArg]) -> Result<(), SignatureError> {
self.check_args_impl(args)
/// Check provided type arguments are valid against [ExtensionRegistry],
/// against parameters, and that no type variables are used as static arguments
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmmm, I could link to [Self::params()], but I also wonder if we should keep that, or switch to static_params() and substitutable_params(&[TypeArg]) (where the latter has to call the custom binary function)

src/hugr/validate.rs Outdated Show resolved Hide resolved
@acl-cqc acl-cqc changed the title Give FuncDecl/FuncDefn binders (by storing PolyFuncType) feat: give FuncDecl/FuncDefn binders (by storing PolyFuncType) Nov 14, 2023
Base automatically changed from fix/funcdefn-inference to main November 16, 2023 13:45
src/hugr/validate.rs Outdated Show resolved Hide resolved
@acl-cqc acl-cqc marked this pull request as ready for review November 16, 2023 18:47
@@ -612,6 +612,14 @@ pub trait Dataflow: Container {
})
}
};
let signature = type_scheme.instantiate(type_args, exts).map_err(|e| {
BuildError::InvalidHUGR(ValidationError::SignatureError {
// TODO this is rather a horrendous hack. Do we need some way of returning a SignatureError without a node
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess we should make a new error constructor for this

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, done, hope the comment clarifies

@acl-cqc acl-cqc mentioned this pull request Nov 19, 2023
Copy link

codecov bot commented Nov 20, 2023

Codecov Report

Attention: 40 lines in your changes are missing coverage. Please review.

Comparison is base (4a8d190) 84.32% compared to head (7e8c515) 84.29%.
Report is 2 commits behind head on main.

Files Patch % Lines
src/hugr/validate/test.rs 85.39% 2 Missing and 11 partials ⚠️
src/hugr/validate.rs 82.00% 6 Missing and 3 partials ⚠️
src/extension/op_def.rs 77.27% 0 Missing and 5 partials ⚠️
src/builder/module.rs 73.33% 0 Missing and 4 partials ⚠️
src/builder/build_traits.rs 81.81% 0 Missing and 2 partials ⚠️
src/hugr/views/sibling_subgraph.rs 66.66% 0 Missing and 2 partials ⚠️
src/builder/cfg.rs 0.00% 0 Missing and 1 partial ⚠️
src/builder/dataflow.rs 90.90% 0 Missing and 1 partial ⚠️
src/builder/tail_loop.rs 90.90% 0 Missing and 1 partial ⚠️
src/hugr/views.rs 75.00% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #692      +/-   ##
==========================================
- Coverage   84.32%   84.29%   -0.03%     
==========================================
  Files          66       66              
  Lines       13000    13119     +119     
  Branches    13000    13119     +119     
==========================================
+ Hits        10962    11059      +97     
- Misses       1274     1278       +4     
- Partials      764      782      +18     

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

src/ops/validate.rs Show resolved Hide resolved
src/hugr/views/sibling_subgraph.rs Outdated Show resolved Hide resolved
OpType::DFG(DFG { signature })
| OpType::FuncDecl(FuncDecl { signature, .. })
| OpType::FuncDefn(FuncDefn { signature, .. }) => Some(signature),
OpType::DFG(DFG { signature }) => Some(signature.clone().into()),
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a little bit wary of converting signatures into PolyFuncTypes like this, as we're forgetting that there are no free variables in the body!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the signature for a DFG, there is no requirement that the body is closed. The body could well have type variables bound in the nearest enclosing FuncDefn ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I see. in my head there was the distinction between body's of PolyFuncType which could have free variables, and I was assuming that FunctionTypes created every other way would be closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a FunctionType for every operation in the implementation/definition of the function, so if the latter has a polymorphic type, operations will too... (and similarly we have a Type for most edges too)

@croyzor
Copy link
Contributor

croyzor commented Nov 21, 2023

do we also want to add binders to AliasDecl/AliasDefn (and corresponding TypeArgs to Type::Alias)?

I would think so

we may want some way to have simple DFG hugrs declaring their own type variables at top level

Maybe make a discussion for this?

what about Const? at present we should have some way to put a polymorphic lambda in a Const; we might (or not) also want polymorphic empty lists etc.

It's not looking good for polymorphic empty lists at the moment! But the polymorphic lambda probably. This should be an issue or a discussion

@acl-cqc acl-cqc changed the title feat: give FuncDecl/FuncDefn binders (by storing PolyFuncType) feat: make FuncDecl/FuncDefn polymorphic Nov 21, 2023
@acl-cqc acl-cqc added this pull request to the merge queue Nov 21, 2023
Merged via the queue into main with commit 2f952ab Nov 21, 2023
12 checks passed
@acl-cqc acl-cqc deleted the new/poly_funcdeclfn branch November 21, 2023 17:09
github-merge-queue bot pushed a commit that referenced this pull request Nov 28, 2023
Main uses were removed in #700 and #692 - so just update tests that were
using Signature to store two things together.

closes #691
@github-actions github-actions bot mentioned this pull request Jan 3, 2024
github-merge-queue bot pushed a commit that referenced this pull request Jan 15, 2024
## 🤖 New release
* `quantinuum-hugr`: 0.1.0

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

<blockquote>

## 0.1.0 (2024-01-15)

### Bug Fixes

- Subgraph boundaries with copies
([#440](#440))
- [**breaking**] Use internal tag for SumType enum serialisation
([#462](#462))
- Check kind before unwrap in insert_identity
([#475](#475))
- Allow for variables to get solved in inference
([#478](#478))
- In IdentityInsertion add noop to correct parent
([#477](#477))
- Failing release tests ([#485](#485))
- [**breaking**] Serialise `Value`, `PrimValue`, and `TypeArg` with
internal tags ([#496](#496))
- Serialise custom constants with internal tag
([#502](#502))
- [**breaking**] Reduce max int width in arithmetic extension to 64
([#504](#504))
- HugrView::get_function_type
([#507](#507))
- TODO in resolve_extension_ops: copy across input_extensions
([#510](#510))
- Use given input extensions in `define_function`
([#524](#524))
- Lessen requirements for hugrs in outline_cfg
([#528](#528))
- Make unification logic less strict
([#538](#538))
- Simple replace incorrectly copying metadata
([#545](#545))
- Account for self-referencial constraints
([#551](#551))
- Consider shunted metas when comparing equality
([#555](#555))
- Join labels in issue workflow
([#563](#563))
- Comment out broken priority code
([#562](#562))
- Handling of issues with no priority label
([#573](#573))
- Don't insert temporary wires when extracting a subgraph
([#582](#582))
- Improve convexity checking and fix test
([#585](#585))
- Ignore input->output links in
SiblingSubgraph::try_new_dataflow_subgraph
([#589](#589))
- Enforce covariance of SiblingMut::RootHandle
([#594](#594))
- Erratic stack overflow in infer.rs (live_var)
([#638](#638))
- Work harder in variable instantiation
([#591](#591))
- Actually add the error type to prelude
([#672](#672))
- Serialise dynamically computed opaqueOp signatures
([#690](#690))
- FuncDefns don't require that their extensions match their children
([#688](#688))
- Binary compute_signature returning a PolyFuncType with binders
([#710](#710))
- Use correct number of args for int ops
([#723](#723))
- [**breaking**] Add serde tag to TypeParam enum
([#722](#722))
- Allow widening and narrowing to same width.
([#735](#735))
- Case node should not have an external signature
([#749](#749))
- [**breaking**] Normalize input/output value/static/other ports in
`OpType` ([#783](#783))
- No dataflow_signature for block types
([#792](#792))
- Ignore unsupported test in miri
([#794](#794))
- Include schema rather than read file
([#807](#807))

### Documentation

- Add operation constraint to quantum extension
([#543](#543))
- Coverage check section in DEVELOPMENT.md
([#648](#648))
- Remove "quantum extension" from HUGR spec.
([#694](#694))
- Improve crate-level docs, including example code.
([#698](#698))
- Spec cleanups and clarifications
([#742](#742))
- Spec clarifications ([#738](#738))
- Spec updates ([#741](#741))
- [spec] Remove references to causal cone and Order edges from Input
([#762](#762))
- Mention experimental inference in readme
([#800](#800))
- Collection of spec updates for 0.1
([#801](#801))
- Add schema v0 ([#805](#805))
- Update spec wrt. polymorphism
([#791](#791))

### Features

- Derive things for builder structs
([#229](#229))
- Return a slice of types from the signature
([#238](#238))
- Move `dot_string` to `HugrView`
([#271](#271))
- [**breaking**] Change `TypeParam::USize` to `TypeParam::BoundedNat`
and use in int extensions
([#445](#445))
- TKET2 compatibility requirements
([#450](#450))
- Split methods between `HugrMut` and `HugrMutInternals`
([#441](#441))
- Add `HugrView::node_connections` to get all links between nodes
([#460](#460))
- Location information in extension inference error
([#464](#464))
- Add T, Tdg, X gates ([#466](#466))
- [**breaking**] Add `ApplyResult` associated type to `Rewrite`
([#472](#472))
- Implement rewrite `IdentityInsertion`
([#474](#474))
- Instantiate inferred extensions
([#461](#461))
- Default DFG builders to open extension sets
([#473](#473))
- Some helper methods ([#482](#482))
- Extension inference for conditional nodes
([#465](#465))
- Add ConvexChecker ([#487](#487))
- Add clippy lint for mut calls in a debug_assert
([#488](#488))
- Default more builder methods to open extension sets
([#492](#492))
- Port is serializable ([#489](#489))
- More general portgraph references
([#494](#494))
- Add extension deltas to CFG ops
([#503](#503))
- Implement petgraph traits on Hugr
([#498](#498))
- Make extension delta a parameter of CFG builders
([#514](#514))
- [**breaking**] SiblingSubgraph does not borrow Hugr
([#515](#515))
- Validate TypeArgs to ExtensionOp
([#509](#509))
- Derive Debug & Clone for `ExtensionRegistry`.
([#530](#530))
- Const nodes are built with some extension requirements
([#527](#527))
- Some python errors and bindings
([#533](#533))
- Insert_hugr/insert_view return node map
([#535](#535))
- Add `SiblingSubgraph::try_from_nodes_with_checker`
([#547](#547))
- PortIndex trait for undirected port parameters
([#553](#553))
- Insert/extract subgraphs from a HugrView
([#552](#552))
- Add `new_array` operation to prelude
([#544](#544))
- Add a `DataflowParentID` node handle
([#559](#559))
- Make TypeEnum and it's contents public
([#558](#558))
- Optional direction check when querying a port index
([#566](#566))
- Extension inference for CFGs
([#529](#529))
- Better subgraph verification errors
([#587](#587))
- Compute affected nodes for `SimpleReplacement`
([#600](#600))
- Move `SimpleReplace::invalidation_set` to the `Rewrite` trait
([#602](#602))
- [**breaking**] Resolve extension ops (mutating Hugr) in
(infer_and_->)update_validate
([#603](#603))
- Add accessors for node index and const values
([#605](#605))
- [**breaking**] Expose the value of ConstUsize
([#621](#621))
- Nicer debug and display for core types
([#628](#628))
- [**breaking**] Static checking of Port direction
([#614](#614))
- Builder and HugrMut add_op_xxx default to open extensions
([#622](#622))
- [**breaking**] Add panicking integer division ops
([#625](#625))
- Add hashable `Angle` type to Quantum extension
([#608](#608))
- [**breaking**] Remove "rotations" extension.
([#645](#645))
- Port.as_directed to match on either direction
([#647](#647))
- Impl GraphRef for PetgraphWrapper
([#651](#651))
- Provide+implement Replace API
([#613](#613))
- Require the node's metadata to always be a Map
([#661](#661))
- [**breaking**] Polymorphic function types (inc OpDefs) using dyn trait
([#630](#630))
- Make prelude error type public
([#669](#669))
- Shorthand for retrieving custom constants from `Const`, `Value`
([#679](#679))
- [**breaking**] HugrView API improvements
([#680](#680))
- Make FuncDecl/FuncDefn polymorphic
([#692](#692))
- [**breaking**] Simplify `SignatureFunc` and add custom arg validation.
([#706](#706))
- [**breaking**] Drop the `pyo3` feature
([#717](#717))
- [**breaking**] `OpEnum` trait for common opdef functionality
([#721](#721))
- MakeRegisteredOp trait for easier registration
([#726](#726))
- Getter for `PolyFuncType::body`
([#727](#727))
- `Into<OpType>` for custom ops
([#731](#731))
- Always require a signature in `OpaqueOp`
([#732](#732))
- Values (and hence Consts) know their extensions
([#733](#733))
- [**breaking**] Use ConvexChecker trait
([#740](#740))
- Custom const for ERROR_TYPE
([#756](#756))
- Implement RemoveConst and RemoveConstIgnore
([#757](#757))
- Constant folding implemented for core and float extension
([#769](#769))
- Constant folding for arithmetic conversion operations
([#720](#720))
- DataflowParent trait for getting inner signatures
([#782](#782))
- Constant folding for logic extension
([#793](#793))
- Constant folding for list operations
([#795](#795))
- Add panic op to prelude
([#802](#802))
- Const::from_bool function
([#803](#803))

### HugrMut

- Validate nodes for set_metadata/get_metadata_mut, too
([#531](#531))

### HugrView

- Validate nodes, and remove Base
([#523](#523))

### Miscellaneous Tasks

- [**breaking**] Update portgraph 0.10 and pyo3 0.20
([#612](#612))
- [**breaking**] Hike MSRV to 1.75
([#761](#761))

### Performance

- Use lazy static definittion for prelude registry
([#481](#481))

### Refactor

- Move `rewrite` inside `hugr`, `Rewrite` -> `Replace` implementing new
'Rewrite' trait ([#119](#119))
- Use an excluded upper bound instead of max log width.
([#451](#451))
- Add extension info to `Conditional` and `Case`
([#463](#463))
- `ExtensionSolution` only consists of input extensions
([#480](#480))
- Remove builder from more DFG tests
([#490](#490))
- Separate hierarchy views
([#500](#500))
- [**breaking**] Use named struct for float constants
([#505](#505))
- Allow NodeType::new to take any Into<Option<ExtensionSet>>
([#511](#511))
- Move apply_rewrite from Hugr to HugrMut
([#519](#519))
- Use SiblingSubgraph in SimpleReplacement
([#517](#517))
- CFG takes a FunctionType
([#532](#532))
- Remove check_custom_impl by inlining into check_custom
([#604](#604))
- Insert_subgraph just return HashMap, make InsertionResult new_root
compulsory ([#609](#609))
- [**breaking**] Rename predicate to TupleSum/UnitSum
([#557](#557))
- Simplify infer.rs/report_mismatch using early return
([#615](#615))
- Move the core types to their own module
([#627](#627))
- Change &NodeType->&OpType conversion into op() accessor
([#623](#623))
- Infer.rs 'fn results' ([#631](#631))
- Be safe ([#637](#637))
- NodeType constructors, adding new_auto
([#635](#635))
- Constraint::Plus stores an ExtensionSet, which is a BTreeSet
([#636](#636))
- [**breaking**] Remove `SignatureDescription`
([#644](#644))
- [**breaking**] Remove add_op_<posn> by generalizing add_node_<posn>
with "impl Into" ([#642](#642))
- Rename accidentally-changed Extension::add_node_xxx back to add_op
([#659](#659))
- [**breaking**] Remove quantum extension
([#670](#670))
- Use type schemes in extension definitions wherever possible
([#678](#678))
- [**breaking**] Flatten `Prim(Type/Value)` in to parent enum
([#685](#685))
- [**breaking**] Rename `new_linear()` to `new_endo()`.
([#697](#697))
- Replace NodeType::signature() with io_extensions()
([#700](#700))
- Validate ExtensionRegistry when built, not as we build it
([#701](#701))
- [**breaking**] One way to add_op to extension
([#704](#704))
- Remove Signature struct
([#714](#714))
- Use `MakeOpDef` for int_ops
([#724](#724))
- [**breaking**] Use enum op traits for floats + conversions
([#755](#755))
- Avoid dynamic dispatch for non-folding operations
([#770](#770))
- Simplify removeconstignore verify
([#768](#768))
- [**breaking**] Unwrap BasicBlock enum
([#781](#781))
- Make clear const folding only for leaf ops
([#785](#785))
- [**breaking**] `s/RemoveConstIgnore/RemoveLoadConstant`
([#789](#789))
- Put extension inference behind a feature gate
([#786](#786))

### SerSimpleType

- Use Vec not TypeRow ([#381](#381))

### SimpleReplace+OutlineCfg

- Use HugrMut methods rather than .hierarchy/.graph
([#280](#280))

### Testing

- Update inference test to not use DFG builder
([#550](#550))
- Strengthen "failing_sccs_test", rename to "sccs" as it's not failing!
([#660](#660))
- [**breaking**] Improve coverage in signature and validate
([#643](#643))
- Use insta snapshots to add dot_string coverage
([#682](#682))
- Miri ignore file-opening test
([#684](#684))
- Unify the serialisation tests
([#730](#730))
- Add schema validation to roundtrips
([#806](#806))

### `ConstValue

- :F64` and `OpaqueOp::new`
([#206](#206))

### Cleanup

- Remove outdated comment
([#536](#536))

### Cosmetic

- Format + remove stray TODO
([#444](#444))

### Doc

- Crate name as README title + add reexport
([#199](#199))

### S/EdgeKind

- :Const/EdgeKind::Static/
([#201](#201))

### Simple_replace.rs

- Use HugrMut::remove_node, includes clearing op_types
([#242](#242))

### Spec

- Remove "Draft 3" from title of spec document.
([#590](#590))
- Rephrase confusing paragraph about TailLoop inputs/outputs
([#567](#567))

### Src/ops/validate.rs

- Common-up some type row calculations
([#254](#254))
</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: Agustín Borgna <121866228+aborgna-q@users.noreply.github.com>
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.

2 participants