diff --git a/quantinuum-hugr/src/extension/infer.rs b/quantinuum-hugr/src/extension/infer.rs index 941ebb010..64fca0265 100644 --- a/quantinuum-hugr/src/extension/infer.rs +++ b/quantinuum-hugr/src/extension/infer.rs @@ -55,12 +55,6 @@ pub fn infer_extensions( #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] struct Meta(u32); -impl Meta { - pub fn new(m: u32) -> Self { - Meta(m) - } -} - #[derive(Clone, Debug, Eq, PartialEq, Hash)] /// Things we know about metavariables enum Constraint { @@ -190,7 +184,7 @@ struct UnificationContext { impl UnificationContext { /// Create a new unification context, and populate it with constraints from /// traversing the hugr which is passed in. - pub fn new(hugr: &impl HugrView) -> Self { + fn new(hugr: &impl HugrView) -> Self { let mut ctx = Self { constraints: HashMap::new(), extensions: HashMap::new(), @@ -206,7 +200,7 @@ impl UnificationContext { /// Create a fresh metavariable, and increment `fresh_name` for next time fn fresh_meta(&mut self) -> Meta { - let fresh = Meta::new(self.fresh_name); + let fresh = Meta(self.fresh_name); self.fresh_name += 1; self.constraints.insert(fresh, HashSet::new()); fresh @@ -544,7 +538,7 @@ impl UnificationContext { /// available. When there are variables, we should leave the graph as it is, /// but make sure that no matter what they're instantiated to, the graph /// still makes sense (should pass the extension validation check) - pub fn results(&self) -> Result { + fn results(&self) -> Result { // Check that all of the metavariables associated with nodes of the // graph are solved let depended_upon = { @@ -612,7 +606,7 @@ impl UnificationContext { /// where it was possible to infer them. If it wasn't possible to infer a /// *concrete* `ExtensionSet`, e.g. if the ExtensionSet relies on an open /// variable in the toplevel graph, don't include that location in the map - pub fn main_loop(&mut self) -> Result { + fn main_loop(&mut self) -> Result { let mut remaining = HashSet::::from_iter(self.constraints.keys().cloned()); // Keep going as long as we're making progress (= merging and solving nodes) @@ -674,7 +668,7 @@ impl UnificationContext { /// 2 = 1 + x, ... /// then 1 and 2 both definitely contain X, even if we don't know what else. /// So instead of instantiating to the empty set, we'll instantiate to `{X}` - pub fn instantiate_variables(&mut self) { + fn instantiate_variables(&mut self) { // A directed graph to keep track of `Plus` constraint relationships let mut relations = GraphContainer::::new(); let mut solutions: HashMap = HashMap::new(); diff --git a/quantinuum-hugr/src/hugr/views.rs b/quantinuum-hugr/src/hugr/views.rs index 0a0cf7d1b..649ae522e 100644 --- a/quantinuum-hugr/src/hugr/views.rs +++ b/quantinuum-hugr/src/hugr/views.rs @@ -28,8 +28,8 @@ use super::{Hugr, HugrError, NodeMetadata, NodeMetadataMap, NodeType, DEFAULT_NO use crate::ops::handle::NodeHandle; use crate::ops::{OpParent, OpTag, OpTrait, OpType}; -use crate::types::Type; use crate::types::{EdgeKind, FunctionType}; +use crate::types::{PolyFuncType, Type}; use crate::{Direction, IncomingPort, Node, OutgoingPort, Port}; use itertools::Either; @@ -327,11 +327,37 @@ pub trait HugrView: sealed::HugrInternals { } } - /// For HUGRs with a [`DataflowParent`][crate::ops::DataflowParent] root operation, report the - /// signature of the inner dataflow sibling graph. Otherwise return None. - fn get_function_type(&self) -> Option { - let op = self.get_nodetype(self.root()); - op.op.inner_function_type() + /// Returns the function type defined by this dataflow HUGR. + /// + /// If the root of the Hugr is a + /// [`DataflowParent`][crate::ops::DataflowParent] operation, report the + /// signature corresponding to the input and output node of its sibling + /// graph. Otherwise, returns `None`. + /// + /// In contrast to [`get_function_type`][HugrView::get_function_type], this + /// method always return a concrete [`FunctionType`]. + fn get_df_function_type(&self) -> Option { + let op = self.get_optype(self.root()); + op.inner_function_type() + } + + /// Returns the function type defined by this HUGR. + /// + /// For HUGRs with a [`DataflowParent`][crate::ops::DataflowParent] root + /// operation, report the signature of the inner dataflow sibling graph. + /// + /// For HUGRS with a [`FuncDecl`][crate::ops::FuncDecl] or + /// [`FuncDefn`][crate::ops::FuncDefn] root operation, report the signature + /// of the function. + /// + /// Otherwise, returns `None`. + fn get_function_type(&self) -> Option { + let op = self.get_optype(self.root()); + match op { + OpType::FuncDecl(decl) => Some(decl.signature.clone()), + OpType::FuncDefn(defn) => Some(defn.signature.clone()), + _ => op.inner_function_type().map(PolyFuncType::from), + } } /// Return a wrapper over the view that can be used in petgraph algorithms. diff --git a/quantinuum-hugr/src/hugr/views/descendants.rs b/quantinuum-hugr/src/hugr/views/descendants.rs index 3a60f4755..453503509 100644 --- a/quantinuum-hugr/src/hugr/views/descendants.rs +++ b/quantinuum-hugr/src/hugr/views/descendants.rs @@ -261,12 +261,12 @@ pub(super) mod test { assert_eq!( region.get_function_type(), - Some(FunctionType::new_endo(type_row![NAT, QB])) + Some(FunctionType::new_endo(type_row![NAT, QB]).into()) ); let inner_region: DescendantsGraph = DescendantsGraph::try_new(&hugr, inner)?; assert_eq!( inner_region.get_function_type(), - Some(FunctionType::new(type_row![NAT], type_row![NAT])) + Some(FunctionType::new(type_row![NAT], type_row![NAT]).into()) ); Ok(()) diff --git a/quantinuum-hugr/src/hugr/views/sibling.rs b/quantinuum-hugr/src/hugr/views/sibling.rs index e07897ac1..7d69cc4b0 100644 --- a/quantinuum-hugr/src/hugr/views/sibling.rs +++ b/quantinuum-hugr/src/hugr/views/sibling.rs @@ -439,7 +439,7 @@ mod test { fn flat_mut(mut simple_dfg_hugr: Hugr) { simple_dfg_hugr.update_validate(&PRELUDE_REGISTRY).unwrap(); let root = simple_dfg_hugr.root(); - let signature = simple_dfg_hugr.get_function_type().unwrap(); + let signature = simple_dfg_hugr.get_df_function_type().unwrap().clone(); let sib_mut = SiblingMut::::try_new(&mut simple_dfg_hugr, root); assert_eq!( diff --git a/quantinuum-hugr/src/ops/constant.rs b/quantinuum-hugr/src/ops/constant.rs index b4e3d95c0..de498d889 100644 --- a/quantinuum-hugr/src/ops/constant.rs +++ b/quantinuum-hugr/src/ops/constant.rs @@ -2,10 +2,10 @@ mod custom; -use super::{OpName, OpParent, OpTrait, StaticTag}; +use super::{OpName, OpTrait, StaticTag}; use super::{OpTag, OpType}; use crate::extension::ExtensionSet; -use crate::types::{CustomType, EdgeKind, PolyFuncType, SumType, SumTypeError, Type}; +use crate::types::{CustomType, EdgeKind, SumType, SumTypeError, Type}; use crate::{Hugr, HugrView}; use itertools::Itertools; @@ -118,7 +118,7 @@ impl Const { Self::Tuple { vs } => Type::new_tuple(vs.iter().map(Self::const_type).collect_vec()), Self::Sum { sum_type, .. } => sum_type.clone().into(), Self::Function { hugr } => { - let func_type = get_const_function_type(hugr).unwrap_or_else(|| { + let func_type = hugr.get_function_type().unwrap_or_else(|| { panic!( "{}", ConstTypeError::FunctionTypeMissing { @@ -161,7 +161,7 @@ impl Const { /// Returns an error if the Hugr root node does not define a function. pub fn function(hugr: impl Into) -> Result { let hugr = hugr.into(); - if get_const_function_type(&hugr).is_none() { + if hugr.get_function_type().is_none() { Err(ConstTypeError::FunctionTypeMissing { hugr_root_type: hugr.get_optype(hugr.root()).clone(), })?; @@ -228,7 +228,7 @@ impl OpName for Const { match self { Self::Extension { e } => format!("const:custom:{}", e.0.name()), Self::Function { hugr: h } => { - let Some(t) = get_const_function_type(h) else { + let Some(t) = h.get_function_type() else { panic!("HUGR root node isn't a valid function parent."); }; format!("const:function:[{}]", t) @@ -272,27 +272,6 @@ impl OpTrait for Const { } } -/// Returns the function type defined by the HUGR. In contrast to -/// [`Hugr::get_function_type`], this function also returns function types for -/// `FuncDecl` and `FuncDefn` operations. -/// -/// For HUGRs with a [`DataflowParent`][crate::ops::DataflowParent] root -/// operation, report the signature of the inner dataflow sibling graph. -/// -/// For HUGRS with a [`FuncDecl`][crate::ops::FuncDecl] or -/// [`FuncDefn`][crate::ops::FuncDefn] root operation, report the signature of -/// the function. -/// -/// Otherwise, returns `None`. -fn get_const_function_type(hugr: &impl HugrView) -> Option { - let op = hugr.get_optype(hugr.root()); - match op { - OpType::FuncDecl(decl) => Some(decl.signature.clone()), - OpType::FuncDefn(defn) => Some(defn.signature.clone()), - _ => op.inner_function_type().map(PolyFuncType::from), - } -} - // [KnownTypeConst] is guaranteed to be the right type, so can be constructed // without initial type check. impl From for Const