-
Notifications
You must be signed in to change notification settings - Fork 7
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
Add RootChecked to guarantee root node type #548
Conversation
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.
Seems fine to me, but I would suggest waiting for Agustin's review too
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 with doing root-checked references, but from knowing how the rest of the codebase went we will also need a mutable versions at some point.
What do you think about having a
pub struct RootTagged<H, Root>(H, PhantomData<Root>);
impl<H: AsRef<Hugr>, Root: NodeHandle> RootTagged<H, Root> { ... }
instead? (and derive AsMut
too).
Not sure I understand the lifetime stuff well enough, but don't we need the explicit
|
Hmmm, probably not. The likely use case here is when you have an (&)Hugr and want to pass it to something that takes an So yeah, maybe we don't need the lifetime after all....but, that said, what's the advantage of using |
Yup, now done :).
Ok, I persuade myself that the use case of returning a That said, it's a shame to see struct RootTagFactory<H>(PhantomData<H>);
impl<H: AsRef<Hugr>> RootTagFactory<H> {
fn try_new<Root: NodeHandle>(h: H) -> Result<RootTagged<H, Root>> {....}
} so you can then do |
src/hugr/hugrmut.rs
Outdated
where | ||
T: HugrView + AsMut<Hugr>, | ||
{ | ||
impl<T: HugrView + AsMut<Hugr>> HugrMut for T { |
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.
Hmmm, these were a bit drive-by, but they make searching for these quasi-blanket impls much easier. (A one-line search hit impl<T> HugrMut for T
is really not very informative!)
Many things converted to use RootTagged that could just use HugrView
CI failing on existing code due to updates in clippy. Let's fix those in another PR. |
src/hugr/views.rs
Outdated
type RootHandle = Root; | ||
} | ||
|
||
// Note do not implement AsMut<Hugr> - that would get us the `impl HugrMutInternals` |
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 contrary to your initial idea @aborgna-q. If you try to impl AsMut, you'll have to remove the impl of HugrMutInternals (and HugrMut) here, and then the test will fail. The test may be enough to justify removing this comment, possibly.
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.
Uhm, this is an easy pit to fall in.
Since the auto-impl for HugrMutInternals
requires RootTagged
, why not check the root type before dereferencing with as_mut
there?
The generic constraints in impl<T: RootTagged + AsMut<Hugr>> HugrMutInts for T
kind of tell you that you're adding the extra check on top of the reference.
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.
Hmmm, the answer might be - premature optimization, i.e. that the impl HugrMutInternals
for T: AsMut<Hugr>
then gets to skip the check....so ok, let's not prematurely optimize, SGTM ;)
Note there was an unexpected subtle consequence that I had to rule out in 07e4f10
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.
(and this does let anyone call .as_mut().replace_op(...)
and bypass the check, which I'm not very keen on....)
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.
So overall, I have done as you say, but I'm not sure why this is better, TBH
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.
See 2be330d, which HEAD reverts - I actually think I prefer the former; it needs an extra impl HugrMut
(but, empty!) so that seems minimally harmful to me
src/hugr/views.rs
Outdated
type RootHandle = Root; | ||
} | ||
|
||
// Note do not implement AsMut<Hugr> - that would get us the `impl HugrMutInternals` |
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.
Uhm, this is an easy pit to fall in.
Since the auto-impl for HugrMutInternals
requires RootTagged
, why not check the root type before dereferencing with as_mut
there?
The generic constraints in impl<T: RootTagged + AsMut<Hugr>> HugrMutInts for T
kind of tell you that you're adding the extra check on top of the reference.
…ult methods only)
…(w/ default methods only)" This reverts commit 2be330d.
33f9d27
to
91d1dea
Compare
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'm now allowing making one RootChecked on top of another, or indeed on top of a SiblingMut, so long as the root-type bound is only narrowed, rather than only on top of something whose RootHandle was Any, as before. And hiding |
7abf1c5
to
89ced66
Compare
89ced66
to
783e5a3
Compare
AsRef<Hugr>
with a fixed RootHandle..as_ref()
, throwing away the extra information in the RootHandlereplace_op
does not break the bound on root-type.as_mut()
as that would allow bypassing and invalidating the extra info in the RootHandleRootHandle=Node
to ensure the lack of checking in replace_op there is safe.