-
Notifications
You must be signed in to change notification settings - Fork 14
feat: traits for transforming Types/TypeArgs/etc. #1991
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
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1991 +/- ##
==========================================
+ Coverage 83.65% 83.72% +0.06%
==========================================
Files 209 209
Lines 38993 39167 +174
Branches 35666 35838 +172
==========================================
+ Hits 32620 32791 +171
+ Misses 4533 4530 -3
- Partials 1840 1846 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
@doug-q I promise you were randomly picked, and it has nothing to do with my having mentioned you in the description! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this a lot. I need to do another more careful pass before approving
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice Alan.
I don't prefer &mut self
over self
. I don't have a strong opinion either way. Ideally we would not clone if we didn't have to, and ideally we would report whether there was any change. I expect that both of these optimisations are in practise irrelevant. If you would prefer the "functional" interface(or both interfaces, this is easy because of the trait-style interface), go for it.
TypeArg::BoundedNat { .. } | ||
| TypeArg::String { .. } | ||
| TypeArg::Extensions { .. } | ||
| TypeArg::Variable { .. } => Ok(false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case should be tested
if args_changed { | ||
*self = Self::new_extension( | ||
custom_type | ||
.get_type_def(&custom_type.get_extension()?)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked at the other callsites of get_type_def, but I don't like it. I would prefer to inline it here, and just "pub(crate)"-icise get_extension
. If you disagree I'm fine with this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd look at it the other way - how about removing get_extension
by inlining into get_type_def
and "pub(crate)"-icise only get_type_def
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are three callers of get_type_def
and they all call get_extension
first with only a slight change in how they handle errors from get_extension
(i.e. one caller panics....on errors from either, so that's fine to combine both errors)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that makes sense, but I do think get_extension
is a perfectly reasonable thing to want to do. Up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OIC. The thing is that the caller has to hang onto the result Arc from get_extension
for the lifetime of the &TypeDef
. Ugh. I guess if Extension::get_type
returned an Option<Arc<TypeDef>>
rather than an Option<&TypeDef>
then this would go away but otherwise we're a bit stuck.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I don't think the implementation of get_type_def
is great either, but it seems mad to make the caller do that work (looking up the CustomType's type-id in the extension). Could change it to an Option rather than Result if that's preferable but the SignatureError is appropriate in at least a couple of cases, so I'm inclined to leave it.
#2001 covers what I think is the way forward but no need to do that in this PR.
Hmmm, I guess a lot depends on how important it is no "not clone if we didn't have to".
The other advantage is that determining whether anything is changed requires an additional traversal (as we are not sharing with Arcs - otherwise a "pointer-eq" check might be an acceptable safe approximation). And, the So the best alternative seems to be, clone even when not needed, and drop change-checking. Hmmm, boo, ok, maybe I'll drop this objection then...;) |
## 🤖 New release * `hugr-model`: 0.18.0 -> 0.18.1 (✓ API compatible changes) * `hugr-core`: 0.15.0 -> 0.16.0 (✓ API compatible changes) * `hugr-llvm`: 0.15.0 -> 0.16.0 (✓ API compatible changes) * `hugr-passes`: 0.15.0 -> 0.16.0 (✓ API compatible changes) * `hugr`: 0.15.0 -> 0.16.0 (✓ API compatible changes) * `hugr-cli`: 0.15.0 -> 0.16.0 (✓ API compatible changes) <details><summary><i><b>Changelog</b></i></summary><p> ## `hugr-model` <blockquote> ## [0.18.0](hugr-model-v0.17.1...hugr-model-v0.18.0) - 2025-03-14 ### Bug Fixes - Hugr-model using undeclared derive_more features ([#1940](#1940)) ### New Features - *(hugr-model)* [**breaking**] Add `read_from_reader` and `write_to_writer` for streaming reads and writes. ([#1871](#1871)) - `hugr-model` AST ([#1953](#1953)) ### Refactor - *(hugr-model)* Reexport `bumpalo` from `hugr-model` ([#1870](#1870)) </blockquote> ## `hugr-core` <blockquote> ## [0.16.0](hugr-core-v0.15.0...hugr-core-v0.16.0) - 2025-03-21 ### Bug Fixes - correct `CallIndirect` tag from `FnCall` to `DataflowChild` ([#2006](#2006)) - StaticArrayValue serialisation ([#2009](#2009)) ### New Features - traits for transforming Types/TypeArgs/etc. ([#1991](#1991)) - add exit operation to prelude ([#2008](#2008)) - Add llvm codegen for collections.static_array ([#2003](#2003)) </blockquote> ## `hugr-llvm` <blockquote> ## [0.16.0](hugr-llvm-v0.15.0...hugr-llvm-v0.16.0) - 2025-03-21 ### Bug Fixes - Remove return from val_or_panic ([#1999](#1999)) ### New Features - add exit operation to prelude ([#2008](#2008)) - Add llvm codegen for collections.static_array ([#2003](#2003)) </blockquote> ## `hugr-passes` <blockquote> ## [0.16.0](hugr-passes-v0.15.0...hugr-passes-v0.16.0) - 2025-03-21 ### Bug Fixes - correct `CallIndirect` tag from `FnCall` to `DataflowChild` ([#2006](#2006)) </blockquote> ## `hugr` <blockquote> ## [0.16.0](hugr-v0.15.0...hugr-v0.16.0) - 2025-03-21 ### Bug Fixes - correct `CallIndirect` tag from `FnCall` to `DataflowChild` ([#2006](#2006)) - StaticArrayValue serialisation ([#2009](#2009)) ### New Features - traits for transforming Types/TypeArgs/etc. ([#1991](#1991)) - add exit operation to prelude ([#2008](#2008)) - Add llvm codegen for collections.static_array ([#2003](#2003)) - *(hugr-py)* Support envelope compression ([#1994](#1994)) </blockquote> ## `hugr-cli` <blockquote> ## [0.16.0](hugr-cli-v0.15.0...hugr-cli-v0.16.0) - 2025-03-21 ### New Features - *(hugr-cli)* Nicer error when passing a non-envelope file ([#2007](#2007)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/release-plz/release-plz/). --------- Co-authored-by: Douglas Wilson <[email protected]>
Allows fallible transformation (whereas Substitution is infallible), by implementing new trait
TypeTransformer
. At present this only allows replacing Extension types (with arbitrary types), but we could easily add new trait methods (with default{Ok(None)}
to make no change) in the future.Trait
Transformable
is more of an implementation detail, it allows commoning up lots of list traversal, I don't really foresee anyone external implementing it, but it doesn't seem worth going to any effort to stop them if they want to.The
(&mut self, ...) -> Result<bool, ...>
interface means you may want to clone first in order to recover from an error, but avoids an extra traversal for change-checking (i.e. it's easier to build an(&self, ...) -> Result<Self, ...>
interface on top of this, than the other way around).