-
Notifications
You must be signed in to change notification settings - Fork 13
feat: ReplaceTypes: recursively replace on types too #2442
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
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2442 +/- ##
==========================================
+ Coverage 83.41% 83.48% +0.06%
==========================================
Files 262 262
Lines 51176 51395 +219
Branches 46737 46956 +219
==========================================
+ Hits 42689 42907 +218
+ Misses 6109 6108 -1
- Partials 2378 2380 +2
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:
|
58a05b1 to
1c9857f
Compare
| } | ||
|
|
||
| /// Options for how the replacement for an op is processed. | ||
| // TODO also need to apply to replacement consts: |
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.
Or do we, see description
| for region_root in regions { | ||
| for n in hugr.descendants(*region_root).collect::<Vec<_>>() { | ||
| changed |= self.change_node(hugr, n)?; | ||
| if n != hugr.entrypoint() && changed { |
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.
Note this is clearly wrong - it means linearization applies to the first node that changes and all nodes coming after that (!)
| for n in hugr.descendants(root).collect::<Vec<_>>() { | ||
| if self.change_node(hugr, n)? { | ||
| changed = true; | ||
| } else if !linearize_unchanged_ops { |
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 should fix the "bug" in the other comment but tests are now breaking!
The goal here is to improve compositionality - if you configure ReplaceTypes to convert type A to type B, and also type B to type C, then if it sees an A it "should" produce a C. (This is not the case at present, you'll get a B.) Likewise for op-replacements containing ops that themselves would be replaced - so this is a step towards addressing #2668 (via the second route therein).
I'd kinda like to turn this option on by default, but that would be a behaviour-breaking change (very breaking if you e.g. replaced
boolbyEither<bool, Future>- thankfully we replacetket::boolwith...bool_tso that one would be ok - or an op with a DFG containing that op, say; such cases would infinite-loop). There are a couple of possible ways of doing this:replace_(parametrized_)type_recursive(likely 4 methods) as the new "Options-less" methods (i.e. which we consider the "default" methods)...that name's not good thoReplacementOptions::without_recursion()(whereReplacementOptions::default()includes recursion). But that's not really "on by default"....A second consideration is whether we should have methods for consts that take ReplacementOptions too. This is not strictly necessary: unlike replacing types/ops, the callback for replacing consts is given the
&ReplaceTypes(it has to, as the framework cannot see include CustomConsts, whereas it can for custom types or ops). So a const callback can call the ReplaceTypes again when it's done (if it's changed the outermost type constructor); but that seems a hard ask for callback authors to remember....Thoughts on both?