Skip to content

Commit

Permalink
fix: enforce covariance of SiblingMut::RootHandle (#594)
Browse files Browse the repository at this point in the history
When creating a SiblingMut with a root whose type is constrained by
being the root of the parent, ensure the "child" SiblingMut only narrows
the constraint
  • Loading branch information
acl-cqc authored Oct 9, 2023
1 parent 26a0aca commit 23754fb
Showing 1 changed file with 28 additions and 2 deletions.
30 changes: 28 additions & 2 deletions src/hugr/views/sibling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,13 @@ pub struct SiblingMut<'g, Root = Node> {
impl<'g, Root: NodeHandle> SiblingMut<'g, Root> {
/// Create a new SiblingMut from a base.
/// Equivalent to [HierarchyView::try_new] but takes a *mutable* reference.
pub fn try_new(hugr: &'g mut impl HugrMut, root: Node) -> Result<Self, HugrError> {
pub fn try_new<Base: HugrMut>(hugr: &'g mut Base, root: Node) -> Result<Self, HugrError> {
if root == hugr.root() && !Base::RootHandle::TAG.is_superset(Root::TAG) {
return Err(HugrError::InvalidTag {
required: Base::RootHandle::TAG,
actual: Root::TAG,
});
}
check_tag::<Root>(hugr, root)?;
Ok(Self {
hugr: hugr.hugr_mut(),
Expand Down Expand Up @@ -366,7 +372,7 @@ mod test {
use crate::builder::{Container, Dataflow, DataflowSubContainer, HugrBuilder, ModuleBuilder};
use crate::extension::PRELUDE_REGISTRY;
use crate::hugr::NodeType;
use crate::ops::handle::{CfgID, DfgID, FuncID, ModuleRootID};
use crate::ops::handle::{CfgID, DataflowParentID, DfgID, FuncID, ModuleRootID};
use crate::ops::{dataflow::IOTrait, Input, OpTag, Output};
use crate::type_row;
use crate::types::{FunctionType, Type};
Expand Down Expand Up @@ -462,4 +468,24 @@ mod test {
simple_dfg_hugr.replace_op(root, bad_nodetype).unwrap();
assert!(simple_dfg_hugr.validate(&PRELUDE_REGISTRY).is_err());
}

#[rstest]
fn sibling_mut_covariance(mut simple_dfg_hugr: Hugr) {
let root = simple_dfg_hugr.root();
let case_nodetype = NodeType::open_extensions(crate::ops::Case {
signature: simple_dfg_hugr.root_type().op_signature(),
});
let mut sib_mut = SiblingMut::<DfgID>::try_new(&mut simple_dfg_hugr, root).unwrap();
// As expected, we cannot replace the root with a Case
assert_eq!(
sib_mut.replace_op(root, case_nodetype.clone()),
Err(HugrError::InvalidTag {
required: OpTag::Dfg,
actual: OpTag::Case
})
);

let nested_sib_mut = SiblingMut::<DataflowParentID>::try_new(&mut sib_mut, root);
assert!(nested_sib_mut.is_err());
}
}

0 comments on commit 23754fb

Please sign in to comment.