From 7b242ac8391fa3b3d73329b647ebd608cbfe44ee Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Jan 2024 14:56:48 +0000 Subject: [PATCH 01/57] Refactor: break out fn valid_row for validating a TypeRow --- src/types.rs | 14 +++++++++++--- src/types/signature.rs | 8 +++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/types.rs b/src/types.rs index ff8164221..074a61fec 100644 --- a/src/types.rs +++ b/src/types.rs @@ -305,9 +305,9 @@ impl Type { // There is no need to check the components against the bound, // that is guaranteed by construction (even for deserialization) match &self.0 { - TypeEnum::Tuple(row) | TypeEnum::Sum(SumType::General { row }) => row - .iter() - .try_for_each(|t| t.validate(extension_registry, var_decls)), + TypeEnum::Tuple(row) | TypeEnum::Sum(SumType::General { row }) => { + valid_row(row, extension_registry, var_decls) + } TypeEnum::Sum(SumType::Unit { .. }) => Ok(()), // No leaves there TypeEnum::Alias(_) => Ok(()), TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), @@ -347,6 +347,14 @@ pub(crate) trait Substitution { fn extension_registry(&self) -> &ExtensionRegistry; } +fn valid_row( + row: &TypeRow, + exts: &ExtensionRegistry, + var_decls: &[TypeParam], +) -> Result<(), SignatureError> { + row.iter().try_for_each(|t| t.validate(exts, var_decls)) +} + fn subst_row(row: &TypeRow, tr: &impl Substitution) -> TypeRow { let res = row .iter() diff --git a/src/types/signature.rs b/src/types/signature.rs index ebcd44a7c..4fba72116 100644 --- a/src/types/signature.rs +++ b/src/types/signature.rs @@ -5,7 +5,7 @@ use itertools::Either; use std::fmt::{self, Display, Write}; use super::type_param::TypeParam; -use super::{subst_row, Substitution, Type, TypeRow}; +use super::{subst_row, valid_row, Substitution, Type, TypeRow}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::{Direction, IncomingPort, OutgoingPort, Port}; @@ -34,10 +34,8 @@ impl FunctionType { extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - self.input - .iter() - .chain(self.output.iter()) - .try_for_each(|t| t.validate(extension_registry, var_decls))?; + valid_row(&self.input, extension_registry, var_decls)?; + valid_row(&self.output, extension_registry, var_decls)?; self.extension_reqs.validate(var_decls) } From ba050108bc349fee47033c0b1f3e6dcfa9ec15dc Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Jan 2024 15:39:39 +0000 Subject: [PATCH 02/57] Type::{validate,substitute}_in_row, {Substitution,SubstValues}::apply_typevar_in_row --- src/types.rs | 36 ++++++++++++++++++++++++++++++++++-- src/types/poly_func.rs | 23 ++++++++++++++++++++++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/types.rs b/src/types.rs index 074a61fec..80ff16b81 100644 --- a/src/types.rs +++ b/src/types.rs @@ -316,6 +316,23 @@ impl Type { } } + fn validate_in_row( + &self, + extension_registry: &ExtensionRegistry, + var_decls: &[TypeParam], + ) -> Result<(), SignatureError> { + if let TypeEnum::Variable(idx, bound) = &self.0 { + // Allow also the Variable to be a *list* of types of the specified bound + let list_bound = TypeParam::List { + param: Box::new((*bound).into()), + }; + if check_typevar_decl(var_decls, *idx, &list_bound).is_ok() { + return Ok(()); + }; + } + self.validate(extension_registry, var_decls) + } + pub(crate) fn substitute(&self, t: &impl Substitution) -> Self { match &self.0 { TypeEnum::Alias(_) | TypeEnum::Sum(SumType::Unit { .. }) => self.clone(), @@ -326,6 +343,13 @@ impl Type { TypeEnum::Sum(SumType::General { row }) => Type::new_sum(subst_row(row, t)), } } + + fn substitute_in_row(&self, t: &impl Substitution) -> Vec { + match &self.0 { + TypeEnum::Variable(idx, bound) => t.apply_typevar_in_row(*idx, *bound), + _ => vec![self.substitute(t)], + } + } } /// A function that replaces type variables with values. @@ -344,6 +368,13 @@ pub(crate) trait Substitution { /// Apply to a variable whose kind is any given [TypeParam] fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg; + fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { + let TypeArg::Type { ty } = self.apply_var(idx, &TypeParam::Type { b: bound }) else { + panic!("Applying to type did not produce type") + }; + vec![ty] + } + fn extension_registry(&self) -> &ExtensionRegistry; } @@ -352,13 +383,14 @@ fn valid_row( exts: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - row.iter().try_for_each(|t| t.validate(exts, var_decls)) + row.iter() + .try_for_each(|t| t.validate_in_row(exts, var_decls)) } fn subst_row(row: &TypeRow, tr: &impl Substitution) -> TypeRow { let res = row .iter() - .map(|ty| ty.substitute(tr)) + .flat_map(|ty| ty.substitute_in_row(tr)) .collect::>() .into(); res diff --git a/src/types/poly_func.rs b/src/types/poly_func.rs index 98d2ac1ed..67fb68c53 100644 --- a/src/types/poly_func.rs +++ b/src/types/poly_func.rs @@ -7,7 +7,7 @@ use crate::{ use itertools::Itertools; use super::type_param::{check_type_args, TypeArg, TypeParam}; -use super::{FunctionType, Substitution}; +use super::{FunctionType, Substitution, Type, TypeBound}; /// A polymorphic function type, e.g. of a [Graph], or perhaps an [OpDef]. /// (Nodes/operations in the Hugr are not polymorphic.) @@ -160,6 +160,27 @@ impl<'a> Substitution for SubstValues<'a> { arg.clone() } + fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { + let arg = self + .0 + .get(idx) + .expect("Undeclared type variable - call validate() ?"); + match arg { + TypeArg::Sequence { elems } => elems + .iter() + .map(|ta| match ta { + TypeArg::Type { ty } => ty.clone(), + _ => panic!("Not a list of types - did validate() ?"), + }) + .collect(), + TypeArg::Type { ty } => { + debug_assert_eq!(check_type_arg(arg, &TypeParam::Type { b: bound }), Ok(())); + vec![ty.clone()] + } + _ => panic!("Not a type or list of types - did validate() ?"), + } + } + fn extension_registry(&self) -> &ExtensionRegistry { self.1 } From 59c585439f42544d8346ba7b2e3846f7461c0a5c Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 14:16:50 +0000 Subject: [PATCH 03/57] [test] types.rs::construct - also validate --- src/types.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 80ff16b81..aa09c10c0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -439,10 +439,16 @@ pub(crate) mod test { pub(crate) use poly_func::test::nested_func; use super::*; + use crate::extension::PRELUDE; + use crate::{const_extension_ids, Extension}; use crate::{extension::prelude::USIZE_T, ops::AliasDecl}; use crate::types::TypeBound; + const_extension_ids! { + const MY_EXT: ExtensionId = "my_extension"; + } + #[test] fn construct() { let t: Type = Type::new_tuple(vec![ @@ -451,7 +457,7 @@ pub(crate) mod test { Type::new_extension(CustomType::new( "my_custom", [], - "my_extension".try_into().unwrap(), + MY_EXT, TypeBound::Copyable, )), Type::new_alias(AliasDecl::new("my_alias", TypeBound::Eq)), @@ -461,6 +467,17 @@ pub(crate) mod test { "Tuple([usize([]), Function(forall . [[]][]), my_custom([]), Alias(my_alias)])" .to_string() ); + + let mut ext = Extension::new(MY_EXT); + ext.add_type( + "my_custom".into(), + vec![], + "".into(), + TypeBound::Copyable.into(), + ) + .unwrap(); + let reg = ExtensionRegistry::try_new([PRELUDE.to_owned(), ext]).unwrap(); + t.validate(®, &[]).unwrap() } #[test] From 72b4fb2483453453debf79888a6ec501cae4bc24 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 15:01:54 +0000 Subject: [PATCH 04/57] [tests] poly_func.rs: test row variables --- src/types.rs | 2 +- src/types/poly_func.rs | 89 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/types.rs b/src/types.rs index aa09c10c0..384a6a28e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -268,7 +268,7 @@ impl Type { /// New use (occurrence) of the type variable with specified DeBruijn index. /// For use in type schemes only: `bound` must match that with which the /// variable was declared (i.e. as a [TypeParam::Type]`(bound)`). - pub fn new_var_use(idx: usize, bound: TypeBound) -> Self { + pub const fn new_var_use(idx: usize, bound: TypeBound) -> Self { Self(TypeEnum::Variable(idx, bound), bound) } diff --git a/src/types/poly_func.rs b/src/types/poly_func.rs index 67fb68c53..79be32b28 100644 --- a/src/types/poly_func.rs +++ b/src/types/poly_func.rs @@ -242,7 +242,7 @@ pub(crate) mod test { use lazy_static::lazy_static; use smol_str::SmolStr; - use crate::extension::prelude::{array_type, PRELUDE_ID, USIZE_CUSTOM_T, USIZE_T}; + use crate::extension::prelude::{array_type, BOOL_T, PRELUDE_ID, USIZE_CUSTOM_T, USIZE_T}; use crate::extension::{ ExtensionId, ExtensionRegistry, SignatureError, TypeDefBound, PRELUDE, PRELUDE_REGISTRY, }; @@ -639,4 +639,91 @@ pub(crate) mod test { ) ) } + + #[test] + fn row_variables() { + const TP: TypeParam = TypeParam::Type { b: TypeBound::Any }; + // Mismatched TypeBound (Copyable vs Any) + PolyFuncType::new_validated( + [TypeParam::List { + param: Box::new(TypeParam::Type { + b: TypeBound::Copyable, + }), + }], + FunctionType::new( + vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], + vec![Type::new_sum(vec![Type::new_var_use(0, TypeBound::Any)])], + ), + &PRELUDE_REGISTRY, + ) + .unwrap_err(); + + let pf = PolyFuncType::new_validated( + [TypeParam::List { + param: Box::new(TP), + }], + FunctionType::new( + vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], + vec![Type::new_sum(vec![Type::new_var_use(0, TypeBound::Any)])], + ), + &PRELUDE_REGISTRY, + ) + .unwrap(); + + fn seq2() -> Vec { + vec![USIZE_T.into(), BOOL_T.into()] + } + pf.instantiate(&[TypeArg::Type { ty: USIZE_T }], &PRELUDE_REGISTRY) + .unwrap_err(); + pf.instantiate( + &[TypeArg::Sequence { + elems: vec![USIZE_T.into(), TypeArg::Sequence { elems: seq2() }], + }], + &PRELUDE_REGISTRY, + ) + .unwrap_err(); + + let t2 = pf + .instantiate(&[TypeArg::Sequence { elems: seq2() }], &PRELUDE_REGISTRY) + .unwrap(); + assert_eq!( + t2, + FunctionType::new( + vec![USIZE_T, USIZE_T, BOOL_T], + vec![Type::new_sum(vec![USIZE_T, BOOL_T])] + ) + ); + } + + #[test] + fn row_variables_inner() { + let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_var_use( + 0, + TypeBound::Copyable, + )])); + let pf = PolyFuncType::new_validated( + [TypeParam::List { + param: Box::new(TypeParam::Type { + b: TypeBound::Copyable, + }), + }], + FunctionType::new(vec![USIZE_T, inner_fty.clone()], vec![inner_fty]), + &PRELUDE_REGISTRY, + ) + .unwrap(); + + let inner3 = Type::new_function(FunctionType::new_endo(vec![USIZE_T, BOOL_T, USIZE_T])); + let t3 = pf + .instantiate( + &[TypeArg::Sequence { + elems: vec![USIZE_T.into(), BOOL_T.into(), USIZE_T.into()], + }], + &PRELUDE_REGISTRY, + ) + .unwrap(); + assert_eq!( + t3, + FunctionType::new(vec![USIZE_T, inner3.clone()], vec![inner3]) + ); + } } From 2cf1e7f0bd71f9cff8a79e4fd1dbb9b7f147b30b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 15:14:33 +0000 Subject: [PATCH 05/57] [test] validate Hugr passing around Function of unknown arity --- src/hugr/validate/test.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/hugr/validate/test.rs b/src/hugr/validate/test.rs index d974339e7..510acb658 100644 --- a/src/hugr/validate/test.rs +++ b/src/hugr/validate/test.rs @@ -559,6 +559,26 @@ fn no_polymorphic_consts() -> Result<(), Box> { Ok(()) } +#[test] +fn inner_row_variables() -> Result<(), Box> { + let tv = Type::new_var_use(0, TypeBound::Any); + let inner_ft = Type::new_function(FunctionType::new_endo(vec![tv])); + let mut fb = FunctionBuilder::new( + "id", + PolyFuncType::new( + [TypeParam::List { + param: Box::new(TypeParam::Type { b: TypeBound::Any }), + }], + FunctionType::new_endo(vec![inner_ft.clone()]), + ), + )?; + // All the wires here are carrying higher-order Function values + // (the Functions themselves have variable arity, but that's fine as we are not calling them) + let id = fb.add_dataflow_op(LeafOp::Noop { ty: inner_ft }, fb.input_wires())?; + fb.finish_hugr_with_outputs(id.outputs(), &EMPTY_REG)?; + Ok(()) +} + #[cfg(feature = "extension_inference")] mod extension_tests { use super::*; From 8899806e4493843427c176a59675ffe806f11509 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 15:22:07 +0000 Subject: [PATCH 06/57] [tests]Validation prevents row variables being used in node signatures --- src/hugr/validate/test.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/hugr/validate/test.rs b/src/hugr/validate/test.rs index 510acb658..ecd69bcdb 100644 --- a/src/hugr/validate/test.rs +++ b/src/hugr/validate/test.rs @@ -4,6 +4,7 @@ use super::*; use crate::builder::test::closed_dfg_root_hugr; use crate::builder::{ BuildError, Container, Dataflow, DataflowHugr, DataflowSubContainer, FunctionBuilder, + HugrBuilder, }; use crate::extension::prelude::{BOOL_T, PRELUDE, USIZE_T}; use crate::extension::{ @@ -579,6 +580,33 @@ fn inner_row_variables() -> Result<(), Box> { Ok(()) } +#[test] +fn no_outer_row_variables() -> Result<(), Box> { + let tv = Type::new_var_use(0, TypeBound::Any); + let fb = FunctionBuilder::new( + "impossible_id_of_unknown_arity", + PolyFuncType::new( + [TypeParam::List { + param: Box::new(TypeParam::Type { b: TypeBound::Any }), + }], + FunctionType::new_endo(vec![tv]), + ), + )?; + // Input and Output nodes have a Port whose type is List(Type(Any)) + // - so this is illegal because the wire between them is not a type: + let err = fb + .clone() + .finish_hugr_with_outputs(fb.input_wires(), &EMPTY_REG) + .unwrap_err(); + assert_matches!( + err, + BuildError::InvalidHUGR(ValidationError::SignatureError { .. }) + ); + // Also try leaving no inputs/outputs - so this should be illegal because the ports are unconnected + fb.finish_hugr(&EMPTY_REG).unwrap_err(); + Ok(()) +} + #[cfg(feature = "extension_inference")] mod extension_tests { use super::*; From e1f182502f6cec77f07a9bf62b6e5431538800b2 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 16:33:50 +0000 Subject: [PATCH 07/57] Simplify default apply_typevar_in_row --- src/types.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/types.rs b/src/types.rs index 384a6a28e..3d3d4d3f3 100644 --- a/src/types.rs +++ b/src/types.rs @@ -369,10 +369,7 @@ pub(crate) trait Substitution { fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg; fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { - let TypeArg::Type { ty } = self.apply_var(idx, &TypeParam::Type { b: bound }) else { - panic!("Applying to type did not produce type") - }; - vec![ty] + vec![self.apply_typevar(idx, bound)] } fn extension_registry(&self) -> &ExtensionRegistry; From 1074093d8274c7c709203ba151f0ad196443ecfe Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Fri, 12 Jan 2024 16:49:31 +0000 Subject: [PATCH 08/57] Separate TypeEnum::RowVariable --- src/extension.rs | 3 +++ src/hugr/validate/test.rs | 4 ++-- src/types.rs | 39 +++++++++++++++++++++++++++------------ src/types/poly_func.rs | 10 +++++----- src/types/serialize.rs | 3 +++ 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/extension.rs b/src/extension.rs index f87925755..5f98d07b8 100644 --- a/src/extension.rs +++ b/src/extension.rs @@ -123,6 +123,9 @@ pub enum SignatureError { /// A type variable that was used has not been declared #[error("Type variable {idx} was not declared ({num_decls} in scope)")] FreeTypeVar { idx: usize, num_decls: usize }, + /// A row variable was found outside of a row + #[error("Row variable {idx} was found outside of a type row")] + RowTypeVarOutsideRow { idx: usize }, /// The type stored in a [LeafOp::TypeApply] is not what we compute from the /// [ExtensionRegistry]. /// diff --git a/src/hugr/validate/test.rs b/src/hugr/validate/test.rs index ecd69bcdb..98ec7db49 100644 --- a/src/hugr/validate/test.rs +++ b/src/hugr/validate/test.rs @@ -562,7 +562,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { #[test] fn inner_row_variables() -> Result<(), Box> { - let tv = Type::new_var_use(0, TypeBound::Any); + let tv = Type::new_row_var(0, TypeBound::Any); let inner_ft = Type::new_function(FunctionType::new_endo(vec![tv])); let mut fb = FunctionBuilder::new( "id", @@ -582,7 +582,7 @@ fn inner_row_variables() -> Result<(), Box> { #[test] fn no_outer_row_variables() -> Result<(), Box> { - let tv = Type::new_var_use(0, TypeBound::Any); + let tv = Type::new_row_var(0, TypeBound::Any); let fb = FunctionBuilder::new( "impossible_id_of_unknown_arity", PolyFuncType::new( diff --git a/src/types.rs b/src/types.rs index 3d3d4d3f3..6a59afb47 100644 --- a/src/types.rs +++ b/src/types.rs @@ -153,10 +153,14 @@ pub enum TypeEnum { #[allow(missing_docs)] #[display(fmt = "Function({})", "_0")] Function(Box), - // DeBruijn index, and cache of TypeBound (checked in validation) + /// DeBruijn index, and cache of TypeBound of [TypeParam::Type] (checked in validation) #[allow(missing_docs)] #[display(fmt = "Variable({})", _0)] Variable(usize, TypeBound), + /// DeBruijn index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type] + /// of this bound (checked in validation) + #[display(fmt = "RowVar({})", _0)] + RowVariable(usize, TypeBound), #[allow(missing_docs)] #[display(fmt = "Tuple({})", "_0")] Tuple(TypeRow), @@ -171,7 +175,7 @@ impl TypeEnum { TypeEnum::Extension(c) => c.bound(), TypeEnum::Alias(a) => a.bound, TypeEnum::Function(_) => TypeBound::Copyable, - TypeEnum::Variable(_, b) => *b, + TypeEnum::Variable(_, b) | TypeEnum::RowVariable(_, b) => *b, TypeEnum::Sum(SumType::Unit { size: _ }) => TypeBound::Eq, TypeEnum::Sum(SumType::General { row }) => { least_upper_bound(row.iter().map(Type::least_upper_bound)) @@ -272,6 +276,13 @@ impl Type { Self(TypeEnum::Variable(idx, bound), bound) } + /// New use (occurrence) of the row variable with specified DeBruijn index. + /// For use in type schemes only: `bound` must match that with which the + /// variable was declared (i.e. as a [TypeParam::List]`(`[TypeParam::Type]`(bound))`). + pub const fn new_row_var(idx: usize, bound: TypeBound) -> Self { + Self(TypeEnum::RowVariable(idx, bound), bound) + } + /// Report the least upper TypeBound, if there is one. #[inline(always)] pub const fn least_upper_bound(&self) -> TypeBound { @@ -313,6 +324,9 @@ impl Type { TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), TypeEnum::Function(ft) => ft.validate(extension_registry, var_decls), TypeEnum::Variable(idx, bound) => check_typevar_decl(var_decls, *idx, &(*bound).into()), + TypeEnum::RowVariable(idx, _) => { + Err(SignatureError::RowTypeVarOutsideRow { idx: *idx }) + } } } @@ -321,22 +335,23 @@ impl Type { extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - if let TypeEnum::Variable(idx, bound) = &self.0 { - // Allow also the Variable to be a *list* of types of the specified bound - let list_bound = TypeParam::List { - param: Box::new((*bound).into()), - }; - if check_typevar_decl(var_decls, *idx, &list_bound).is_ok() { - return Ok(()); + if let TypeEnum::RowVariable(idx, bound) = self.0 { + let t = TypeParam::List { + param: Box::new(bound.into()), }; + check_typevar_decl(var_decls, idx, &t) + } else { + self.validate(extension_registry, var_decls) } - self.validate(extension_registry, var_decls) } pub(crate) fn substitute(&self, t: &impl Substitution) -> Self { match &self.0 { TypeEnum::Alias(_) | TypeEnum::Sum(SumType::Unit { .. }) => self.clone(), TypeEnum::Variable(idx, bound) => t.apply_typevar(*idx, *bound), + TypeEnum::RowVariable(_, _) => { + panic!("Row Variable found outside of row - should have been detected in validate") + } TypeEnum::Extension(cty) => Type::new_extension(cty.substitute(t)), TypeEnum::Function(bf) => Type::new_function(bf.substitute(t)), TypeEnum::Tuple(elems) => Type::new_tuple(subst_row(elems, t)), @@ -346,7 +361,7 @@ impl Type { fn substitute_in_row(&self, t: &impl Substitution) -> Vec { match &self.0 { - TypeEnum::Variable(idx, bound) => t.apply_typevar_in_row(*idx, *bound), + TypeEnum::RowVariable(idx, bound) => t.apply_rowvar(*idx, *bound), _ => vec![self.substitute(t)], } } @@ -368,7 +383,7 @@ pub(crate) trait Substitution { /// Apply to a variable whose kind is any given [TypeParam] fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg; - fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { + fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { vec![self.apply_typevar(idx, bound)] } diff --git a/src/types/poly_func.rs b/src/types/poly_func.rs index 79be32b28..6026f783d 100644 --- a/src/types/poly_func.rs +++ b/src/types/poly_func.rs @@ -160,7 +160,7 @@ impl<'a> Substitution for SubstValues<'a> { arg.clone() } - fn apply_typevar_in_row(&self, idx: usize, bound: TypeBound) -> Vec { + fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { let arg = self .0 .get(idx) @@ -652,7 +652,7 @@ pub(crate) mod test { }], FunctionType::new( vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], - vec![Type::new_sum(vec![Type::new_var_use(0, TypeBound::Any)])], + vec![Type::new_sum(vec![Type::new_row_var(0, TypeBound::Any)])], ), &PRELUDE_REGISTRY, ) @@ -663,8 +663,8 @@ pub(crate) mod test { param: Box::new(TP), }], FunctionType::new( - vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], - vec![Type::new_sum(vec![Type::new_var_use(0, TypeBound::Any)])], + vec![USIZE_T, Type::new_row_var(0, TypeBound::Any)], + vec![Type::new_sum(vec![Type::new_row_var(0, TypeBound::Any)])], ), &PRELUDE_REGISTRY, ) @@ -697,7 +697,7 @@ pub(crate) mod test { #[test] fn row_variables_inner() { - let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_var_use( + let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_row_var( 0, TypeBound::Copyable, )])); diff --git a/src/types/serialize.rs b/src/types/serialize.rs index ad10c3ff5..1aac86e5f 100644 --- a/src/types/serialize.rs +++ b/src/types/serialize.rs @@ -17,6 +17,7 @@ pub(super) enum SerSimpleType { Opaque(CustomType), Alias(AliasDecl), V { i: usize, b: TypeBound }, + R { i: usize, b: TypeBound }, } impl From for SerSimpleType { @@ -34,6 +35,7 @@ impl From for SerSimpleType { TypeEnum::Alias(a) => SerSimpleType::Alias(a), TypeEnum::Function(sig) => SerSimpleType::G(sig), TypeEnum::Variable(i, b) => SerSimpleType::V { i, b }, + TypeEnum::RowVariable(i, b) => SerSimpleType::R { i, b }, TypeEnum::Sum(sum) => SerSimpleType::Sum(sum), TypeEnum::Tuple(inner) => SerSimpleType::Tuple { inner }, } @@ -54,6 +56,7 @@ impl From for Type { SerSimpleType::Opaque(custom) => Type::new_extension(custom), SerSimpleType::Alias(a) => Type::new_alias(a), SerSimpleType::V { i, b } => Type::new_var_use(i, b), + SerSimpleType::R { i, b } => Type::new_row_var(i, b), } } } From 6c9685b4b887146c6310fbb8f2adbb437dbdf13b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Thu, 25 Jan 2024 16:33:58 +0000 Subject: [PATCH 09/57] WIP TypeRowV contains enum RowVarOrType --- src/types.rs | 86 +++++++++++++++--------------------------- src/types/serialize.rs | 1 - src/types/signature.rs | 7 ++-- src/types/type_row.rs | 80 ++++++++++++++++++++++++++++----------- 4 files changed, 93 insertions(+), 81 deletions(-) diff --git a/src/types.rs b/src/types.rs index 6a59afb47..7a525c64f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -25,6 +25,7 @@ use crate::type_row; use std::fmt::Debug; use self::type_param::TypeParam; +use self::type_row::{RowVarOrType, TypeRowV}; /// The kinds of edges in a HUGR, excluding Hierarchy. #[derive(Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)] @@ -103,16 +104,16 @@ pub(crate) fn least_upper_bound(mut tags: impl Iterator) -> Ty pub enum SumType { #[allow(missing_docs)] #[display(fmt = "UnitSum({})", "size")] - Unit { size: u8 }, + Unit { size: u8 }, // TODO what about a type variable of BoundedUSize #[allow(missing_docs)] - General { row: TypeRow }, + General { row: TypeRowV }, } impl SumType { /// Initialize a new sum type. - pub fn new(types: impl Into) -> Self { - let row: TypeRow = types.into(); - + pub fn new(types: impl Into) -> Self { + let row = types.into(); + // ALAN need to TryInto to a TypeRow (-notV) here let len: usize = row.len(); if len <= (u8::MAX as usize) && row.iter().all(|t| *t == Type::UNIT) { Self::Unit { size: len as u8 } @@ -157,13 +158,9 @@ pub enum TypeEnum { #[allow(missing_docs)] #[display(fmt = "Variable({})", _0)] Variable(usize, TypeBound), - /// DeBruijn index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type] - /// of this bound (checked in validation) - #[display(fmt = "RowVar({})", _0)] - RowVariable(usize, TypeBound), #[allow(missing_docs)] #[display(fmt = "Tuple({})", "_0")] - Tuple(TypeRow), + Tuple(TypeRowV), #[allow(missing_docs)] #[display(fmt = "Sum({})", "_0")] Sum(SumType), @@ -175,12 +172,12 @@ impl TypeEnum { TypeEnum::Extension(c) => c.bound(), TypeEnum::Alias(a) => a.bound, TypeEnum::Function(_) => TypeBound::Copyable, - TypeEnum::Variable(_, b) | TypeEnum::RowVariable(_, b) => *b, + TypeEnum::Variable(_, b) => *b, TypeEnum::Sum(SumType::Unit { size: _ }) => TypeBound::Eq, TypeEnum::Sum(SumType::General { row }) => { - least_upper_bound(row.iter().map(Type::least_upper_bound)) + least_upper_bound(row.iter().map(RowVarOrType::least_upper_bound)) } - TypeEnum::Tuple(ts) => least_upper_bound(ts.iter().map(Type::least_upper_bound)), + TypeEnum::Tuple(ts) => least_upper_bound(ts.iter().map(RowVarOrType::least_upper_bound)), } } } @@ -227,13 +224,13 @@ impl Type { /// Initialize a new tuple type by providing the elements. #[inline(always)] - pub fn new_tuple(types: impl Into) -> Self { + pub fn new_tuple(types: impl Into) -> Self { Self::new(TypeEnum::Tuple(types.into())) } /// Initialize a new sum type by providing the possible variant types. #[inline(always)] - pub fn new_sum(types: impl Into) -> Self { + pub fn new_sum(types: impl Into) -> Self { Self::new(TypeEnum::Sum(SumType::new(types))) } @@ -276,13 +273,6 @@ impl Type { Self(TypeEnum::Variable(idx, bound), bound) } - /// New use (occurrence) of the row variable with specified DeBruijn index. - /// For use in type schemes only: `bound` must match that with which the - /// variable was declared (i.e. as a [TypeParam::List]`(`[TypeParam::Type]`(bound))`). - pub const fn new_row_var(idx: usize, bound: TypeBound) -> Self { - Self(TypeEnum::RowVariable(idx, bound), bound) - } - /// Report the least upper TypeBound, if there is one. #[inline(always)] pub const fn least_upper_bound(&self) -> TypeBound { @@ -324,24 +314,6 @@ impl Type { TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), TypeEnum::Function(ft) => ft.validate(extension_registry, var_decls), TypeEnum::Variable(idx, bound) => check_typevar_decl(var_decls, *idx, &(*bound).into()), - TypeEnum::RowVariable(idx, _) => { - Err(SignatureError::RowTypeVarOutsideRow { idx: *idx }) - } - } - } - - fn validate_in_row( - &self, - extension_registry: &ExtensionRegistry, - var_decls: &[TypeParam], - ) -> Result<(), SignatureError> { - if let TypeEnum::RowVariable(idx, bound) = self.0 { - let t = TypeParam::List { - param: Box::new(bound.into()), - }; - check_typevar_decl(var_decls, idx, &t) - } else { - self.validate(extension_registry, var_decls) } } @@ -349,22 +321,12 @@ impl Type { match &self.0 { TypeEnum::Alias(_) | TypeEnum::Sum(SumType::Unit { .. }) => self.clone(), TypeEnum::Variable(idx, bound) => t.apply_typevar(*idx, *bound), - TypeEnum::RowVariable(_, _) => { - panic!("Row Variable found outside of row - should have been detected in validate") - } TypeEnum::Extension(cty) => Type::new_extension(cty.substitute(t)), TypeEnum::Function(bf) => Type::new_function(bf.substitute(t)), TypeEnum::Tuple(elems) => Type::new_tuple(subst_row(elems, t)), TypeEnum::Sum(SumType::General { row }) => Type::new_sum(subst_row(row, t)), } } - - fn substitute_in_row(&self, t: &impl Substitution) -> Vec { - match &self.0 { - TypeEnum::RowVariable(idx, bound) => t.apply_rowvar(*idx, *bound), - _ => vec![self.substitute(t)], - } - } } /// A function that replaces type variables with values. @@ -383,26 +345,37 @@ pub(crate) trait Substitution { /// Apply to a variable whose kind is any given [TypeParam] fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg; - fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { - vec![self.apply_typevar(idx, bound)] + fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { + vec![RowVarOrType::T(self.apply_typevar(idx, bound))] } fn extension_registry(&self) -> &ExtensionRegistry; } fn valid_row( - row: &TypeRow, + row: &TypeRowV, exts: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { row.iter() - .try_for_each(|t| t.validate_in_row(exts, var_decls)) + .try_for_each(|t| match t { + RowVarOrType::T(t) => t.validate(exts, var_decls), + RowVarOrType::RV(idx, bound) => { + let t = TypeParam::List { + param: Box::new((*bound).into()), + }; + check_typevar_decl(var_decls, *idx, &t) + }, + }) } -fn subst_row(row: &TypeRow, tr: &impl Substitution) -> TypeRow { +fn subst_row(row: &TypeRowV, tr: &impl Substitution) -> TypeRowV { let res = row .iter() - .flat_map(|ty| ty.substitute_in_row(tr)) + .flat_map(|ty| match ty { + RowVarOrType::RV(idx, bound) => tr.apply_rowvar(*idx, *bound), + RowVarOrType::T(t) => vec![RowVarOrType::T(t.substitute(tr))], + }) .collect::>() .into(); res @@ -441,6 +414,7 @@ where { variant_rows .into_iter() + .map(Into::into) .map(Type::new_tuple) .collect_vec() .into() diff --git a/src/types/serialize.rs b/src/types/serialize.rs index 1aac86e5f..11d16794d 100644 --- a/src/types/serialize.rs +++ b/src/types/serialize.rs @@ -35,7 +35,6 @@ impl From for SerSimpleType { TypeEnum::Alias(a) => SerSimpleType::Alias(a), TypeEnum::Function(sig) => SerSimpleType::G(sig), TypeEnum::Variable(i, b) => SerSimpleType::V { i, b }, - TypeEnum::RowVariable(i, b) => SerSimpleType::R { i, b }, TypeEnum::Sum(sum) => SerSimpleType::Sum(sum), TypeEnum::Tuple(inner) => SerSimpleType::Tuple { inner }, } diff --git a/src/types/signature.rs b/src/types/signature.rs index 4fba72116..2c0e45640 100644 --- a/src/types/signature.rs +++ b/src/types/signature.rs @@ -5,6 +5,7 @@ use itertools::Either; use std::fmt::{self, Display, Write}; use super::type_param::TypeParam; +use super::type_row::TypeRowV; use super::{subst_row, valid_row, Substitution, Type, TypeRow}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; @@ -15,9 +16,9 @@ use crate::{Direction, IncomingPort, OutgoingPort, Port}; /// and also the target (value) of a call (static). pub struct FunctionType { /// Value inputs of the function. - pub input: TypeRow, + pub input: TypeRowV, /// Value outputs of the function. - pub output: TypeRow, + pub output: TypeRowV, /// The extension requirements which are added by the operation pub extension_reqs: ExtensionSet, } @@ -58,7 +59,7 @@ impl FunctionType { impl FunctionType { /// Create a new signature with specified inputs and outputs. - pub fn new(input: impl Into, output: impl Into) -> Self { + pub fn new(input: impl Into, output: impl Into) -> Self { Self { input: input.into(), output: output.into(), diff --git a/src/types/type_row.rs b/src/types/type_row.rs index 694b56921..c4bbb37cb 100644 --- a/src/types/type_row.rs +++ b/src/types/type_row.rs @@ -7,21 +7,44 @@ use std::{ ops::{Deref, DerefMut}, }; -use super::Type; +use super::{Type, TypeBound}; use crate::utils::display_list; use crate::PortIndex; use delegate::delegate; +#[derive(Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display)] +pub enum RowVarOrType { + #[display(fmt="{}", _0)] + T(Type), + /// DeBruijn index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type] + /// of this bound (checked in validation) + #[display(fmt = "RowVar({})", _0)] + RV(usize, TypeBound), +} + +impl RowVarOrType { + pub fn least_upper_bound(&self) -> TypeBound { + match self { + RowVarOrType::T(t) => t.least_upper_bound(), + RowVarOrType::RV(_, b) => *b, + } + } +} /// List of types, used for function signatures. #[derive(Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)] #[non_exhaustive] #[serde(transparent)] -pub struct TypeRow { +pub struct TypeRowBase + where T: 'static,//Clone + PartialEq + Eq + std::fmt::Debug + serde::Serialize + 'static, + [T]: ToOwned> { /// The datatypes in the row. - types: Cow<'static, [Type]>, + types: Cow<'static, [T]>, } -impl Display for TypeRow { +pub type TypeRow = TypeRowBase; +pub type TypeRowV = TypeRowBase; + +impl Display for TypeRowBase where [T]: ToOwned> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_char('[')?; display_list(self.types.as_ref(), f)?; @@ -29,7 +52,7 @@ impl Display for TypeRow { } } -impl TypeRow { +impl TypeRowBase where [T]: ToOwned> { /// Create a new empty row. pub const fn new() -> Self { Self { @@ -37,6 +60,29 @@ impl TypeRow { } } + delegate! { + to self.types { + /// Iterator over the types and row variables in the row. + pub fn iter(&self) -> impl Iterator; + + /// Mutable vector of the types and row variables in the row. + pub fn to_mut(&mut self) -> &mut Vec; + + /// Allow access (consumption) of the contained elements + pub fn into_owned(self) -> Vec; + } + } +} + +impl From for TypeRowV { + fn from(value: TypeRow) -> Self { + Self { + types: value.into_owned().into_iter().map(RowVarOrType::T).collect() + } + } +} + +impl TypeRow { #[inline(always)] /// Returns the port type given an offset. Returns `None` if the offset is out of bounds. pub fn get(&self, offset: impl PortIndex) -> Option<&Type> { @@ -51,33 +97,25 @@ impl TypeRow { delegate! { to self.types { - /// Iterator over the types in the row. - pub fn iter(&self) -> impl Iterator; - /// Returns the number of types in the row. pub fn len(&self) -> usize; - /// Mutable vector of the types in the row. - pub fn to_mut(&mut self) -> &mut Vec; - - /// Allow access (consumption) of the contained elements - pub fn into_owned(self) -> Vec; - /// Returns `true` if the row contains no types. - pub fn is_empty(&self) -> bool ; + pub fn is_empty(&self) -> bool ; } } } -impl Default for TypeRow { +impl Default for TypeRowBase where [T]: ToOwned> { fn default() -> Self { Self::new() } } -impl From for TypeRow +impl From for TypeRowBase where - F: Into>, + F: Into>, + [T]: ToOwned> { fn from(types: F) -> Self { Self { @@ -86,15 +124,15 @@ where } } -impl Deref for TypeRow { - type Target = [Type]; +impl Deref for TypeRowBase where [T]: ToOwned> { + type Target = [T]; fn deref(&self) -> &Self::Target { &self.types } } -impl DerefMut for TypeRow { +impl DerefMut for TypeRowBase where [T]: ToOwned> { fn deref_mut(&mut self) -> &mut Self::Target { self.types.to_mut() } From bb874893eec3f1b751fd9d0f53106ee38629cdaa Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 16:58:29 +0000 Subject: [PATCH 10/57] Add a test of a Call to a polymorphic function...failing validation! --- quantinuum-hugr/src/hugr/validate/test.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/quantinuum-hugr/src/hugr/validate/test.rs b/quantinuum-hugr/src/hugr/validate/test.rs index 3bf93758c..6ecf00699 100644 --- a/quantinuum-hugr/src/hugr/validate/test.rs +++ b/quantinuum-hugr/src/hugr/validate/test.rs @@ -4,6 +4,7 @@ use super::*; use crate::builder::test::closed_dfg_root_hugr; use crate::builder::{ BuildError, Container, Dataflow, DataflowHugr, DataflowSubContainer, FunctionBuilder, + HugrBuilder, ModuleBuilder, }; use crate::extension::prelude::{BOOL_T, PRELUDE, USIZE_T}; use crate::extension::{Extension, ExtensionId, TypeDefBound, EMPTY_REG, PRELUDE_REGISTRY}; @@ -540,6 +541,23 @@ fn no_polymorphic_consts() -> Result<(), Box> { Ok(()) } +#[test] +fn test_polymorphic_call() -> Result<(), Box> { + let mut m = ModuleBuilder::new(); + let id = m.declare( + "id", + PolyFuncType::new( + vec![TypeBound::Any.into()], + FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + ), + )?; + let mut f = m.define_function("main", FunctionType::new_endo(vec![USIZE_T]).into())?; + let c = f.call(&id, &[USIZE_T.into()], f.input_wires(), &PRELUDE_REGISTRY)?; + f.finish_with_outputs(c.outputs())?; + let _ = m.finish_prelude_hugr()?; + Ok(()) +} + #[cfg(feature = "extension_inference")] mod extension_tests { use super::*; From cb1d47d2a2029987a2a4433dc9c97b2a95106dcb Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 17:03:15 +0000 Subject: [PATCH 11/57] Fix: store functiontype + type_args in Call --- quantinuum-hugr/src/builder/build_traits.rs | 3 +- quantinuum-hugr/src/ops/dataflow.rs | 37 ++++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/quantinuum-hugr/src/builder/build_traits.rs b/quantinuum-hugr/src/builder/build_traits.rs index 277bcd0a6..7b510df68 100644 --- a/quantinuum-hugr/src/builder/build_traits.rs +++ b/quantinuum-hugr/src/builder/build_traits.rs @@ -576,8 +576,7 @@ pub trait Dataflow: Container { }) } }; - let signature = type_scheme.instantiate(type_args, exts)?; - let op: OpType = ops::Call { signature }.into(); + let op: OpType = ops::Call::try_new(type_scheme, type_args, exts)?.into(); let const_in_port = op.static_input_port().unwrap(); let op_id = self.add_dataflow_op(op, input_wires)?; let src_port = self.hugr_mut().num_outputs(function.node()) - 1; diff --git a/quantinuum-hugr/src/ops/dataflow.rs b/quantinuum-hugr/src/ops/dataflow.rs index 74ef64dde..3c0dfd47b 100644 --- a/quantinuum-hugr/src/ops/dataflow.rs +++ b/quantinuum-hugr/src/ops/dataflow.rs @@ -2,9 +2,9 @@ use super::{impl_op_name, OpTag, OpTrait}; -use crate::extension::ExtensionSet; +use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::ops::StaticTag; -use crate::types::{EdgeKind, FunctionType, Type, TypeRow}; +use crate::types::{EdgeKind, FunctionType, PolyFuncType, Type, TypeArg, TypeRow}; use crate::IncomingPort; pub(crate) trait DataflowOpTrait { @@ -153,7 +153,9 @@ impl StaticTag for T { #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Call { /// Signature of function being called - pub signature: FunctionType, + func_sig: PolyFuncType, + type_args: Vec, + instantiation: FunctionType, // Cache, so we can fail in try_new() not in signature() } impl_op_name!(Call); @@ -165,7 +167,7 @@ impl DataflowOpTrait for Call { } fn signature(&self) -> FunctionType { - self.signature.clone() + self.instantiation.clone() } fn static_input(&self) -> Option { @@ -174,10 +176,28 @@ impl DataflowOpTrait for Call { } } impl Call { + /// Try to make a new Call. Returns an error if the `type_args`` do not fit the [TypeParam]s + /// declared by the function. + /// + /// [TypeParam]: crate::types::type_param::TypeParam + pub fn try_new( + func_sig: PolyFuncType, + type_args: impl Into>, + exts: &ExtensionRegistry, + ) -> Result { + let type_args = type_args.into(); + let instantiation = func_sig.instantiate(&type_args, exts)?; + Ok(Self { + func_sig, + type_args, + instantiation, + }) + } + #[inline] /// Return the signature of the function called by this op. - pub fn called_function_type(&self) -> &FunctionType { - &self.signature + pub fn called_function_type(&self) -> &PolyFuncType { + &self.func_sig } /// The IncomingPort which links to the function being called. @@ -189,8 +209,9 @@ impl Call { /// # use hugr::ops::OpType; /// # use hugr::types::FunctionType; /// # use hugr::extension::prelude::QB_T; + /// # use hugr::extension::PRELUDE_REGISTRY; /// let signature = FunctionType::new(vec![QB_T, QB_T], vec![QB_T, QB_T]); - /// let call = Call { signature }; + /// let call = Call::try_new(signature.into(), &[], &PRELUDE_REGISTRY).unwrap(); /// let op = OpType::Call(call.clone()); /// assert_eq!(op.static_input_port(), Some(call.called_function_port())); /// ``` @@ -198,7 +219,7 @@ impl Call { /// [`OpType::static_input_port`]: crate::ops::OpType::static_input_port #[inline] pub fn called_function_port(&self) -> IncomingPort { - self.called_function_type().input_count().into() + self.instantiation.input_count().into() } } From ee7df6f21907f4ece11a9c434e1fa5c3a0242e49 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 17:03:45 +0000 Subject: [PATCH 12/57] Clarify docs of CallIndirect --- quantinuum-hugr/src/ops/dataflow.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quantinuum-hugr/src/ops/dataflow.rs b/quantinuum-hugr/src/ops/dataflow.rs index 3c0dfd47b..9929ac5ac 100644 --- a/quantinuum-hugr/src/ops/dataflow.rs +++ b/quantinuum-hugr/src/ops/dataflow.rs @@ -223,7 +223,11 @@ impl Call { } } -/// Call a function indirectly. Like call, but the first input is a standard dataflow graph type. +/// Call a function indirectly. Like call, but the function input is a value +/// (runtime, not static) dataflow edge, and we assume all its binders have +/// already been given [TypeArg]s by [TypeApply] nodes. +/// +/// [TypeApply]: crate::ops::LeafOp::TypeApply #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct CallIndirect { /// Signature of function being called From 38d68c00ed7f632132d3012ef35cd65672a90527 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 13:39:55 +0000 Subject: [PATCH 13/57] WIP --- quantinuum-hugr/src/types.rs | 20 ++++---- quantinuum-hugr/src/types/type_row.rs | 70 ++++++++++++++------------- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index 6f0af92d9..222e6e68e 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -140,7 +140,7 @@ impl SumType { let rows = variants.into_iter().map(Into::into).collect_vec(); let len: usize = rows.len(); - if len <= (u8::MAX as usize) && rows.iter().all(TypeRow::is_empty) { + if len <= (u8::MAX as usize) && rows.iter().all(TypeRowV::is_empty) { Self::Unit { size: len as u8 } } else { Self::General { rows } @@ -148,9 +148,9 @@ impl SumType { } /// Report the tag'th variant, if it exists. - pub fn get_variant(&self, tag: usize) -> Option<&TypeRow> { + pub fn get_variant(&self, tag: usize) -> Option<&TypeRowV> { match self { - SumType::Unit { size } if tag < (*size as usize) => Some(Type::EMPTY_TYPEROW_REF), + SumType::Unit { size } if tag < (*size as usize) => Some(Type::EMPTY_VL_TYPEROW_REF), SumType::General { rows } => rows.get(tag), _ => None, } @@ -206,8 +206,8 @@ impl TypeEnum { TypeEnum::Sum(SumType::Unit { size: _ }) => TypeBound::Eq, TypeEnum::Sum(SumType::General { rows }) => least_upper_bound( rows.iter() - .flat_map(TypeRow::iter) - .map(Type::least_upper_bound), + .flat_map(TypeRowV::iter) + .map(RowVarOrType::least_upper_bound), ), } } @@ -254,10 +254,13 @@ fn validate_each<'a>( impl Type { /// An empty `TypeRow`. Provided here for convenience pub const EMPTY_TYPEROW: TypeRow = type_row![]; + /// An empty `TypeRowV`. Provided here for convenience + pub const EMPTY_VL_TYPEROW: TypeRowV = type_row![]; /// Unit type (empty tuple). pub const UNIT: Self = Self(TypeEnum::Sum(SumType::Unit { size: 1 }), TypeBound::Eq); const EMPTY_TYPEROW_REF: &'static TypeRow = &Self::EMPTY_TYPEROW; + const EMPTY_VL_TYPEROW_REF: &'static TypeRowV = &Self::EMPTY_VL_TYPEROW; /// Initialize a new function type. pub fn new_function(fun_ty: impl Into) -> Self { @@ -343,11 +346,10 @@ impl Type { // There is no need to check the components against the bound, // that is guaranteed by construction (even for deserialization) match &self.0 { - TypeEnum::Sum(SumType::General { rows }) => validate_each( + TypeEnum::Sum(SumType::General { rows }) => + rows.iter().try_for_each(|row| valid_row(row, extension_registry, - var_decls, - rows.iter().flat_map(|x| x.iter()), - ), + var_decls)), TypeEnum::Sum(SumType::Unit { .. }) => Ok(()), // No leaves there TypeEnum::Alias(_) => Ok(()), TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index e0cce66cd..ecdf7bc36 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -31,6 +31,13 @@ impl RowVarOrType { } } } + +impl From for RowVarOrType { + fn from(value: Type) -> Self { + Self::T(value) + } +} + /// List of types, used for function signatures. #[derive(Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)] #[non_exhaustive] @@ -61,53 +68,34 @@ impl TypeRowBase where [T]: ToOwned> { } } - delegate! { - to self.types { - /// Iterator over the types and row variables in the row. - pub fn iter(&self) -> impl Iterator; - - /// Mutable vector of the types and row variables in the row. - pub fn to_mut(&mut self) -> &mut Vec; - - /// Allow access (consumption) of the contained elements - pub fn into_owned(self) -> Vec; - } - } -} - -impl From for TypeRowV { - fn from(value: TypeRow) -> Self { - Self { - types: value.into_owned().into_iter().map(RowVarOrType::T).collect() - } - } -} - -impl TypeRow { #[inline(always)] /// Returns the port type given an offset. Returns `None` if the offset is out of bounds. - pub fn get(&self, offset: impl PortIndex) -> Option<&Type> { + pub fn get(&self, offset: impl PortIndex) -> Option<&T> { self.types.get(offset.index()) } #[inline(always)] /// Returns the port type given an offset. Returns `None` if the offset is out of bounds. - pub fn get_mut(&mut self, offset: impl PortIndex) -> Option<&mut Type> { + pub fn get_mut(&mut self, offset: impl PortIndex) -> Option<&mut T> { self.types.to_mut().get_mut(offset.index()) } - /// Returns a new `TypeRow` with `xs` concatenated onto `self`. - pub fn extend<'a>(&'a self, rest: impl IntoIterator) -> Self { - self.iter().chain(rest).cloned().collect_vec().into() - } - /// Returns a reference to the types in the row. - pub fn as_slice(&self) -> &[Type] { + pub fn as_slice(&self) -> &[T] { &self.types } delegate! { to self.types { + /// Iterator over the types and row variables in the row. + pub fn iter(&self) -> impl Iterator; + + /// Mutable vector of the types and row variables in the row. + pub fn to_mut(&mut self) -> &mut Vec; + + /// Allow access (consumption) of the contained elements + pub fn into_owned(self) -> Vec; + /// Returns the number of types in the row. pub fn len(&self) -> usize; @@ -117,13 +105,27 @@ impl TypeRow { } } +impl TypeRowBase where T: Clone, [T]: ToOwned> { + /// Returns a new `TypeRow` with `xs` concatenated onto `self`. + pub fn extend<'a>(&'a self, rest: impl IntoIterator) -> Self { + self.iter().chain(rest).cloned().collect_vec().into() + } +} + +impl Into> for TypeRow { + fn into(self: TypeRow) -> Cow<'static, [RowVarOrType]> { + self.types.into_owned().into_iter().map(RowVarOrType::from).collect() + } +} + + impl Default for TypeRowBase where [T]: ToOwned> { fn default() -> Self { Self::new() } } -impl From for TypeRowBase +impl From for TypeRowBase // impl From for TypeRowV where F: Into> where F: Into>, [T]: ToOwned> @@ -135,13 +137,13 @@ where } } -impl From for TypeRowBase { +/*impl From for TypeRowBase { fn from(t: Type) -> Self { Self { types: vec![t].into(), } } -} +}*/ impl Deref for TypeRowBase where [T]: ToOwned> { type Target = [T]; From 98806a411c54ce299a14fdf0b5f155a3b4ab8f0e Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 13:58:21 +0000 Subject: [PATCH 14/57] Go via IntoIterator?? --- quantinuum-hugr/src/types.rs | 26 ++++---- quantinuum-hugr/src/types/type_row.rs | 94 +++++++++++++++++++-------- 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index 222e6e68e..b6f1d2540 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -346,10 +346,9 @@ impl Type { // There is no need to check the components against the bound, // that is guaranteed by construction (even for deserialization) match &self.0 { - TypeEnum::Sum(SumType::General { rows }) => - rows.iter().try_for_each(|row| valid_row(row, - extension_registry, - var_decls)), + TypeEnum::Sum(SumType::General { rows }) => rows + .iter() + .try_for_each(|row| valid_row(row, extension_registry, var_decls)), TypeEnum::Sum(SumType::Unit { .. }) => Ok(()), // No leaves there TypeEnum::Alias(_) => Ok(()), TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), @@ -399,16 +398,15 @@ fn valid_row( exts: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - row.iter() - .try_for_each(|t| match t { - RowVarOrType::T(t) => t.validate(exts, var_decls), - RowVarOrType::RV(idx, bound) => { - let t = TypeParam::List { - param: Box::new((*bound).into()), - }; - check_typevar_decl(var_decls, *idx, &t) - }, - }) + row.iter().try_for_each(|t| match t { + RowVarOrType::T(t) => t.validate(exts, var_decls), + RowVarOrType::RV(idx, bound) => { + let t = TypeParam::List { + param: Box::new((*bound).into()), + }; + check_typevar_decl(var_decls, *idx, &t) + } + }) } fn subst_row(row: &TypeRowV, tr: &impl Substitution) -> TypeRowV { diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index ecdf7bc36..7baf4fe4b 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -11,11 +11,12 @@ use super::{Type, TypeBound}; use crate::utils::display_list; use crate::PortIndex; use delegate::delegate; -use itertools::Itertools; -#[derive(Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display)] +#[derive( + Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display, +)] pub enum RowVarOrType { - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] T(Type), /// DeBruijn index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type] /// of this bound (checked in validation) @@ -43,8 +44,10 @@ impl From for RowVarOrType { #[non_exhaustive] #[serde(transparent)] pub struct TypeRowBase - where T: 'static,//Clone + PartialEq + Eq + std::fmt::Debug + serde::Serialize + 'static, - [T]: ToOwned> { +where + T: 'static, //Clone + PartialEq + Eq + std::fmt::Debug + serde::Serialize + 'static, + [T]: ToOwned>, +{ /// The datatypes in the row. types: Cow<'static, [T]>, } @@ -52,7 +55,10 @@ pub struct TypeRowBase pub type TypeRow = TypeRowBase; pub type TypeRowV = TypeRowBase; -impl Display for TypeRowBase where [T]: ToOwned> { +impl Display for TypeRowBase +where + [T]: ToOwned>, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_char('[')?; display_list(self.types.as_ref(), f)?; @@ -60,7 +66,10 @@ impl Display for TypeRowBase where [T]: ToOwned> { } } -impl TypeRowBase where [T]: ToOwned> { +impl TypeRowBase +where + [T]: ToOwned>, +{ /// Create a new empty row. pub const fn new() -> Self { Self { @@ -95,40 +104,42 @@ impl TypeRowBase where [T]: ToOwned> { /// Allow access (consumption) of the contained elements pub fn into_owned(self) -> Vec; - + /// Returns the number of types in the row. pub fn len(&self) -> usize; /// Returns `true` if the row contains no types. - pub fn is_empty(&self) -> bool ; + pub fn is_empty(&self) -> bool ; } } } -impl TypeRowBase where T: Clone, [T]: ToOwned> { +impl TypeRowBase +where + T: Clone, + [T]: ToOwned>, +{ /// Returns a new `TypeRow` with `xs` concatenated onto `self`. pub fn extend<'a>(&'a self, rest: impl IntoIterator) -> Self { - self.iter().chain(rest).cloned().collect_vec().into() - } -} - -impl Into> for TypeRow { - fn into(self: TypeRow) -> Cow<'static, [RowVarOrType]> { - self.types.into_owned().into_iter().map(RowVarOrType::from).collect() + Self { + types: self.iter().chain(rest).cloned().collect(), + } } } - -impl Default for TypeRowBase where [T]: ToOwned> { +impl Default for TypeRowBase +where + [T]: ToOwned>, +{ fn default() -> Self { Self::new() } } -impl From for TypeRowBase // impl From for TypeRowV where F: Into> +impl From for TypeRow +// impl From for TypeRowV where F: Into> where - F: Into>, - [T]: ToOwned> + F: Into>, { fn from(types: F) -> Self { Self { @@ -137,15 +148,26 @@ where } } -/*impl From for TypeRowBase { - fn from(t: Type) -> Self { +impl From for TypeRowV +where + F: IntoIterator, +{ + // Note: I tried "where F: Into>" but that requires + // types.into().into_owned().into_iter() + // both allow use of owned data without cloning, and use of borrowed data with clone + // (this one might require an explicit `.cloned()` from the caller) + // but I think this looks no less efficient (?) + fn from(types: F) -> Self { Self { - types: vec![t].into(), + types: types.into_iter().map(RowVarOrType::from).collect(), } } -}*/ +} -impl Deref for TypeRowBase where [T]: ToOwned> { +impl Deref for TypeRowBase +where + [T]: ToOwned>, +{ type Target = [T]; fn deref(&self) -> &Self::Target { @@ -153,8 +175,24 @@ impl Deref for TypeRowBase where [T]: ToOwned> { } } -impl DerefMut for TypeRowBase where [T]: ToOwned> { +impl DerefMut for TypeRowBase +where + [T]: ToOwned>, +{ fn deref_mut(&mut self) -> &mut Self::Target { self.types.to_mut() } } + +impl IntoIterator for TypeRowBase +where + [T]: ToOwned>, +{ + type Item = T; + + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.types.into_owned().into_iter() + } +} From 81c63d92464706b6660917c81fd7d1628950adbf Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 14:38:58 +0000 Subject: [PATCH 15/57] WIP2 --- quantinuum-hugr/src/types/type_row.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index 7baf4fe4b..12953cbe0 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -11,6 +11,7 @@ use super::{Type, TypeBound}; use crate::utils::display_list; use crate::PortIndex; use delegate::delegate; +use itertools::Itertools; #[derive( Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display, @@ -136,10 +137,10 @@ where } } -impl From for TypeRow -// impl From for TypeRowV where F: Into> +impl From for TypeRowBase where - F: Into>, + [T]: ToOwned>, + F: Into>, { fn from(types: F) -> Self { Self { @@ -148,6 +149,18 @@ where } } +/*impl >> From for TypeRowV { + fn from(value: F) -> Self { + todo!() + } +}*/ + +impl Into> for TypeRow { + fn into(self) -> Cow<'static, [RowVarOrType]> { + self.types.into_owned().into_iter().map(RowVarOrType::from).collect() + } +} + impl From for TypeRowV where F: IntoIterator, @@ -186,13 +199,15 @@ where impl IntoIterator for TypeRowBase where + RowVarOrType: From, [T]: ToOwned>, { - type Item = T; + type Item = RowVarOrType; - type IntoIter = as IntoIterator>::IntoIter; + type IntoIter = itertools::MapInto< as IntoIterator>::IntoIter, RowVarOrType>; fn into_iter(self) -> Self::IntoIter { - self.types.into_owned().into_iter() + let owned = self.types.into_owned(); + owned.into_iter().map_into() } } From efa84e25ea847a6c97b0b5893fffcf90d2bf5bf9 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 14:50:12 +0000 Subject: [PATCH 16/57] Separate impl From for TypeRow/TypeRowV after all, we never have fn foo(x: impl Into>) so no need to parameterize over that --- quantinuum-hugr/src/types/type_row.rs | 50 +++++++++------------------ 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index 12953cbe0..a020fb02a 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -11,7 +11,6 @@ use super::{Type, TypeBound}; use crate::utils::display_list; use crate::PortIndex; use delegate::delegate; -use itertools::Itertools; #[derive( Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display, @@ -137,10 +136,9 @@ where } } -impl From for TypeRowBase +impl From for TypeRow where - [T]: ToOwned>, - F: Into>, + F: Into>, { fn from(types: F) -> Self { Self { @@ -149,27 +147,28 @@ where } } -/*impl >> From for TypeRowV { - fn from(value: F) -> Self { - todo!() - } -}*/ - impl Into> for TypeRow { fn into(self) -> Cow<'static, [RowVarOrType]> { - self.types.into_owned().into_iter().map(RowVarOrType::from).collect() + self.types + .into_owned() + .into_iter() + .map(RowVarOrType::from) + .collect() } } -impl From for TypeRowV +impl From for TypeRowV where - F: IntoIterator, + RowVarOrType: From, + F: IntoIterator, { - // Note: I tried "where F: Into>" but that requires - // types.into().into_owned().into_iter() - // both allow use of owned data without cloning, and use of borrowed data with clone - // (this one might require an explicit `.cloned()` from the caller) - // but I think this looks no less efficient (?) + // Note: I tried "where F: Into>" but + // (a) that requires `types.into().into_owned().into_iter()` + // - both allow use of owned data without cloning, and use of borrowed data with clone + // - (this way might require an explicit `.cloned()` from the caller) + // but I think this looks no less efficient (?) + // (b) can't then parameterize the impl over because it's unconstrained + // (seems F: IntoIterator provides a constraint but F: Into> does not) fn from(types: F) -> Self { Self { types: types.into_iter().map(RowVarOrType::from).collect(), @@ -196,18 +195,3 @@ where self.types.to_mut() } } - -impl IntoIterator for TypeRowBase -where - RowVarOrType: From, - [T]: ToOwned>, -{ - type Item = RowVarOrType; - - type IntoIter = itertools::MapInto< as IntoIterator>::IntoIter, RowVarOrType>; - - fn into_iter(self) -> Self::IntoIter { - let owned = self.types.into_owned(); - owned.into_iter().map_into() - } -} From b205525661f5b743df007c5878564138b2c8b58b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 15:46:12 +0000 Subject: [PATCH 17/57] impl IntoIter for TypeRow (=> RowVarOrType's) --- quantinuum-hugr/src/types/type_row.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index a020fb02a..24518a47c 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -11,6 +11,7 @@ use super::{Type, TypeBound}; use crate::utils::display_list; use crate::PortIndex; use delegate::delegate; +use itertools::Itertools; #[derive( Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display, @@ -195,3 +196,14 @@ where self.types.to_mut() } } + +/// Turns a row of [Type] into an iterator of [RowVarOrType]. +/// An iterator of [Type] can be obtained by `into_owned().into_iter()` +impl IntoIterator for TypeRow { + type Item = RowVarOrType; + type IntoIter = itertools::MapInto< as IntoIterator>::IntoIter, RowVarOrType>; + + fn into_iter(self) -> Self::IntoIter { + self.types.into_owned().into_iter().map_into() + } +} From eee4e29dc0e6c81160b6016637d2afdc8fbeda3d Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 15:47:25 +0000 Subject: [PATCH 18/57] type.rs: don't publicise EMPTY_VL_TYPE_ROW - new() is const. (TODO same non-VL?) --- quantinuum-hugr/src/types.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index b6f1d2540..4b3ca0496 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -254,12 +254,13 @@ fn validate_each<'a>( impl Type { /// An empty `TypeRow`. Provided here for convenience pub const EMPTY_TYPEROW: TypeRow = type_row![]; - /// An empty `TypeRowV`. Provided here for convenience - pub const EMPTY_VL_TYPEROW: TypeRowV = type_row![]; + /// Unit type (empty tuple). pub const UNIT: Self = Self(TypeEnum::Sum(SumType::Unit { size: 1 }), TypeBound::Eq); const EMPTY_TYPEROW_REF: &'static TypeRow = &Self::EMPTY_TYPEROW; + + const EMPTY_VL_TYPEROW: TypeRowV = TypeRowV::new(); const EMPTY_VL_TYPEROW_REF: &'static TypeRowV = &Self::EMPTY_VL_TYPEROW; /// Initialize a new function type. @@ -493,7 +494,7 @@ pub(crate) mod test { #[test] fn sum_construct() { - let pred1 = Type::new_sum([Type::EMPTY_TYPEROW, Type::EMPTY_TYPEROW]); + let pred1 = Type::new_sum([TypeRowV::new(), TypeRowV::new()]); let pred2 = Type::new_unit_sum(2); assert_eq!(pred1, pred2); From 7d7115546c7fb3e27c2e4908ec8b06bce569e667 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 15:48:32 +0000 Subject: [PATCH 19/57] signature.rs: add Signature = fixed-len, FunctionType is var-length --- quantinuum-hugr/src/types/signature.rs | 97 +++++++++++++++----------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/quantinuum-hugr/src/types/signature.rs b/quantinuum-hugr/src/types/signature.rs index c775f4a3d..beadcc8e4 100644 --- a/quantinuum-hugr/src/types/signature.rs +++ b/quantinuum-hugr/src/types/signature.rs @@ -5,8 +5,8 @@ use itertools::Either; use std::fmt::{self, Display, Write}; use super::type_param::TypeParam; -use super::type_row::TypeRowV; -use super::{subst_row, valid_row, Substitution, Type, TypeRow}; +use super::type_row::{RowVarOrType, TypeRowBase}; +use super::{subst_row, valid_row, Substitution, Type, TypeRowV}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::{Direction, IncomingPort, OutgoingPort, Port}; @@ -14,22 +14,53 @@ use crate::{Direction, IncomingPort, OutgoingPort, Port}; #[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)] /// Describes the edges required to/from a node. This includes both the concept of "signature" in the spec, /// and also the target (value) of a call (static). -pub struct FunctionType { +pub struct FuncTypeBase +where + T: 'static, + [T]: ToOwned>, +{ /// Value inputs of the function. - pub input: TypeRowV, + pub input: TypeRowBase, /// Value outputs of the function. - pub output: TypeRowV, + pub output: TypeRowBase, /// The extension requirements which are added by the operation pub extension_reqs: ExtensionSet, } -impl FunctionType { +/// The type of a function, e.g. passing around a pointer/static ref to it. +pub type FunctionType = FuncTypeBase; + +/// The type of a node. Fixed/known arity of inputs + outputs. +pub type Signature = FuncTypeBase; + +impl FuncTypeBase +where + T: 'static + Clone, + [T]: ToOwned>, +{ /// Builder method, add extension_reqs to an FunctionType pub fn with_extension_delta(mut self, rs: impl Into) -> Self { self.extension_reqs = self.extension_reqs.union(rs.into()); self } + /// Create a new signature with specified inputs and outputs. + pub fn new(input: impl Into>, output: impl Into>) -> Self { + Self { + input: input.into(), + output: output.into(), + extension_reqs: ExtensionSet::new(), + } + } + /// Create a new signature with the same input and output types (signature of an endomorphic + /// function). + pub fn new_endo(linear: impl Into>) -> Self { + let linear = linear.into(); + Self::new(linear.clone(), linear) + } +} + +impl FunctionType { pub(crate) fn validate( &self, extension_registry: &ExtensionRegistry, @@ -41,37 +72,32 @@ impl FunctionType { } pub(crate) fn substitute(&self, tr: &impl Substitution) -> Self { - FunctionType { + Self { input: subst_row(&self.input, tr), output: subst_row(&self.output, tr), extension_reqs: self.extension_reqs.substitute(tr), } } + + #[inline] + /// Returns the input row + pub fn input(&self) -> &TypeRowV { + &self.input + } + + #[inline] + /// Returns the output row + pub fn output(&self) -> &TypeRowV { + &self.output + } } -impl FunctionType { +impl Signature { /// The number of wires in the signature. #[inline(always)] pub fn is_empty(&self) -> bool { self.input.is_empty() && self.output.is_empty() } -} - -impl FunctionType { - /// Create a new signature with specified inputs and outputs. - pub fn new(input: impl Into, output: impl Into) -> Self { - Self { - input: input.into(), - output: output.into(), - extension_reqs: ExtensionSet::new(), - } - } - /// Create a new signature with the same input and output types (signature of an endomorphic - /// function). - pub fn new_endo(linear: impl Into) -> Self { - let linear = linear.into(); - Self::new(linear.clone(), linear) - } /// Returns the type of a value [`Port`]. Returns `None` if the port is out /// of bounds. @@ -165,20 +191,6 @@ impl FunctionType { self.types(Direction::Outgoing) } - #[inline] - /// Returns the input row - pub fn input(&self) -> &TypeRow { - &self.input - } - - #[inline] - /// Returns the output row - pub fn output(&self) -> &TypeRow { - &self.output - } -} - -impl FunctionType { /// Returns the `Port`s in the signature for a given direction. #[inline] pub fn ports(&self, dir: Direction) -> impl Iterator { @@ -200,7 +212,10 @@ impl FunctionType { } } -impl Display for FunctionType { +impl Display for FuncTypeBase +where + [T]: ToOwned>, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if !self.input.is_empty() { self.input.fmt(f)?; @@ -220,7 +235,7 @@ mod test { use super::*; #[test] fn test_function_type() { - let mut f_type = FunctionType::new(type_row![Type::UNIT], type_row![Type::UNIT]); + let mut f_type = Signature::new(type_row![Type::UNIT], type_row![Type::UNIT]); assert_eq!(f_type.input_count(), 1); assert_eq!(f_type.output_count(), 1); From 97e6fd8aa2901f1fe2ebc96a256754379ae32ea8 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 15:51:43 +0000 Subject: [PATCH 20/57] WIP --- quantinuum-hugr/src/ops/controlflow.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quantinuum-hugr/src/ops/controlflow.rs b/quantinuum-hugr/src/ops/controlflow.rs index 41d597e60..ecf8a6917 100644 --- a/quantinuum-hugr/src/ops/controlflow.rs +++ b/quantinuum-hugr/src/ops/controlflow.rs @@ -30,10 +30,10 @@ impl DataflowOpTrait for TailLoop { "A tail-controlled loop" } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { let [inputs, outputs] = [&self.just_inputs, &self.just_outputs].map(|row| row.extend(self.rest.iter())); - FunctionType::new(inputs, outputs) + Signature::new(inputs, outputs) } } From ef977ff1caed3f671da330bfeccc02d0da2b5459 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 16:32:04 +0000 Subject: [PATCH 21/57] signature() methods return Signature --- quantinuum-hugr/src/ops.rs | 4 +-- quantinuum-hugr/src/ops/controlflow.rs | 18 ++++++------ quantinuum-hugr/src/ops/custom.rs | 6 ++-- quantinuum-hugr/src/ops/dataflow.rs | 40 ++++++++++++++------------ quantinuum-hugr/src/ops/leaf.rs | 2 +- quantinuum-hugr/src/ops/module.rs | 4 +-- quantinuum-hugr/src/types.rs | 2 +- quantinuum-hugr/src/types/signature.rs | 14 ++++++++- 8 files changed, 52 insertions(+), 38 deletions(-) diff --git a/quantinuum-hugr/src/ops.rs b/quantinuum-hugr/src/ops.rs index 7145b35e1..9edcb4c41 100644 --- a/quantinuum-hugr/src/ops.rs +++ b/quantinuum-hugr/src/ops.rs @@ -10,7 +10,7 @@ pub mod module; pub mod tag; pub mod validate; use crate::extension::ExtensionSet; -use crate::types::{EdgeKind, FunctionType}; +use crate::types::{EdgeKind, Signature}; use crate::{Direction, OutgoingPort, Port}; use crate::{IncomingPort, PortIndex}; use paste::paste; @@ -319,7 +319,7 @@ pub trait OpTrait { /// The signature of the operation. /// /// Only dataflow operations have a signature, otherwise returns None. - fn dataflow_signature(&self) -> Option { + fn dataflow_signature(&self) -> Option { None } diff --git a/quantinuum-hugr/src/ops/controlflow.rs b/quantinuum-hugr/src/ops/controlflow.rs index ecf8a6917..5d9e27f5d 100644 --- a/quantinuum-hugr/src/ops/controlflow.rs +++ b/quantinuum-hugr/src/ops/controlflow.rs @@ -3,7 +3,7 @@ use smol_str::SmolStr; use crate::extension::ExtensionSet; -use crate::types::{EdgeKind, FunctionType, Type, TypeRow}; +use crate::types::{EdgeKind, Signature, Type, TypeRow}; use crate::Direction; use super::dataflow::{DataflowOpTrait, DataflowParent}; @@ -73,12 +73,12 @@ impl DataflowOpTrait for Conditional { "HUGR conditional operation" } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { let mut inputs = self.other_inputs.clone(); inputs .to_mut() .insert(0, Type::new_sum(self.sum_rows.clone())); - FunctionType::new(inputs, self.outputs.clone()) + Signature::new(inputs, self.outputs.clone()) .with_extension_delta(self.extension_delta.clone()) } } @@ -94,7 +94,7 @@ impl Conditional { #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[allow(missing_docs)] pub struct CFG { - pub signature: FunctionType, + pub signature: Signature, } impl_op_name!(CFG); @@ -106,7 +106,7 @@ impl DataflowOpTrait for CFG { "A dataflow node defined by a child CFG" } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { self.signature.clone() } } @@ -150,12 +150,12 @@ impl StaticTag for ExitBlock { } impl DataflowParent for DataflowBlock { - fn inner_signature(&self) -> FunctionType { + fn inner_signature(&self) -> Signature { // The node outputs a Sum before the data outputs of the block node let sum_type = Type::new_sum(self.sum_rows.clone()); let mut node_outputs = vec![sum_type]; node_outputs.extend_from_slice(&self.other_outputs); - FunctionType::new(self.inputs.clone(), TypeRow::from(node_outputs)) + Signature::new(self.inputs.clone(), TypeRow::from(node_outputs)) } } @@ -246,7 +246,7 @@ impl BasicBlock for ExitBlock { /// Case ops - nodes valid inside Conditional nodes. pub struct Case { /// The signature of the contained dataflow graph. - pub signature: FunctionType, + pub signature: Signature, } impl_op_name!(Case); @@ -256,7 +256,7 @@ impl StaticTag for Case { } impl DataflowParent for Case { - fn inner_signature(&self) -> FunctionType { + fn inner_signature(&self) -> Signature { self.signature.clone() } } diff --git a/quantinuum-hugr/src/ops/custom.rs b/quantinuum-hugr/src/ops/custom.rs index d4e4c88a6..3e36eeecb 100644 --- a/quantinuum-hugr/src/ops/custom.rs +++ b/quantinuum-hugr/src/ops/custom.rs @@ -93,7 +93,7 @@ impl DataflowOpTrait for ExternalOp { } } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { match self { Self::Opaque(op) => op.signature.clone(), Self::Extension(ext_op) => ext_op.signature(), @@ -187,7 +187,7 @@ impl DataflowOpTrait for ExtensionOp { self.def().description() } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { self.signature.clone() } } @@ -264,7 +264,7 @@ impl DataflowOpTrait for OpaqueOp { &self.description } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { self.signature.clone() } } diff --git a/quantinuum-hugr/src/ops/dataflow.rs b/quantinuum-hugr/src/ops/dataflow.rs index 9929ac5ac..790074f50 100644 --- a/quantinuum-hugr/src/ops/dataflow.rs +++ b/quantinuum-hugr/src/ops/dataflow.rs @@ -4,13 +4,13 @@ use super::{impl_op_name, OpTag, OpTrait}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::ops::StaticTag; -use crate::types::{EdgeKind, FunctionType, PolyFuncType, Type, TypeArg, TypeRow}; +use crate::types::{EdgeKind, Signature, PolyFuncType, Type, TypeArg, TypeRow}; use crate::IncomingPort; pub(crate) trait DataflowOpTrait { const TAG: OpTag; fn description(&self) -> &str; - fn signature(&self) -> FunctionType; + fn signature(&self) -> Signature; /// The edge kind for the non-dataflow or constant inputs of the operation, /// not described by the signature. @@ -94,8 +94,8 @@ impl DataflowOpTrait for Input { None } - fn signature(&self) -> FunctionType { - FunctionType::new(TypeRow::new(), self.types.clone()) + fn signature(&self) -> Signature { + Signature::new(TypeRow::new(), self.types.clone()) } } impl DataflowOpTrait for Output { @@ -107,8 +107,8 @@ impl DataflowOpTrait for Output { // Note: We know what the input extensions should be, so we *could* give an // instantiated Signature instead - fn signature(&self) -> FunctionType { - FunctionType::new(self.types.clone(), TypeRow::new()) + fn signature(&self) -> Signature { + Signature::new(self.types.clone(), TypeRow::new()) } fn other_output(&self) -> Option { @@ -123,7 +123,7 @@ impl OpTrait for T { fn tag(&self) -> OpTag { T::TAG } - fn dataflow_signature(&self) -> Option { + fn dataflow_signature(&self) -> Option { Some(DataflowOpTrait::signature(self)) } fn extension_delta(&self) -> ExtensionSet { @@ -155,7 +155,7 @@ pub struct Call { /// Signature of function being called func_sig: PolyFuncType, type_args: Vec, - instantiation: FunctionType, // Cache, so we can fail in try_new() not in signature() + instantiation: Signature, // Cache, so we can fail in try_new() not in signature() } impl_op_name!(Call); @@ -166,7 +166,7 @@ impl DataflowOpTrait for Call { "Call a function directly" } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { self.instantiation.clone() } @@ -186,7 +186,9 @@ impl Call { exts: &ExtensionRegistry, ) -> Result { let type_args = type_args.into(); - let instantiation = func_sig.instantiate(&type_args, exts)?; + let instantiation = func_sig.instantiate(&type_args, exts)? + .try_into() + .map_err(|(idx, _)|SignatureError::RowTypeVarOutsideRow { idx })?; Ok(Self { func_sig, type_args, @@ -207,7 +209,7 @@ impl Call { /// ``` /// # use hugr::ops::dataflow::Call; /// # use hugr::ops::OpType; - /// # use hugr::types::FunctionType; + /// # use hugr::types::Signature; /// # use hugr::extension::prelude::QB_T; /// # use hugr::extension::PRELUDE_REGISTRY; /// let signature = FunctionType::new(vec![QB_T, QB_T], vec![QB_T, QB_T]); @@ -231,7 +233,7 @@ impl Call { #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct CallIndirect { /// Signature of function being called - pub signature: FunctionType, + pub signature: Signature, } impl_op_name!(CallIndirect); @@ -242,7 +244,7 @@ impl DataflowOpTrait for CallIndirect { "Call a function indirectly" } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { let mut s = self.signature.clone(); s.input .to_mut() @@ -265,8 +267,8 @@ impl DataflowOpTrait for LoadConstant { "Load a static constant in to the local dataflow graph" } - fn signature(&self) -> FunctionType { - FunctionType::new(TypeRow::new(), vec![self.datatype.clone()]) + fn signature(&self) -> Signature { + Signature::new(TypeRow::new(), vec![self.datatype.clone()]) } fn static_input(&self) -> Option { @@ -304,20 +306,20 @@ impl LoadConstant { /// Operations that is the parent of a dataflow graph. pub trait DataflowParent { /// Signature of the inner dataflow graph. - fn inner_signature(&self) -> FunctionType; + fn inner_signature(&self) -> Signature; } /// A simply nested dataflow graph. #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct DFG { /// Signature of DFG node - pub signature: FunctionType, + pub signature: Signature, } impl_op_name!(DFG); impl DataflowParent for DFG { - fn inner_signature(&self) -> FunctionType { + fn inner_signature(&self) -> Signature { self.signature.clone() } } @@ -329,7 +331,7 @@ impl DataflowOpTrait for DFG { "A simply nested dataflow graph" } - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { self.inner_signature() } } diff --git a/quantinuum-hugr/src/ops/leaf.rs b/quantinuum-hugr/src/ops/leaf.rs index 07476ff7a..127d0553a 100644 --- a/quantinuum-hugr/src/ops/leaf.rs +++ b/quantinuum-hugr/src/ops/leaf.rs @@ -179,7 +179,7 @@ impl DataflowOpTrait for LeafOp { } /// The signature of the operation. - fn signature(&self) -> FunctionType { + fn signature(&self) -> Signature { // Static signatures. The `TypeRow`s in the `FunctionType` use a // copy-on-write strategy, so we can avoid unnecessary allocations. diff --git a/quantinuum-hugr/src/ops/module.rs b/quantinuum-hugr/src/ops/module.rs index 060b3354a..eaf52ce27 100644 --- a/quantinuum-hugr/src/ops/module.rs +++ b/quantinuum-hugr/src/ops/module.rs @@ -2,7 +2,7 @@ use smol_str::SmolStr; -use crate::types::{EdgeKind, FunctionType, PolyFuncType}; +use crate::types::{EdgeKind, PolyFuncType, Signature}; use crate::types::{Type, TypeBound}; use super::dataflow::DataflowParent; @@ -46,7 +46,7 @@ impl StaticTag for FuncDefn { } impl DataflowParent for FuncDefn { - fn inner_signature(&self) -> FunctionType { + fn inner_signature(&self) -> Signature { self.signature.body().clone() } } diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index 4b3ca0496..c64c41ebe 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -13,7 +13,7 @@ use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; pub use poly_func::PolyFuncType; -pub use signature::FunctionType; +pub use signature::{Signature, FunctionType}; use smol_str::SmolStr; pub use type_param::TypeArg; pub use type_row::TypeRow; diff --git a/quantinuum-hugr/src/types/signature.rs b/quantinuum-hugr/src/types/signature.rs index beadcc8e4..8e892eb11 100644 --- a/quantinuum-hugr/src/types/signature.rs +++ b/quantinuum-hugr/src/types/signature.rs @@ -6,7 +6,7 @@ use std::fmt::{self, Display, Write}; use super::type_param::TypeParam; use super::type_row::{RowVarOrType, TypeRowBase}; -use super::{subst_row, valid_row, Substitution, Type, TypeRowV}; +use super::{subst_row, valid_row, Substitution, Type, TypeBound, TypeRowV}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::{Direction, IncomingPort, OutgoingPort, Port}; @@ -33,6 +33,18 @@ pub type FunctionType = FuncTypeBase; /// The type of a node. Fixed/known arity of inputs + outputs. pub type Signature = FuncTypeBase; +impl TryFrom for Signature { + type Error = (usize, TypeBound); + + fn try_from(value: FunctionType) -> Result { + Ok(Self { + input: value.input.try_into()?, + output: value.output.try_into()?, + extension_reqs: value.extension_reqs + }) + } +} + impl FuncTypeBase where T: 'static + Clone, From aeb0d2ff25efb6c2a6264968dfa48a37c24f47c1 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 17:34:04 +0000 Subject: [PATCH 22/57] Remove TryFrom (fixup earlier) --- quantinuum-hugr/src/types/signature.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/quantinuum-hugr/src/types/signature.rs b/quantinuum-hugr/src/types/signature.rs index 8e892eb11..b820ab2f8 100644 --- a/quantinuum-hugr/src/types/signature.rs +++ b/quantinuum-hugr/src/types/signature.rs @@ -33,18 +33,6 @@ pub type FunctionType = FuncTypeBase; /// The type of a node. Fixed/known arity of inputs + outputs. pub type Signature = FuncTypeBase; -impl TryFrom for Signature { - type Error = (usize, TypeBound); - - fn try_from(value: FunctionType) -> Result { - Ok(Self { - input: value.input.try_into()?, - output: value.output.try_into()?, - extension_reqs: value.extension_reqs - }) - } -} - impl FuncTypeBase where T: 'static + Clone, From 63e9c9766a86ea6444c79f0b7ccf4e77da2fd878 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 16:44:49 +0000 Subject: [PATCH 23/57] PolyFuncType impls From; add some Into/TryInto --- quantinuum-hugr/src/types/poly_func.rs | 13 +++++++++++-- quantinuum-hugr/src/types/signature.rs | 22 ++++++++++++++++++++++ quantinuum-hugr/src/types/type_row.rs | 16 ++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index 0a061e28f..9691a9f52 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -6,8 +6,11 @@ use crate::{ }; use itertools::Itertools; -use super::type_param::{check_type_args, TypeArg, TypeParam}; -use super::{FunctionType, Substitution, Type, TypeBound}; +use super::{ + type_param::{check_type_args, TypeArg, TypeParam}, + type_row::RowVarOrType, +}; +use super::{FunctionType, Signature, Substitution, Type, TypeBound}; /// A polymorphic function type, e.g. of a [Graph], or perhaps an [OpDef]. /// (Nodes/operations in the Hugr are not polymorphic.) @@ -43,6 +46,12 @@ impl From for PolyFuncType { } } +impl From for PolyFuncType { + fn from(value: Signature) -> Self { + FunctionType::from(value).into() + } +} + impl PolyFuncType { /// The type parameters, aka binders, over which this type is polymorphic pub fn params(&self) -> &[TypeParam] { diff --git a/quantinuum-hugr/src/types/signature.rs b/quantinuum-hugr/src/types/signature.rs index b820ab2f8..afe35b1c7 100644 --- a/quantinuum-hugr/src/types/signature.rs +++ b/quantinuum-hugr/src/types/signature.rs @@ -212,6 +212,28 @@ impl Signature { } } +impl From for FunctionType { + fn from(sig: Signature) -> Self { + Self { + input: sig.input.into(), + output: sig.output.into(), + extension_reqs: sig.extension_reqs, + } + } +} + +impl TryFrom for Signature { + type Error = (usize, TypeBound); + + fn try_from(funty: FunctionType) -> Result { + Ok(Self { + input: funty.input.try_into()?, + output: funty.output.try_into()?, + extension_reqs: funty.extension_reqs, + }) + } +} + impl Display for FuncTypeBase where [T]: ToOwned>, diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index 24518a47c..00f180876 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -207,3 +207,19 @@ impl IntoIterator for TypeRow { self.types.into_owned().into_iter().map_into() } } + +impl TryInto for TypeRowV { + type Error = (usize, TypeBound); + + fn try_into(self) -> Result { + self.types + .into_owned() + .into_iter() + .map(|rvt| match rvt { + RowVarOrType::T(ty) => Ok(ty), + RowVarOrType::RV(idx, bound) => Err((idx, bound)), + }) + .collect::, _>>() + .map(TypeRow::from) + } +} From 1dbd1cab7dd7fff8c638ad0c4feaf101e7ee7b9d Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 16:47:34 +0000 Subject: [PATCH 24/57] fix apply_rowvar --- quantinuum-hugr/src/types/poly_func.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index 9691a9f52..eaad18c5d 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -169,7 +169,7 @@ impl<'a> Substitution for SubstValues<'a> { arg.clone() } - fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { + fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { let arg = self .0 .get(idx) @@ -181,11 +181,8 @@ impl<'a> Substitution for SubstValues<'a> { TypeArg::Type { ty } => ty.clone(), _ => panic!("Not a list of types - did validate() ?"), }) + .map(RowVarOrType::T) .collect(), - TypeArg::Type { ty } => { - debug_assert_eq!(check_type_arg(arg, &TypeParam::Type { b: bound }), Ok(())); - vec![ty.clone()] - } _ => panic!("Not a type or list of types - did validate() ?"), } } From 09459139028135d78281bd3ee9d10578f1300f62 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 16:51:51 +0000 Subject: [PATCH 25/57] More Signature stuff --- quantinuum-hugr/src/hugr.rs | 4 ++-- quantinuum-hugr/src/ops.rs | 4 ++-- quantinuum-hugr/src/types.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/quantinuum-hugr/src/hugr.rs b/quantinuum-hugr/src/hugr.rs index c92231804..a14f7df13 100644 --- a/quantinuum-hugr/src/hugr.rs +++ b/quantinuum-hugr/src/hugr.rs @@ -30,7 +30,7 @@ use crate::extension::infer_extensions; use crate::extension::{ExtensionRegistry, ExtensionSet, ExtensionSolution, InferExtensionError}; use crate::ops::custom::resolve_extension_ops; use crate::ops::{OpTag, OpTrait, OpType, DEFAULT_OPTYPE}; -use crate::types::FunctionType; +use crate::types::Signature; use crate::{Direction, Node}; use delegate::delegate; @@ -108,7 +108,7 @@ impl NodeType { } /// Get the function type from the embedded op - pub fn op_signature(&self) -> Option { + pub fn op_signature(&self) -> Option { self.op.dataflow_signature() } diff --git a/quantinuum-hugr/src/ops.rs b/quantinuum-hugr/src/ops.rs index 9edcb4c41..05e222341 100644 --- a/quantinuum-hugr/src/ops.rs +++ b/quantinuum-hugr/src/ops.rs @@ -382,13 +382,13 @@ pub trait OpParent { /// sibling graph. /// /// Non-container ops like `FuncDecl` return `None` even though they represent a function. - fn inner_function_type(&self) -> Option { + fn inner_function_type(&self) -> Option { None } } impl OpParent for T { - fn inner_function_type(&self) -> Option { + fn inner_function_type(&self) -> Option { Some(DataflowParent::inner_signature(self)) } } diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index c64c41ebe..3d134ba4d 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -13,7 +13,7 @@ use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; pub use poly_func::PolyFuncType; -pub use signature::{Signature, FunctionType}; +pub use signature::{FunctionType, Signature}; use smol_str::SmolStr; pub use type_param::TypeArg; pub use type_row::TypeRow; From 5274103c59a6f27624481746eb929781332e36ea Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 16:52:16 +0000 Subject: [PATCH 26/57] Manually implement Default for FuncTypeBase - can we revert this later?? --- quantinuum-hugr/src/types/signature.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/quantinuum-hugr/src/types/signature.rs b/quantinuum-hugr/src/types/signature.rs index afe35b1c7..0a7d6fb15 100644 --- a/quantinuum-hugr/src/types/signature.rs +++ b/quantinuum-hugr/src/types/signature.rs @@ -11,7 +11,7 @@ use super::{subst_row, valid_row, Substitution, Type, TypeBound, TypeRowV}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::{Direction, IncomingPort, OutgoingPort, Port}; -#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] /// Describes the edges required to/from a node. This includes both the concept of "signature" in the spec, /// and also the target (value) of a call (static). pub struct FuncTypeBase @@ -27,6 +27,20 @@ where pub extension_reqs: ExtensionSet, } +impl Default for FuncTypeBase +where + T: 'static, + [T]: ToOwned>, +{ + fn default() -> Self { + Self { + input: Default::default(), + output: Default::default(), + extension_reqs: Default::default(), + } + } +} + /// The type of a function, e.g. passing around a pointer/static ref to it. pub type FunctionType = FuncTypeBase; From 406a656488488a6f2abc71727fed35c3caa4fedc Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 16:52:43 +0000 Subject: [PATCH 27/57] Generalize Type::new_sum --- quantinuum-hugr/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index 3d134ba4d..e197081bf 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -280,7 +280,7 @@ impl Type { /// Initialize a new sum type by providing the possible variant types. #[inline(always)] - pub fn new_sum(variants: impl IntoIterator) -> Self where { + pub fn new_sum>(variants: impl IntoIterator) -> Self where { Self::new(TypeEnum::Sum(SumType::new(variants))) } From 84a7a76ef6ba167d3aec09c2b1e50eba088e5c67 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 17:06:19 +0000 Subject: [PATCH 28/57] new_endo(vec![]) and similar empty types -> default() --- quantinuum-hugr/src/extension/type_def.rs | 2 +- quantinuum-hugr/src/types.rs | 4 ++-- quantinuum-hugr/src/types/serialize.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/quantinuum-hugr/src/extension/type_def.rs b/quantinuum-hugr/src/extension/type_def.rs index dd13b453f..50363a7b7 100644 --- a/quantinuum-hugr/src/extension/type_def.rs +++ b/quantinuum-hugr/src/extension/type_def.rs @@ -186,7 +186,7 @@ mod test { }; let typ = Type::new_extension( def.instantiate(vec![TypeArg::Type { - ty: Type::new_function(FunctionType::new(vec![], vec![])), + ty: Type::new_function(FunctionType::default()), }]) .unwrap(), ); diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index e197081bf..ca4480b65 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -236,7 +236,7 @@ impl TypeEnum { /// ``` /// # use hugr::types::{Type, TypeBound, FunctionType}; /// -/// let func_type = Type::new_function(FunctionType::new_endo(vec![])); +/// let func_type = Type::new_function(FunctionType::default()); /// assert_eq!(func_type.least_upper_bound(), TypeBound::Copyable); /// /// ``` @@ -466,7 +466,7 @@ pub(crate) mod test { fn construct() { let t: Type = Type::new_tuple(vec![ USIZE_T, - Type::new_function(FunctionType::new_endo(vec![])), + Type::new_function(FunctionType::default()), Type::new_extension(CustomType::new( "my_custom", [], diff --git a/quantinuum-hugr/src/types/serialize.rs b/quantinuum-hugr/src/types/serialize.rs index 7cf6674c5..4fd098141 100644 --- a/quantinuum-hugr/src/types/serialize.rs +++ b/quantinuum-hugr/src/types/serialize.rs @@ -68,7 +68,7 @@ mod test { #[test] fn serialize_types_roundtrip() { - let g: Type = Type::new_function(FunctionType::new_endo(vec![])); + let g: Type = Type::new_function(FunctionType::default()); assert_eq!(ser_roundtrip(&g), g); From bf6bb1d9923a47a95ccb0b59c8d7b741e5fb2c60 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 17:22:04 +0000 Subject: [PATCH 29/57] More FunctionType -> Signature (op_def.rs) --- quantinuum-hugr/src/extension.rs | 3 +++ quantinuum-hugr/src/extension/op_def.rs | 22 +++++++++++++--------- quantinuum-hugr/src/ops/custom.rs | 14 +++++++------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/quantinuum-hugr/src/extension.rs b/quantinuum-hugr/src/extension.rs index 75915f722..d16a11b8b 100644 --- a/quantinuum-hugr/src/extension.rs +++ b/quantinuum-hugr/src/extension.rs @@ -142,6 +142,9 @@ pub enum SignatureError { /// Invalid type arguments #[error("Invalid type arguments for operation")] InvalidTypeArgs, + /// Signature contains row variables i.e. is of unknown length + #[error("Signature contains variable {idx} which is a row of unknown length of {bound} types")] + ContainsRowVars { idx: usize, bound: TypeBound }, /// The Extension Registry did not contain an Extension referenced by the Signature #[error("Extension '{0}' not found")] ExtensionNotFound(ExtensionId), diff --git a/quantinuum-hugr/src/extension/op_def.rs b/quantinuum-hugr/src/extension/op_def.rs index 4eefeb61f..eeaec5a96 100644 --- a/quantinuum-hugr/src/extension/op_def.rs +++ b/quantinuum-hugr/src/extension/op_def.rs @@ -12,7 +12,7 @@ use super::{ }; use crate::types::type_param::{check_type_args, TypeArg, TypeParam}; -use crate::types::{FunctionType, PolyFuncType}; +use crate::types::{FunctionType, PolyFuncType, Signature}; use crate::Hugr; /// Trait necessary for binary computations of OpDef signature @@ -194,6 +194,7 @@ impl From for SignatureFunc { } impl From for SignatureFunc { + // ALAN might want to be Signature? fn from(v: FunctionType) -> Self { Self::TypeScheme(CustomValidator::from_polyfunc(v)) } @@ -213,7 +214,7 @@ impl SignatureFunc { } } - /// Compute the concrete signature ([FunctionType]). + /// Compute the concrete [Signature] for a node /// /// # Panics /// @@ -229,7 +230,7 @@ impl SignatureFunc { def: &OpDef, args: &[TypeArg], exts: &ExtensionRegistry, - ) -> Result { + ) -> Result { let temp: PolyFuncType; let (pf, args) = match &self { SignatureFunc::TypeScheme(custom) => { @@ -250,7 +251,8 @@ impl SignatureFunc { // TODO bring this assert back once resource inference is done? // https://github.com/CQCL/hugr/issues/388 // debug_assert!(res.extension_reqs.contains(def.extension())); - Ok(res) + res.try_into() + .map_err(|(idx, bound)| SignatureError::ContainsRowVars { idx, bound }) } } @@ -350,7 +352,7 @@ impl OpDef { &self, args: &[TypeArg], exts: &ExtensionRegistry, - ) -> Result { + ) -> Result { self.signature_func.compute_signature(self, args, exts) } @@ -480,7 +482,9 @@ mod test { use crate::ops::LeafOp; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; use crate::types::Type; - use crate::types::{type_param::TypeParam, FunctionType, PolyFuncType, TypeArg, TypeBound}; + use crate::types::{ + type_param::TypeParam, FunctionType, PolyFuncType, Signature, TypeArg, TypeBound, + }; use crate::Hugr; use crate::{const_extension_ids, Extension}; @@ -563,7 +567,7 @@ mod test { let args = [TypeArg::BoundedNat { n: 3 }, USIZE_T.into()]; assert_eq!( def.compute_signature(&args, &PRELUDE_REGISTRY), - Ok(FunctionType::new( + Ok(Signature::new( vec![USIZE_T; 3], vec![Type::new_tuple(vec![USIZE_T; 3])] )) @@ -576,7 +580,7 @@ mod test { let args = [TypeArg::BoundedNat { n: 3 }, tyvar.clone().into()]; assert_eq!( def.compute_signature(&args, &PRELUDE_REGISTRY), - Ok(FunctionType::new( + Ok(Signature::new( tyvars.clone(), vec![Type::new_tuple(tyvars)] )) @@ -632,7 +636,7 @@ mod test { def.validate_args(&args, &EMPTY_REG, &decls).unwrap(); assert_eq!( def.compute_signature(&args, &EMPTY_REG), - Ok(FunctionType::new_endo(vec![tv])) + Ok(Signature::new_endo(vec![tv])) ); Ok(()) } diff --git a/quantinuum-hugr/src/ops/custom.rs b/quantinuum-hugr/src/ops/custom.rs index 3e36eeecb..aa11e41cb 100644 --- a/quantinuum-hugr/src/ops/custom.rs +++ b/quantinuum-hugr/src/ops/custom.rs @@ -7,7 +7,7 @@ use thiserror::Error; use crate::extension::{ConstFoldResult, ExtensionId, ExtensionRegistry, OpDef, SignatureError}; use crate::hugr::hugrmut::sealed::HugrMutInternals; use crate::hugr::{HugrView, NodeType}; -use crate::types::{type_param::TypeArg, FunctionType}; +use crate::types::{type_param::TypeArg, Signature}; use crate::{ops, Hugr, IncomingPort, Node}; use super::dataflow::DataflowOpTrait; @@ -109,7 +109,7 @@ impl DataflowOpTrait for ExternalOp { pub struct ExtensionOp { def: Arc, args: Vec, - signature: FunctionType, // Cache + signature: Signature, // Cache } impl ExtensionOp { @@ -201,7 +201,7 @@ pub struct OpaqueOp { op_name: SmolStr, description: String, // cache in advance so description() can return &str args: Vec, - signature: FunctionType, + signature: Signature, } fn qualify_name(res_id: &ExtensionId, op_name: &SmolStr) -> SmolStr { @@ -215,7 +215,7 @@ impl OpaqueOp { op_name: impl Into, description: String, args: impl Into>, - signature: FunctionType, + signature: Signature, ) -> Self { Self { extension, @@ -346,8 +346,8 @@ pub enum CustomOpError { SignatureMismatch { extension: ExtensionId, op: SmolStr, - stored: FunctionType, - computed: FunctionType, + stored: Signature, + computed: Signature, }, } @@ -360,7 +360,7 @@ mod test { #[test] fn new_opaque_op() { - let sig = FunctionType::new_endo(vec![QB_T]); + let sig = Signature::new_endo(vec![QB_T]); let op = OpaqueOp::new( "res".try_into().unwrap(), "op", From c4ce0e8aa3c61351c7254b84dc662032f905326d Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 17:36:43 +0000 Subject: [PATCH 30/57] check.rs: fix SumType using TryInto --- quantinuum-hugr/src/types/check.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/quantinuum-hugr/src/types/check.rs b/quantinuum-hugr/src/types/check.rs index d2da2a372..4a45dfb0a 100644 --- a/quantinuum-hugr/src/types/check.rs +++ b/quantinuum-hugr/src/types/check.rs @@ -2,7 +2,7 @@ use thiserror::Error; -use super::Type; +use super::{Type, TypeBound, TypeRow}; use crate::ops::Const; /// Errors that arise from typechecking constants @@ -31,6 +31,15 @@ pub enum SumTypeError { /// The length of the sum variant found. found: usize, }, + #[error("Sum variant #{tag} contained row variable with index {idx} standing for a row of {bound} types")] + ContainsRowVariables { + /// The tag of the sum (and value) + tag: usize, + /// (DeBruijn) index of the row variable + idx: usize, + /// Bound on types which can be substituted for the variable + bound: TypeBound, + }, /// Tag for a sum value exceeded the number of variants. #[error("Invalid tag {tag} for sum type with {num_variants} variants")] InvalidTag { @@ -60,6 +69,7 @@ impl super::SumType { num_variants: self.num_variants(), })?; + // TODO how is it possible to call len() here? if variant.len() != val.len() { Err(SumTypeError::WrongVariantLength { tag, @@ -68,6 +78,11 @@ impl super::SumType { })?; } + let variant: TypeRow = variant + .clone() + .try_into() + .map_err(|(idx, bound)| SumTypeError::ContainsRowVariables { tag, idx, bound })?; + for (index, (t, v)) in itertools::zip_eq(variant.iter(), val.iter()).enumerate() { if v.const_type() != *t { Err(SumTypeError::InvalidValueType { From 6e1059a5f725285c3548fab63a1b4e1fe48ce6ba Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 17:53:20 +0000 Subject: [PATCH 31/57] views.rs FunctionType -> Signature --- quantinuum-hugr/src/hugr/views.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/quantinuum-hugr/src/hugr/views.rs b/quantinuum-hugr/src/hugr/views.rs index 649ae522e..7bcc80abd 100644 --- a/quantinuum-hugr/src/hugr/views.rs +++ b/quantinuum-hugr/src/hugr/views.rs @@ -28,7 +28,7 @@ use super::{Hugr, HugrError, NodeMetadata, NodeMetadataMap, NodeType, DEFAULT_NO use crate::ops::handle::NodeHandle; use crate::ops::{OpParent, OpTag, OpTrait, OpType}; -use crate::types::{EdgeKind, FunctionType}; +use crate::types::{EdgeKind, Signature}; use crate::types::{PolyFuncType, Type}; use crate::{Direction, IncomingPort, Node, OutgoingPort, Port}; @@ -335,8 +335,8 @@ pub trait HugrView: sealed::HugrInternals { /// 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 { + /// method always return a concrete [`Signature`]. + fn get_df_function_type(&self) -> Option { let op = self.get_optype(self.root()); op.inner_function_type() } @@ -435,7 +435,7 @@ pub trait HugrView: sealed::HugrInternals { /// Get the "signature" (incoming and outgoing types) of a node, non-Value /// kind ports will be missing. - fn signature(&self, node: Node) -> Option { + fn signature(&self, node: Node) -> Option { self.get_optype(node).dataflow_signature() } From b06b1f2bc4ecc3ede356fcb93c86fc276b2bca3a Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 17:35:31 +0000 Subject: [PATCH 32/57] FunctionType -> Signature in builder (adding fix_sig) --- quantinuum-hugr/src/builder/build_traits.rs | 16 ++++--- quantinuum-hugr/src/builder/cfg.rs | 27 ++++++------ quantinuum-hugr/src/builder/circuit.rs | 3 +- quantinuum-hugr/src/builder/conditional.rs | 8 ++-- quantinuum-hugr/src/builder/dataflow.rs | 47 +++++++++++---------- quantinuum-hugr/src/builder/module.rs | 4 +- quantinuum-hugr/src/builder/tail_loop.rs | 6 +-- 7 files changed, 59 insertions(+), 52 deletions(-) diff --git a/quantinuum-hugr/src/builder/build_traits.rs b/quantinuum-hugr/src/builder/build_traits.rs index 7b510df68..879dee5bd 100644 --- a/quantinuum-hugr/src/builder/build_traits.rs +++ b/quantinuum-hugr/src/builder/build_traits.rs @@ -19,8 +19,8 @@ use crate::{ types::EdgeKind, }; -use crate::extension::{ExtensionRegistry, ExtensionSet, PRELUDE_REGISTRY}; -use crate::types::{FunctionType, PolyFuncType, Type, TypeArg, TypeRow}; +use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError, PRELUDE_REGISTRY}; +use crate::types::{FunctionType, PolyFuncType, Signature, Type, TypeArg, TypeRow}; use itertools::Itertools; @@ -87,7 +87,7 @@ pub trait Container { name: impl Into, signature: PolyFuncType, ) -> Result, BuildError> { - let body = signature.body().clone(); + let body = fix_sig(signature.body().clone())?; let f_node = self.add_child_node(NodeType::new_pure(ops::FuncDefn { name: name.into(), signature, @@ -296,7 +296,7 @@ pub trait Dataflow: Container { // TODO: Should this be one function, or should there be a temporary "op" one like with the others? fn dfg_builder( &mut self, - signature: FunctionType, + signature: Signature, input_extensions: Option, input_wires: impl IntoIterator, ) -> Result, BuildError> { @@ -334,7 +334,7 @@ pub trait Dataflow: Container { self, NodeType::new( ops::CFG { - signature: FunctionType::new(inputs.clone(), output_types.clone()) + signature: Signature::new(inputs.clone(), output_types.clone()) .with_extension_delta(extension_delta), }, input_extensions.into(), @@ -715,6 +715,12 @@ fn wire_up( )) } +pub(super) fn fix_sig(fnty: FunctionType) -> Result { + fnty.try_into().map_err(|(idx, bound)| { + BuildError::SignatureError(SignatureError::ContainsRowVars { idx, bound }) + }) +} + /// Trait implemented by builders of Dataflow Hugrs pub trait DataflowHugr: HugrBuilder + Dataflow { /// Set outputs of dataflow HUGR and return validated HUGR diff --git a/quantinuum-hugr/src/builder/cfg.rs b/quantinuum-hugr/src/builder/cfg.rs index cd2923b12..c815fcbe8 100644 --- a/quantinuum-hugr/src/builder/cfg.rs +++ b/quantinuum-hugr/src/builder/cfg.rs @@ -5,11 +5,9 @@ use super::{ BasicBlockID, BuildError, CfgID, Container, Dataflow, HugrBuilder, Wire, }; +use crate::extension::{ExtensionRegistry, ExtensionSet}; use crate::ops::{self, handle::NodeHandle, DataflowBlock, DataflowParent, ExitBlock, OpType}; -use crate::{ - extension::{ExtensionRegistry, ExtensionSet}, - types::FunctionType, -}; +use crate::types::Signature; use crate::{hugr::views::HugrView, types::TypeRow}; use crate::Node; @@ -155,7 +153,7 @@ impl + AsRef> SubContainer for CFGBuilder { impl CFGBuilder { /// New CFG rooted HUGR builder - pub fn new(signature: FunctionType) -> Result { + pub fn new(signature: Signature) -> Result { let cfg_op = ops::CFG { signature: signature.clone(), }; @@ -253,7 +251,7 @@ impl + AsRef> CFGBuilder { /// This function will return an error if there is an error adding the node. pub fn simple_block_builder( &mut self, - signature: FunctionType, + signature: Signature, n_cases: usize, ) -> Result, BuildError> { self.block_builder( @@ -405,6 +403,7 @@ pub(crate) mod test { use crate::hugr::validate::InterGraphEdgeError; use crate::hugr::ValidationError; + use crate::types::FunctionType; use crate::{builder::test::NAT, type_row}; use cool_asserts::assert_matches; @@ -441,7 +440,7 @@ pub(crate) mod test { } #[test] fn basic_cfg_hugr() -> Result<(), BuildError> { - let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; build_basic_cfg(&mut cfg_builder)?; assert_matches!(cfg_builder.finish_prelude_hugr(), Ok(_)); @@ -460,8 +459,8 @@ pub(crate) mod test { let sum = entry_b.make_sum(1, sum2_variants, [inw])?; entry_b.finish_with_outputs(sum, [])? }; - let mut middle_b = cfg_builder - .simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?; + let mut middle_b = + cfg_builder.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?; let middle = { let c = middle_b.add_load_const(ops::Const::unary_unit_sum()); let [inw] = middle_b.input_wires_arr(); @@ -475,7 +474,7 @@ pub(crate) mod test { } #[test] fn test_dom_edge() -> Result<(), BuildError> { - let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; let sum_tuple_const = cfg_builder.add_constant(ops::Const::unary_unit_sum()); let sum_variants = vec![type_row![]]; @@ -488,7 +487,7 @@ pub(crate) mod test { entry_b.finish_with_outputs(sum, [])? }; let mut middle_b = - cfg_builder.simple_block_builder(FunctionType::new(type_row![], type_row![NAT]), 1)?; + cfg_builder.simple_block_builder(Signature::new(type_row![], type_row![NAT]), 1)?; let middle = { let c = middle_b.load_const(&sum_tuple_const); middle_b.finish_with_outputs(c, [inw])? @@ -503,11 +502,11 @@ pub(crate) mod test { #[test] fn test_non_dom_edge() -> Result<(), BuildError> { - let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; let sum_tuple_const = cfg_builder.add_constant(ops::Const::unary_unit_sum()); let sum_variants = vec![type_row![]]; - let mut middle_b = cfg_builder - .simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?; + let mut middle_b = + cfg_builder.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?; let [inw] = middle_b.input_wires_arr(); let middle = { let c = middle_b.load_const(&sum_tuple_const); diff --git a/quantinuum-hugr/src/builder/circuit.rs b/quantinuum-hugr/src/builder/circuit.rs index 89d6b45a6..f8957e3a5 100644 --- a/quantinuum-hugr/src/builder/circuit.rs +++ b/quantinuum-hugr/src/builder/circuit.rs @@ -237,6 +237,7 @@ mod test { use super::*; use cool_asserts::assert_matches; + use crate::types::Signature; use crate::utils::test_quantum_extension::{cx_gate, h_gate, measure, q_alloc, q_discard}; use crate::{ builder::{ @@ -284,7 +285,7 @@ mod test { "MyOp", "unknown op".to_string(), vec![], - FunctionType::new(vec![QB, NAT], vec![QB]), + Signature::new(vec![QB, NAT], vec![QB]), )) .into(), ); diff --git a/quantinuum-hugr/src/builder/conditional.rs b/quantinuum-hugr/src/builder/conditional.rs index 3c27a8c86..f825ad445 100644 --- a/quantinuum-hugr/src/builder/conditional.rs +++ b/quantinuum-hugr/src/builder/conditional.rs @@ -1,7 +1,7 @@ use crate::extension::ExtensionRegistry; use crate::hugr::views::HugrView; use crate::ops::dataflow::DataflowOpTrait; -use crate::types::{FunctionType, TypeRow}; +use crate::types::{FunctionType, Signature, TypeRow}; use crate::ops; use crate::ops::handle::CaseID; @@ -121,7 +121,7 @@ impl + AsRef> ConditionalBuilder { let outputs = cond.outputs; let case_op = ops::Case { - signature: FunctionType::new(inputs.clone(), outputs.clone()) + signature: Signature::new(inputs.clone(), outputs.clone()) .with_extension_delta(extension_delta.clone()), }; let case_node = @@ -137,7 +137,7 @@ impl + AsRef> ConditionalBuilder { let dfg_builder = DFGBuilder::create_with_io( self.hugr_mut(), case_node, - FunctionType::new(inputs, outputs).with_extension_delta(extension_delta), + Signature::new(inputs, outputs).with_extension_delta(extension_delta), None, )?; @@ -191,7 +191,7 @@ impl ConditionalBuilder { impl CaseBuilder { /// Initialize a Case rooted HUGR - pub fn new(signature: FunctionType) -> Result { + pub fn new(signature: Signature) -> Result { let op = ops::Case { signature: signature.clone(), }; diff --git a/quantinuum-hugr/src/builder/dataflow.rs b/quantinuum-hugr/src/builder/dataflow.rs index cebdbd242..091d9775a 100644 --- a/quantinuum-hugr/src/builder/dataflow.rs +++ b/quantinuum-hugr/src/builder/dataflow.rs @@ -1,4 +1,4 @@ -use super::build_traits::{HugrBuilder, SubContainer}; +use super::build_traits::{fix_sig, HugrBuilder, SubContainer}; use super::handle::BuildHandle; use super::{BuildError, Container, Dataflow, DfgID, FuncID}; @@ -7,7 +7,7 @@ use std::marker::PhantomData; use crate::hugr::{HugrView, NodeType, ValidationError}; use crate::ops; -use crate::types::{FunctionType, PolyFuncType}; +use crate::types::{PolyFuncType, Signature}; use crate::extension::{ExtensionRegistry, ExtensionSet}; use crate::Node; @@ -26,11 +26,16 @@ impl + AsRef> DFGBuilder { pub(super) fn create_with_io( mut base: T, parent: Node, - signature: FunctionType, + signature: Signature, input_extensions: Option, ) -> Result { - let num_in_wires = signature.input().len(); - let num_out_wires = signature.output().len(); + let Signature { + input, + output, + extension_reqs, + } = signature; + let num_in_wires = input.len(); + let num_out_wires = output.len(); /* For a given dataflow graph with extension requirements IR -> IR + dR, - The output node's extension requirements are IR + dR -> IR + dR (but we expect no output wires) @@ -43,12 +48,8 @@ impl + AsRef> DFGBuilder { from the input wires as we normally expect, but have to infer the output wires and make use of the equality between the two. */ - let input = ops::Input { - types: signature.input().clone(), - }; - let output = ops::Output { - types: signature.output().clone(), - }; + let input = ops::Input { types: input }; + let output = ops::Output { types: output }; base.as_mut() .add_node_with_parent(parent, NodeType::new(input, input_extensions.clone())); base.as_mut().add_node_with_parent( @@ -75,7 +76,7 @@ impl DFGBuilder { /// # Errors /// /// Error in adding DFG child nodes. - pub fn new(signature: FunctionType) -> Result, BuildError> { + pub fn new(signature: Signature) -> Result, BuildError> { let dfg_op = ops::DFG { signature: signature.clone(), }; @@ -147,7 +148,7 @@ impl FunctionBuilder { /// /// Error in adding DFG child nodes. pub fn new(name: impl Into, signature: PolyFuncType) -> Result { - let body = signature.body().clone(); + let body = fix_sig(signature.body().clone())?; let op = ops::FuncDefn { signature, name: name.into(), @@ -214,7 +215,7 @@ pub(crate) mod test { use crate::ops::{handle::NodeHandle, LeafOp, OpTag}; use crate::std_extensions::logic::test::and_op; - use crate::types::Type; + use crate::types::{FunctionType, Type}; use crate::utils::test_quantum_extension::h_gate; use crate::{ builder::{ @@ -243,7 +244,7 @@ pub(crate) mod test { let q_out = func_builder.add_dataflow_op(h_gate(), vec![qb])?; let inner_builder = func_builder.dfg_builder( - FunctionType::new(type_row![NAT], type_row![NAT]), + Signature::new(type_row![NAT], type_row![NAT]), None, [int], )?; @@ -351,7 +352,7 @@ pub(crate) mod test { let i1 = noop.out_wire(0); let mut nested = - f_build.dfg_builder(FunctionType::new(type_row![], type_row![BIT]), None, [])?; + f_build.dfg_builder(Signature::new(type_row![], type_row![BIT]), None, [])?; let id = nested.add_dataflow_op(LeafOp::Noop { ty: BIT }, [i1])?; @@ -375,7 +376,7 @@ pub(crate) mod test { let i1 = noop.out_wire(0); let mut nested = - f_build.dfg_builder(FunctionType::new(type_row![], type_row![QB]), None, [])?; + f_build.dfg_builder(Signature::new(type_row![], type_row![QB]), None, [])?; let id_res = nested.add_dataflow_op(LeafOp::Noop { ty: QB }, [i1]); @@ -401,7 +402,7 @@ pub(crate) mod test { #[test] fn insert_hugr() -> Result<(), BuildError> { // Create a simple DFG - let mut dfg_builder = DFGBuilder::new(FunctionType::new(type_row![BIT], type_row![BIT]))?; + let mut dfg_builder = DFGBuilder::new(Signature::new(type_row![BIT], type_row![BIT]))?; let [i1] = dfg_builder.input_wires_arr(); dfg_builder.set_metadata("x", 42); let dfg_hugr = dfg_builder.finish_hugr_with_outputs([i1], &EMPTY_REG)?; @@ -441,15 +442,15 @@ pub(crate) mod test { let abc_extensions = ab_extensions.clone().union(xc.clone().into()); let parent_sig = - FunctionType::new(type_row![BIT], type_row![BIT]).with_extension_delta(abc_extensions); + Signature::new(type_row![BIT], type_row![BIT]).with_extension_delta(abc_extensions); let mut parent = DFGBuilder::new(parent_sig)?; let add_c_sig = - FunctionType::new(type_row![BIT], type_row![BIT]).with_extension_delta(xc.clone()); + Signature::new(type_row![BIT], type_row![BIT]).with_extension_delta(xc.clone()); let [w] = parent.input_wires_arr(); - let add_ab_sig = FunctionType::new(type_row![BIT], type_row![BIT]) + let add_ab_sig = Signature::new(type_row![BIT], type_row![BIT]) .with_extension_delta(ab_extensions.clone()); // A box which adds extensions A and B, via child Lift nodes @@ -505,7 +506,7 @@ pub(crate) mod test { #[test] fn non_cfg_ancestor() -> Result<(), BuildError> { - let unit_sig = FunctionType::new(type_row![Type::UNIT], type_row![Type::UNIT]); + let unit_sig = Signature::new(type_row![Type::UNIT], type_row![Type::UNIT]); let mut b = DFGBuilder::new(unit_sig.clone())?; let b_child = b.dfg_builder(unit_sig.clone(), None, [b.input().out_wire(0)])?; let b_child_in_wire = b_child.input().out_wire(0); @@ -529,7 +530,7 @@ pub(crate) mod test { #[test] fn no_relation_edge() -> Result<(), BuildError> { - let unit_sig = FunctionType::new(type_row![Type::UNIT], type_row![Type::UNIT]); + let unit_sig = Signature::new(type_row![Type::UNIT], type_row![Type::UNIT]); let mut b = DFGBuilder::new(unit_sig.clone())?; let mut b_child = b.dfg_builder(unit_sig.clone(), None, [b.input().out_wire(0)])?; let b_child_child = diff --git a/quantinuum-hugr/src/builder/module.rs b/quantinuum-hugr/src/builder/module.rs index f6b4b7f20..61e5c91d6 100644 --- a/quantinuum-hugr/src/builder/module.rs +++ b/quantinuum-hugr/src/builder/module.rs @@ -1,5 +1,5 @@ use super::{ - build_traits::HugrBuilder, + build_traits::{fix_sig, HugrBuilder}, dataflow::{DFGBuilder, FunctionBuilder}, BuildError, Container, }; @@ -84,7 +84,7 @@ impl + AsRef> ModuleBuilder { op_desc: "crate::ops::OpType::FuncDecl", })? .clone(); - let body = signature.body().clone(); + let body = fix_sig(signature.body().clone())?; self.hugr_mut() .replace_op( f_node, diff --git a/quantinuum-hugr/src/builder/tail_loop.rs b/quantinuum-hugr/src/builder/tail_loop.rs index 3d3022253..485082f04 100644 --- a/quantinuum-hugr/src/builder/tail_loop.rs +++ b/quantinuum-hugr/src/builder/tail_loop.rs @@ -1,7 +1,7 @@ use crate::ops; use crate::hugr::{views::HugrView, NodeType}; -use crate::types::{FunctionType, TypeRow}; +use crate::types::{Signature, TypeRow}; use crate::{Hugr, Node}; use super::build_traits::SubContainer; @@ -20,7 +20,7 @@ impl + AsRef> TailLoopBuilder { loop_node: Node, tail_loop: &ops::TailLoop, ) -> Result { - let signature = FunctionType::new(tail_loop.body_input_row(), tail_loop.body_output_row()); + let signature = Signature::new(tail_loop.body_input_row(), tail_loop.body_output_row()); let dfg_build = DFGBuilder::create_with_io(base, loop_node, signature, None)?; Ok(TailLoopBuilder::from_dfg_builder(dfg_build)) @@ -126,7 +126,7 @@ mod test { let mut module_builder = ModuleBuilder::new(); let mut fbuild = module_builder.define_function( "main", - FunctionType::new(type_row![BIT], type_row![NAT]) + Signature::new(type_row![BIT], type_row![NAT]) .with_extension_delta(PRELUDE_ID) .into(), )?; From 28cbbbc7c0bd262b815fd86fa7dc102a5798ed76 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 26 Mar 2024 18:59:18 +0000 Subject: [PATCH 33/57] Many more FunctionType->Signatures --- quantinuum-hugr/src/algorithm/const_fold.rs | 25 ++++------ quantinuum-hugr/src/algorithm/nest_cfgs.rs | 22 ++++---- quantinuum-hugr/src/builder.rs | 9 ++-- quantinuum-hugr/src/extension/infer/test.rs | 50 +++++++++---------- quantinuum-hugr/src/extension/op_def.rs | 2 +- quantinuum-hugr/src/extension/prelude.rs | 6 +-- quantinuum-hugr/src/hugr/views/descendants.rs | 4 +- .../src/hugr/views/root_checked.rs | 5 +- quantinuum-hugr/src/hugr/views/sibling.rs | 4 +- .../src/hugr/views/sibling_subgraph.rs | 15 +++--- quantinuum-hugr/src/hugr/views/tests.rs | 15 +++--- quantinuum-hugr/src/ops/constant.rs | 5 +- quantinuum-hugr/src/ops/leaf.rs | 28 +++++------ 13 files changed, 88 insertions(+), 102 deletions(-) diff --git a/quantinuum-hugr/src/algorithm/const_fold.rs b/quantinuum-hugr/src/algorithm/const_fold.rs index 6fcec022d..d14393815 100644 --- a/quantinuum-hugr/src/algorithm/const_fold.rs +++ b/quantinuum-hugr/src/algorithm/const_fold.rs @@ -4,7 +4,7 @@ use std::collections::{BTreeSet, HashMap}; use itertools::Itertools; -use crate::types::SumType; +use crate::types::{Signature, SumType}; use crate::{ builder::{DFGBuilder, Dataflow, DataflowHugr}, extension::{ConstFoldResult, ExtensionRegistry}, @@ -14,9 +14,7 @@ use crate::{ HugrMut, }, ops::{Const, LeafOp}, - type_row, - types::FunctionType, - Hugr, HugrView, IncomingPort, Node, SimpleReplacement, + type_row, Hugr, HugrView, IncomingPort, Node, SimpleReplacement, }; /// Tag some output constants with [`OutgoingPort`] inferred from the ordering. @@ -77,7 +75,7 @@ pub fn fold_leaf_op(op: &LeafOp, consts: &[(IncomingPort, Const)]) -> ConstFoldR /// against `reg`. fn const_graph(consts: Vec, reg: &ExtensionRegistry) -> Hugr { let const_types = consts.iter().map(Const::const_type).collect_vec(); - let mut b = DFGBuilder::new(FunctionType::new(type_row![], const_types)).unwrap(); + let mut b = DFGBuilder::new(Signature::new(type_row![], const_types)).unwrap(); let outputs = consts .into_iter() @@ -221,6 +219,7 @@ mod test { use crate::std_extensions::arithmetic::float_types::{ConstF64, FLOAT64_TYPE}; use crate::std_extensions::arithmetic::int_types::{ConstIntU, INT_TYPES}; use crate::std_extensions::logic::{self, NaryLogic}; + use crate::types::Signature; use rstest::rstest; @@ -254,11 +253,8 @@ mod test { int(x.0 - x.1) == 2 */ let sum_type = sum_with_error(INT_TYPES[5].to_owned()); - let mut build = DFGBuilder::new(FunctionType::new( - type_row![], - vec![sum_type.clone().into()], - )) - .unwrap(); + let mut build = + DFGBuilder::new(Signature::new(type_row![], vec![sum_type.clone().into()])).unwrap(); let tup = build.add_load_const(Const::tuple([f2c(5.6), f2c(3.2)])); @@ -307,7 +303,7 @@ mod test { #[case] ins: [bool; 3], #[case] out: bool, ) -> Result<(), Box> { - let mut build = DFGBuilder::new(FunctionType::new(type_row![], vec![BOOL_T])).unwrap(); + let mut build = DFGBuilder::new(Signature::new(type_row![], vec![BOOL_T])).unwrap(); let ins = ins.map(|b| build.add_load_const(Const::from_bool(b))); let logic_op = build.add_dataflow_op(op.with_n_inputs(ins.len() as u64), ins)?; @@ -336,11 +332,8 @@ mod test { ]) .unwrap(); let list: Const = ListValue::new(BOOL_T, [Const::unit_sum(0, 1).unwrap()]).into(); - let mut build = DFGBuilder::new(FunctionType::new( - type_row![], - vec![list.const_type().clone()], - )) - .unwrap(); + let mut build = + DFGBuilder::new(Signature::new(type_row![], vec![list.const_type().clone()])).unwrap(); let list_wire = build.add_load_const(list.clone()); diff --git a/quantinuum-hugr/src/algorithm/nest_cfgs.rs b/quantinuum-hugr/src/algorithm/nest_cfgs.rs index 174af2b3d..385d67b45 100644 --- a/quantinuum-hugr/src/algorithm/nest_cfgs.rs +++ b/quantinuum-hugr/src/algorithm/nest_cfgs.rs @@ -580,7 +580,7 @@ pub(crate) mod test { use crate::hugr::views::RootChecked; use crate::ops::handle::{BasicBlockID, ConstID, NodeHandle}; use crate::ops::Const; - use crate::types::{FunctionType, Type}; + use crate::types::{Signature, Type}; use crate::{type_row, Hugr}; const NAT: Type = USIZE_T; @@ -603,7 +603,7 @@ pub(crate) mod test { // /-> left --\ // entry -> split > merge -> head -> tail -> exit // \-> right -/ \-<--<-/ - let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; let pred_const = cfg_builder.add_constant(Const::unit_sum(0, 2).expect("0 < 2")); let const_unit = cfg_builder.add_constant(Const::unary_unit_sum()); @@ -823,7 +823,7 @@ pub(crate) mod test { unit_const: &ConstID, ) -> Result<(BasicBlockID, BasicBlockID), BuildError> { let split = n_identity( - cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 2)?, + cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 2)?, const_pred, )?; let merge = build_then_else_merge_from_if(cfg, unit_const, split)?; @@ -836,15 +836,15 @@ pub(crate) mod test { split: BasicBlockID, ) -> Result { let merge = n_identity( - cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, + cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, unit_const, )?; let left = n_identity( - cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, + cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, unit_const, )?; let right = n_identity( - cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, + cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, unit_const, )?; cfg.branch(&split, 0, &left)?; @@ -861,7 +861,7 @@ pub(crate) mod test { header: BasicBlockID, ) -> Result { let tail = n_identity( - cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 2)?, + cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 2)?, const_pred, )?; cfg.branch(&tail, 1, &header)?; @@ -875,7 +875,7 @@ pub(crate) mod test { unit_const: &ConstID, ) -> Result<(BasicBlockID, BasicBlockID), BuildError> { let header = n_identity( - cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, + cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, unit_const, )?; let tail = build_loop_from_header(cfg, const_pred, header)?; @@ -886,7 +886,7 @@ pub(crate) mod test { pub fn build_cond_then_loop_cfg( separate: bool, ) -> Result<(Hugr, BasicBlockID, BasicBlockID), BuildError> { - let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; let pred_const = cfg_builder.add_constant(Const::unit_sum(0, 2).expect("0 < 2")); let const_unit = cfg_builder.add_constant(Const::unary_unit_sum()); @@ -898,7 +898,7 @@ pub(crate) mod test { let head = if separate { let h = n_identity( cfg_builder - .simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, + .simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, &const_unit, )?; cfg_builder.branch(&merge, 0, &h)?; @@ -919,7 +919,7 @@ pub(crate) mod test { pub(crate) fn build_conditional_in_loop_cfg( separate_headers: bool, ) -> Result<(Hugr, BasicBlockID, BasicBlockID), BuildError> { - let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; let (head, tail) = build_conditional_in_loop(&mut cfg_builder, separate_headers)?; let h = cfg_builder.finish_prelude_hugr()?; Ok((h, head, tail)) diff --git a/quantinuum-hugr/src/builder.rs b/quantinuum-hugr/src/builder.rs index bfd361282..3a563573e 100644 --- a/quantinuum-hugr/src/builder.rs +++ b/quantinuum-hugr/src/builder.rs @@ -223,7 +223,7 @@ pub(crate) mod test { use crate::hugr::{views::HugrView, HugrMut, NodeType}; use crate::ops; - use crate::types::{FunctionType, PolyFuncType, Type}; + use crate::types::{PolyFuncType, Signature, Type}; use crate::{type_row, Hugr}; use super::handle::BuildHandle; @@ -258,8 +258,7 @@ pub(crate) mod test { #[fixture] pub(crate) fn simple_dfg_hugr() -> Hugr { - let dfg_builder = - DFGBuilder::new(FunctionType::new(type_row![BIT], type_row![BIT])).unwrap(); + let dfg_builder = DFGBuilder::new(Signature::new(type_row![BIT], type_row![BIT])).unwrap(); let [i1] = dfg_builder.input_wires_arr(); dfg_builder.finish_prelude_hugr_with_outputs([i1]).unwrap() } @@ -267,7 +266,7 @@ pub(crate) mod test { #[fixture] pub(crate) fn simple_cfg_hugr() -> Hugr { let mut cfg_builder = - CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT])).unwrap(); + CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT])).unwrap(); super::cfg::test::build_basic_cfg(&mut cfg_builder).unwrap(); cfg_builder.finish_prelude_hugr().unwrap() } @@ -276,7 +275,7 @@ pub(crate) mod test { /// for tests which want to avoid having open extension variables after /// inference. Using DFGBuilder will default to a root node with an open /// extension variable - pub(crate) fn closed_dfg_root_hugr(signature: FunctionType) -> Hugr { + pub(crate) fn closed_dfg_root_hugr(signature: Signature) -> Hugr { let mut hugr = Hugr::new(NodeType::new_pure(ops::DFG { signature: signature.clone(), })); diff --git a/quantinuum-hugr/src/extension/infer/test.rs b/quantinuum-hugr/src/extension/infer/test.rs index 91aa7788b..3b0ca6e34 100644 --- a/quantinuum-hugr/src/extension/infer/test.rs +++ b/quantinuum-hugr/src/extension/infer/test.rs @@ -20,7 +20,7 @@ use crate::{ }; use crate::type_row; -use crate::types::{FunctionType, Type, TypeRow}; +use crate::types::{FunctionType, Signature, Type, TypeRow}; use cool_asserts::assert_matches; use itertools::Itertools; @@ -40,7 +40,7 @@ const_extension_ids! { // them. fn from_graph() -> Result<(), Box> { let rs = ExtensionSet::from_iter([A, B, C]); - let main_sig = FunctionType::new(type_row![NAT, NAT], type_row![NAT]).with_extension_delta(rs); + let main_sig = Signature::new(type_row![NAT, NAT], type_row![NAT]).with_extension_delta(rs); let op = ops::DFG { signature: main_sig, @@ -57,14 +57,14 @@ fn from_graph() -> Result<(), Box> { assert_matches!(hugr.get_io(hugr.root()), Some(_)); - let add_a_sig = FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(A); + let add_a_sig = Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(A); - let add_b_sig = FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(B); + let add_b_sig = Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(B); - let add_ab_sig = FunctionType::new(type_row![NAT], type_row![NAT]) + let add_ab_sig = Signature::new(type_row![NAT], type_row![NAT]) .with_extension_delta(ExtensionSet::from_iter([A, B])); - let mult_c_sig = FunctionType::new(type_row![NAT, NAT], type_row![NAT]).with_extension_delta(C); + let mult_c_sig = Signature::new(type_row![NAT, NAT], type_row![NAT]).with_extension_delta(C); let add_a = hugr.add_node_with_parent( hugr.root(), @@ -220,8 +220,7 @@ fn dangling_src() -> Result<(), Box> { ); let [input, output] = hugr.get_io(hugr.root()).unwrap(); - let add_r_sig = - FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(rs.clone()); + let add_r_sig = Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(rs.clone()); let add_r = hugr.add_node_with_parent( hugr.root(), @@ -231,11 +230,11 @@ fn dangling_src() -> Result<(), Box> { ); // Dangling thingy - let src_sig = FunctionType::new(type_row![], type_row![NAT]); + let src_sig = Signature::new(type_row![], type_row![NAT]); let src = hugr.add_node_with_parent(hugr.root(), ops::DFG { signature: src_sig }); - let mult_sig = FunctionType::new(type_row![NAT, NAT], type_row![NAT]); + let mult_sig = Signature::new(type_row![NAT, NAT], type_row![NAT]); // Mult has open extension requirements, which we should solve to be "R" let mult = hugr.add_node_with_parent( hugr.root(), @@ -281,7 +280,7 @@ fn create_with_io( hugr: &mut Hugr, parent: Node, op: impl Into, - op_sig: FunctionType, + op_sig: Signature, ) -> Result<[Node; 3], Box> { let op: OpType = op.into(); @@ -354,7 +353,7 @@ fn test_conditional_inference() -> Result<(), Box> { let conditional_node = hugr.root(); let case_op = ops::Case { - signature: FunctionType::new(inputs, outputs).with_extension_delta(rs), + signature: Signature::new(inputs, outputs).with_extension_delta(rs), }; let case0_node = build_case(&mut hugr, conditional_node, case_op.clone(), A, B)?; @@ -377,7 +376,7 @@ fn test_conditional_inference() -> Result<(), Box> { #[test] fn extension_adding_sequence() -> Result<(), Box> { - let df_sig = FunctionType::new(type_row![NAT], type_row![NAT]); + let df_sig = Signature::new(type_row![NAT], type_row![NAT]); let mut hugr = Hugr::new(NodeType::new_open(ops::DFG { signature: df_sig @@ -438,7 +437,7 @@ fn extension_adding_sequence() -> Result<(), Box> { Ok(()) } -fn make_opaque(extension: impl Into, signature: FunctionType) -> ops::LeafOp { +fn make_opaque(extension: impl Into, signature: Signature) -> ops::LeafOp { let opaque = ops::custom::OpaqueOp::new(extension.into(), "", "".into(), vec![], signature); ops::custom::ExternalOp::from(opaque).into() } @@ -452,7 +451,7 @@ fn make_block( ) -> Result> { let sum_rows: Vec<_> = sum_rows.into_iter().collect(); let sum_type = Type::new_sum(sum_rows.clone()); - let dfb_sig = FunctionType::new(inputs.clone(), vec![sum_type]) + let dfb_sig = Signature::new(inputs.clone(), vec![sum_type]) .with_extension_delta(extension_delta.clone()); let dfb = ops::DataflowBlock { inputs, @@ -543,7 +542,7 @@ fn infer_cfg_test() -> Result<(), Box> { let bc = ExtensionSet::from_iter([B, C]); let mut hugr = Hugr::new(NodeType::new_open(ops::CFG { - signature: FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(abc), + signature: Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(abc), })); let root = hugr.root(); @@ -561,7 +560,7 @@ fn infer_cfg_test() -> Result<(), Box> { entry, make_opaque( A, - FunctionType::new(vec![NAT], twoway(NAT)).with_extension_delta(A), + Signature::new(vec![NAT], twoway(NAT)).with_extension_delta(A), ), ); @@ -641,7 +640,7 @@ fn infer_cfg_test() -> Result<(), Box> { #[test] fn multi_entry() -> Result<(), Box> { let mut hugr = Hugr::new(NodeType::new_open(ops::CFG { - signature: FunctionType::new(type_row![NAT], type_row![NAT]), // maybe add extensions? + signature: Signature::new(type_row![NAT], type_row![NAT]), // maybe add extensions? })); let cfg = hugr.root(); let ([entry, entry_in, entry_out], exit) = create_entry_exit( @@ -655,7 +654,7 @@ fn multi_entry() -> Result<(), Box> { let entry_mid = hugr.add_node_with_parent( entry, - make_opaque(UNKNOWN_EXTENSION, FunctionType::new(vec![NAT], twoway(NAT))), + make_opaque(UNKNOWN_EXTENSION, Signature::new(vec![NAT], twoway(NAT))), ); hugr.connect(entry_in, 0, entry_mid, 0); @@ -727,8 +726,7 @@ fn make_looping_cfg( .union(bb2_ext.clone()); let mut hugr = Hugr::new(NodeType::new_open(ops::CFG { - signature: FunctionType::new(type_row![NAT], type_row![NAT]) - .with_extension_delta(hugr_delta), + signature: Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(hugr_delta), })); let root = hugr.root(); @@ -746,7 +744,7 @@ fn make_looping_cfg( entry, make_opaque( UNKNOWN_EXTENSION, - FunctionType::new(vec![NAT], oneway(NAT)).with_extension_delta(entry_ext), + Signature::new(vec![NAT], oneway(NAT)).with_extension_delta(entry_ext), ), ); @@ -803,7 +801,7 @@ fn simple_cfg_loop() -> Result<(), Box> { let mut hugr = Hugr::new(NodeType::new( ops::CFG { - signature: FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(A), + signature: Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(A), }, Some(A.into()), )); @@ -821,7 +819,7 @@ fn simple_cfg_loop() -> Result<(), Box> { let entry_mid = hugr.add_node_with_parent( entry, - make_opaque(UNKNOWN_EXTENSION, FunctionType::new(vec![NAT], oneway(NAT))), + make_opaque(UNKNOWN_EXTENSION, Signature::new(vec![NAT], oneway(NAT))), ); hugr.connect(entry_in, 0, entry_mid, 0); @@ -849,7 +847,7 @@ fn simple_cfg_loop() -> Result<(), Box> { #[test] fn plus_on_self() -> Result<(), Box> { let ext = ExtensionId::new("unknown1").unwrap(); - let ft = FunctionType::new_endo(type_row![QB_T, QB_T]).with_extension_delta(ext.clone()); + let ft = Signature::new_endo(type_row![QB_T, QB_T]).with_extension_delta(ext.clone()); let mut dfg = DFGBuilder::new(ft.clone())?; // While https://github.com/CQCL/hugr/issues/388 is unsolved, @@ -863,7 +861,7 @@ fn plus_on_self() -> Result<(), Box> { ft, )) .into(); - let unary_sig = FunctionType::new_endo(type_row![QB_T]).with_extension_delta(ext.clone()); + let unary_sig = Signature::new_endo(type_row![QB_T]).with_extension_delta(ext.clone()); let unop: LeafOp = ExternalOp::Opaque(OpaqueOp::new( ext, "1qb_op", diff --git a/quantinuum-hugr/src/extension/op_def.rs b/quantinuum-hugr/src/extension/op_def.rs index eeaec5a96..4d0130a24 100644 --- a/quantinuum-hugr/src/extension/op_def.rs +++ b/quantinuum-hugr/src/extension/op_def.rs @@ -515,7 +515,7 @@ mod test { let list_usize = Type::new_extension(list_def.instantiate(vec![TypeArg::Type { ty: USIZE_T }])?); - let mut dfg = DFGBuilder::new(FunctionType::new_endo(vec![list_usize]))?; + let mut dfg = DFGBuilder::new(Signature::new_endo(vec![list_usize]))?; let rev = dfg.add_dataflow_op( LeafOp::from(ExternalOp::Extension( e.instantiate_extension_op(&OP_NAME, vec![TypeArg::Type { ty: USIZE_T }], ®) diff --git a/quantinuum-hugr/src/extension/prelude.rs b/quantinuum-hugr/src/extension/prelude.rs index cdccfdecd..025a94d9c 100644 --- a/quantinuum-hugr/src/extension/prelude.rs +++ b/quantinuum-hugr/src/extension/prelude.rs @@ -238,7 +238,7 @@ impl CustomConst for ConstError { mod test { use crate::{ builder::{DFGBuilder, Dataflow, DataflowHugr}, - types::FunctionType, + types::{FunctionType, Signature}, }; use super::*; @@ -246,7 +246,7 @@ mod test { #[test] /// Test building a HUGR involving a new_array operation. fn test_new_array() { - let mut b = DFGBuilder::new(FunctionType::new( + let mut b = DFGBuilder::new(Signature::new( vec![QB_T, QB_T], vec![array_type(TypeArg::BoundedNat { n: 2 }, QB_T)], )) @@ -286,7 +286,7 @@ mod test { assert!(error_val.equal_consts(&ConstError::new(2, "my message"))); assert!(!error_val.equal_consts(&ConstError::new(3, "my message"))); - let mut b = DFGBuilder::new(FunctionType::new_endo(type_row![])).unwrap(); + let mut b = DFGBuilder::new(Signature::new_endo(type_row![])).unwrap(); let err = b.add_load_const(error_val); diff --git a/quantinuum-hugr/src/hugr/views/descendants.rs b/quantinuum-hugr/src/hugr/views/descendants.rs index 453503509..8aa05138f 100644 --- a/quantinuum-hugr/src/hugr/views/descendants.rs +++ b/quantinuum-hugr/src/hugr/views/descendants.rs @@ -203,7 +203,7 @@ pub(super) mod test { builder::{Container, Dataflow, DataflowSubContainer, HugrBuilder, ModuleBuilder}, ops::handle::NodeHandle, type_row, - types::{FunctionType, Type}, + types::{FunctionType, Signature, Type}, utils::test_quantum_extension::h_gate, }; @@ -231,7 +231,7 @@ pub(super) mod test { let inner_id = { let inner_builder = func_builder.dfg_builder( - FunctionType::new(type_row![NAT], type_row![NAT]), + Signature::new(type_row![NAT], type_row![NAT]), None, [int], )?; diff --git a/quantinuum-hugr/src/hugr/views/root_checked.rs b/quantinuum-hugr/src/hugr/views/root_checked.rs index 39aa332a8..10832466b 100644 --- a/quantinuum-hugr/src/hugr/views/root_checked.rs +++ b/quantinuum-hugr/src/hugr/views/root_checked.rs @@ -75,12 +75,13 @@ mod test { use crate::hugr::{HugrError, HugrMut, NodeType}; use crate::ops::handle::{BasicBlockID, CfgID, DataflowParentID, DfgID}; use crate::ops::{DataflowBlock, LeafOp, OpTag}; - use crate::{ops, type_row, types::FunctionType, Hugr, HugrView}; + use crate::types::Signature; + use crate::{ops, type_row, Hugr, HugrView}; #[test] fn root_checked() { let root_type = NodeType::new_pure(ops::DFG { - signature: FunctionType::new(vec![], vec![]), + signature: Signature::new(vec![], vec![]), }); let mut h = Hugr::new(root_type.clone()); let cfg_v = RootChecked::<&Hugr, CfgID>::try_new(&h); diff --git a/quantinuum-hugr/src/hugr/views/sibling.rs b/quantinuum-hugr/src/hugr/views/sibling.rs index 7d69cc4b0..74bee860a 100644 --- a/quantinuum-hugr/src/hugr/views/sibling.rs +++ b/quantinuum-hugr/src/hugr/views/sibling.rs @@ -381,7 +381,7 @@ mod test { use crate::ops::handle::{CfgID, DataflowParentID, DfgID, FuncID}; use crate::ops::{dataflow::IOTrait, Input, OpTag, Output}; use crate::type_row; - use crate::types::{FunctionType, Type}; + use crate::types::{Signature, Type}; use super::super::descendants::test::make_module_hgr; use super::*; @@ -405,7 +405,7 @@ mod test { #[test] fn nested_flat() -> Result<(), Box> { let mut module_builder = ModuleBuilder::new(); - let fty = FunctionType::new(type_row![NAT], type_row![NAT]); + let fty = Signature::new(type_row![NAT], type_row![NAT]); let mut fbuild = module_builder.define_function("main", fty.clone().into())?; let dfg = fbuild.dfg_builder(fty, None, fbuild.input_wires())?; let ins = dfg.input_wires(); diff --git a/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs b/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs index 9741b08c7..a4c2f5484 100644 --- a/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs +++ b/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs @@ -22,7 +22,7 @@ use crate::hugr::{HugrMut, HugrView, RootTagged}; use crate::ops::dataflow::DataflowOpTrait; use crate::ops::handle::{ContainerHandle, DataflowOpID}; use crate::ops::{OpTag, OpTrait}; -use crate::types::{FunctionType, Type}; +use crate::types::{Signature, Type}; use crate::{Hugr, IncomingPort, Node, OutgoingPort, Port, SimpleReplacement}; /// A non-empty convex subgraph of a HUGR sibling graph. @@ -289,7 +289,7 @@ impl SiblingSubgraph { } /// The signature of the subgraph. - pub fn signature(&self, hugr: &impl HugrView) -> FunctionType { + pub fn signature(&self, hugr: &impl HugrView) -> Signature { let input = self .inputs .iter() @@ -307,7 +307,7 @@ impl SiblingSubgraph { sig.port_type(p).cloned().expect("must be dataflow edge") }) .collect_vec(); - FunctionType::new(input, output) + Signature::new(input, output) } /// The parent of the sibling subgraph. @@ -684,6 +684,7 @@ mod tests { use cool_asserts::assert_matches; use crate::extension::PRELUDE_REGISTRY; + use crate::types::FunctionType; use crate::utils::test_quantum_extension::cx_gate; use crate::{ builder::{ @@ -805,7 +806,7 @@ mod tests { let sub = SiblingSubgraph::try_new_dataflow_subgraph(&func)?; let empty_dfg = { - let builder = DFGBuilder::new(FunctionType::new_endo(type_row![QB_T, QB_T])).unwrap(); + let builder = DFGBuilder::new(Signature::new_endo(type_row![QB_T, QB_T])).unwrap(); let inputs = builder.input_wires(); builder.finish_prelude_hugr_with_outputs(inputs).unwrap() }; @@ -830,7 +831,7 @@ mod tests { // the first two qubits. assert_eq!( sub.signature(&func), - FunctionType::new_endo(type_row![QB_T, QB_T]) + Signature::new_endo(type_row![QB_T, QB_T]) ); Ok(()) } @@ -842,7 +843,7 @@ mod tests { let sub = SiblingSubgraph::from_sibling_graph(&func)?; let empty_dfg = { - let builder = DFGBuilder::new(FunctionType::new_endo(type_row![QB_T])).unwrap(); + let builder = DFGBuilder::new(Signature::new_endo(type_row![QB_T])).unwrap(); let inputs = builder.input_wires(); builder.finish_prelude_hugr_with_outputs(inputs).unwrap() }; @@ -981,7 +982,7 @@ mod tests { let two_bit = type_row![BOOL_T, BOOL_T]; let mut builder = - DFGBuilder::new(FunctionType::new(one_bit.clone(), two_bit.clone())).unwrap(); + DFGBuilder::new(Signature::new(one_bit.clone(), two_bit.clone())).unwrap(); let inw = builder.input_wires().exactly_one().unwrap(); let outw1 = builder.add_dataflow_op(NotOp, [inw]).unwrap().out_wire(0); let outw2 = builder diff --git a/quantinuum-hugr/src/hugr/views/tests.rs b/quantinuum-hugr/src/hugr/views/tests.rs index 678459578..47e4868e6 100644 --- a/quantinuum-hugr/src/hugr/views/tests.rs +++ b/quantinuum-hugr/src/hugr/views/tests.rs @@ -6,18 +6,15 @@ use crate::{ extension::prelude::QB_T, ops::handle::{DataflowOpID, NodeHandle}, type_row, - types::FunctionType, + types::{FunctionType, Signature}, utils::test_quantum_extension::cx_gate, Hugr, HugrView, }; #[fixture] fn sample_hugr() -> (Hugr, BuildHandle, BuildHandle) { - let mut dfg = DFGBuilder::new(FunctionType::new( - type_row![QB_T, QB_T], - type_row![QB_T, QB_T], - )) - .unwrap(); + let mut dfg = + DFGBuilder::new(Signature::new(type_row![QB_T, QB_T], type_row![QB_T, QB_T])).unwrap(); let [q1, q2] = dfg.input_wires_arr(); @@ -122,7 +119,7 @@ fn value_types() { use crate::utils::test_quantum_extension::h_gate; use itertools::Itertools; - let mut dfg = DFGBuilder::new(FunctionType::new( + let mut dfg = DFGBuilder::new(Signature::new( type_row![QB_T, BOOL_T], type_row![BOOL_T, QB_T], )) @@ -150,7 +147,7 @@ fn static_targets() { use crate::extension::prelude::{ConstUsize, PRELUDE_ID, USIZE_T}; use itertools::Itertools; let mut dfg = DFGBuilder::new( - FunctionType::new(type_row![], type_row![USIZE_T]).with_extension_delta(PRELUDE_ID), + Signature::new(type_row![], type_row![USIZE_T]).with_extension_delta(PRELUDE_ID), ) .unwrap(); @@ -176,7 +173,7 @@ fn test_dataflow_ports_only() { use crate::std_extensions::logic::NotOp; use itertools::Itertools; - let mut dfg = DFGBuilder::new(FunctionType::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap(); + let mut dfg = DFGBuilder::new(Signature::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap(); let local_and = { let local_and = dfg .define_function( diff --git a/quantinuum-hugr/src/ops/constant.rs b/quantinuum-hugr/src/ops/constant.rs index d18cff4dd..f59da31e3 100644 --- a/quantinuum-hugr/src/ops/constant.rs +++ b/quantinuum-hugr/src/ops/constant.rs @@ -285,6 +285,7 @@ where mod test { use super::Const; use crate::builder::test::simple_dfg_hugr; + use crate::types::Signature; use crate::{ builder::{BuildError, DFGBuilder, Dataflow, DataflowHugr}, extension::{ @@ -343,7 +344,7 @@ mod test { let pred_rows = vec![type_row![USIZE_T, FLOAT64_TYPE], Type::EMPTY_TYPEROW]; let pred_ty = SumType::new(pred_rows.clone()); - let mut b = DFGBuilder::new(FunctionType::new( + let mut b = DFGBuilder::new(Signature::new( type_row![], TypeRow::from(vec![pred_ty.clone().into()]), ))?; @@ -358,7 +359,7 @@ mod test { let w = b.load_const(&c); b.finish_hugr_with_outputs([w], &test_registry()).unwrap(); - let mut b = DFGBuilder::new(FunctionType::new( + let mut b = DFGBuilder::new(Signature::new( type_row![], TypeRow::from(vec![pred_ty.clone().into()]), ))?; diff --git a/quantinuum-hugr/src/ops/leaf.rs b/quantinuum-hugr/src/ops/leaf.rs index 127d0553a..5e871a7f1 100644 --- a/quantinuum-hugr/src/ops/leaf.rs +++ b/quantinuum-hugr/src/ops/leaf.rs @@ -6,13 +6,9 @@ use super::custom::{ExtensionOp, ExternalOp}; use super::dataflow::DataflowOpTrait; use super::{OpName, OpTag}; -use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; +use crate::extension::{ExtensionId, ExtensionRegistry, ExtensionSet, SignatureError}; use crate::types::type_param::TypeArg; -use crate::types::PolyFuncType; -use crate::{ - extension::ExtensionId, - types::{EdgeKind, FunctionType, Type, TypeRow}, -}; +use crate::types::{EdgeKind, PolyFuncType, Signature, Type, TypeRow}; /// Dataflow operations with no children. #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] @@ -184,24 +180,24 @@ impl DataflowOpTrait for LeafOp { // copy-on-write strategy, so we can avoid unnecessary allocations. match self { - LeafOp::Noop { ty: typ } => FunctionType::new(vec![typ.clone()], vec![typ.clone()]), + LeafOp::Noop { ty: typ } => Signature::new(vec![typ.clone()], vec![typ.clone()]), LeafOp::CustomOp(ext) => ext.signature(), LeafOp::MakeTuple { tys: types } => { - FunctionType::new(types.clone(), vec![Type::new_tuple(types.clone())]) + Signature::new(types.clone(), vec![Type::new_tuple(types.clone())]) } LeafOp::UnpackTuple { tys: types } => { - FunctionType::new(vec![Type::new_tuple(types.clone())], types.clone()) + Signature::new(vec![Type::new_tuple(types.clone())], types.clone()) } - LeafOp::Tag { tag, variants } => FunctionType::new( + LeafOp::Tag { tag, variants } => Signature::new( variants.get(*tag).expect("Not a valid tag").clone(), vec![Type::new_sum(variants.clone())], ), LeafOp::Lift { type_row, new_extension, - } => FunctionType::new(type_row.clone(), type_row.clone()) + } => Signature::new(type_row.clone(), type_row.clone()) .with_extension_delta(ExtensionSet::singleton(new_extension)), - LeafOp::TypeApply { ta } => FunctionType::new( + LeafOp::TypeApply { ta } => Signature::new( vec![Type::new_function(ta.input.clone())], vec![Type::new_function(ta.output.clone())], ), @@ -226,8 +222,8 @@ mod test { use crate::hugr::ValidationError; use crate::ops::handle::NodeHandle; use crate::std_extensions::collections::EXTENSION; - use crate::types::Type; - use crate::types::{test::nested_func, FunctionType, TypeArg}; + use crate::types::test::nested_func; + use crate::types::{Signature, Type, TypeArg}; use super::{LeafOp, TypeApplication}; @@ -238,7 +234,7 @@ mod test { let reg = ExtensionRegistry::try_new([PRELUDE.to_owned(), EXTENSION.to_owned()]).unwrap(); let pf_in = nested_func(); let pf_out = pf_in.instantiate(&[USIZE_TA], ®)?; - let mut dfg = DFGBuilder::new(FunctionType::new( + let mut dfg = DFGBuilder::new(Signature::new( vec![Type::new_function(pf_in.clone())], vec![Type::new_function(pf_out)], ))?; @@ -258,7 +254,7 @@ mod test { let pf = nested_func(); let pf_usz = pf.instantiate_poly(&[USIZE_TA], ®)?; let pf_bool = pf.instantiate_poly(&[TypeArg::Type { ty: BOOL_T }], ®)?; - let mut dfg = DFGBuilder::new(FunctionType::new( + let mut dfg = DFGBuilder::new(Signature::new( vec![Type::new_function(pf.clone())], vec![Type::new_function(pf_usz.clone())], ))?; From a1c29921f3872dae3de6628220a3397f429aeddb Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 11:56:21 +0000 Subject: [PATCH 34/57] serialization via try_into --- quantinuum-hugr/src/types.rs | 5 +++- quantinuum-hugr/src/types/serialize.rs | 32 ++++++++++++++++++++------ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index ca4480b65..fbcf946df 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -217,7 +217,10 @@ impl TypeEnum { Clone, PartialEq, Debug, Eq, derive_more::Display, serde::Serialize, serde::Deserialize, )] #[display(fmt = "{}", "_0")] -#[serde(into = "serialize::SerSimpleType", from = "serialize::SerSimpleType")] +#[serde( + into = "serialize::SerSimpleType", + try_from = "serialize::SerSimpleType" +)] /// A HUGR type - the valid types of [EdgeKind::Value] and [EdgeKind::Static] edges. /// Such an edge is valid if the ports on either end agree on the [Type]. /// Types have an optional [TypeBound] which places limits on the valid diff --git a/quantinuum-hugr/src/types/serialize.rs b/quantinuum-hugr/src/types/serialize.rs index 4fd098141..423bde785 100644 --- a/quantinuum-hugr/src/types/serialize.rs +++ b/quantinuum-hugr/src/types/serialize.rs @@ -1,3 +1,4 @@ +use super::type_row::RowVarOrType; use super::{PolyFuncType, SumType, Type, TypeArg, TypeBound, TypeEnum}; use super::custom::CustomType; @@ -39,20 +40,37 @@ impl From for SerSimpleType { } } -impl From for Type { - fn from(value: SerSimpleType) -> Type { - match value { +impl From for RowVarOrType { + fn from(value: SerSimpleType) -> RowVarOrType { + let ty = match value { SerSimpleType::Q => QB_T, SerSimpleType::I => USIZE_T, SerSimpleType::G(sig) => Type::new_function(*sig), SerSimpleType::Sum(sum) => sum.into(), - SerSimpleType::Array { inner, len } => { - array_type(TypeArg::BoundedNat { n: len }, (*inner).into()) - } + SerSimpleType::Array { inner, len } => array_type( + TypeArg::BoundedNat { n: len }, + (*inner) + .try_into() + .expect("Element type of array should not be a row"), + ), SerSimpleType::Opaque(custom) => Type::new_extension(custom), SerSimpleType::Alias(a) => Type::new_alias(a), SerSimpleType::V { i, b } => Type::new_var_use(i, b), - SerSimpleType::R { i, b } => Type::new_row_var(i, b), + SerSimpleType::R { i, b } => return RowVarOrType::RV(i, b), + }; + RowVarOrType::T(ty) + } +} + +impl TryFrom for Type { + type Error = String; // TODO ALAN What should this be? + + fn try_from(value: SerSimpleType) -> Result { + match value.into() { + RowVarOrType::T(t) => Ok(t), + RowVarOrType::RV(idx, bound) => Err(format!( + "Type contained Row Variable with DeBruijn index {idx} and bound {bound}" + )), } } } From 8277c7fd7d4d6c881ea23e3d4478ec73e42adf9b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 11:56:57 +0000 Subject: [PATCH 35/57] collections.rs update --- quantinuum-hugr/src/std_extensions/collections.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/quantinuum-hugr/src/std_extensions/collections.rs b/quantinuum-hugr/src/std_extensions/collections.rs index 6c829cbfb..4a6decb6b 100644 --- a/quantinuum-hugr/src/std_extensions/collections.rs +++ b/quantinuum-hugr/src/std_extensions/collections.rs @@ -346,8 +346,8 @@ mod test { let both_row: TypeRow = vec![list_t.clone(), QB_T].into(); let just_list_row: TypeRow = vec![list_t].into(); - assert_eq!(pop_sig.input(), &just_list_row); - assert_eq!(pop_sig.output(), &both_row); + assert_eq!(&pop_sig.input, &just_list_row); + assert_eq!(&pop_sig.output, &both_row); let push_op = ListOp::Push.with_type(FLOAT64_TYPE); let push_ext = push_op.clone().to_extension_op(®).unwrap(); @@ -359,7 +359,7 @@ mod test { let both_row: TypeRow = vec![list_t.clone(), FLOAT64_TYPE].into(); let just_list_row: TypeRow = vec![list_t].into(); - assert_eq!(push_sig.input(), &both_row); - assert_eq!(push_sig.output(), &just_list_row); + assert_eq!(&push_sig.input, &both_row); + assert_eq!(&push_sig.output, &just_list_row); } } From fe4f84cb2a73640540e331764228bded95e0f885 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 11:57:08 +0000 Subject: [PATCH 36/57] WIP len?? --- quantinuum-hugr/src/types/type_row.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index 00f180876..b26eaefef 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -90,7 +90,7 @@ where self.types.to_mut().get_mut(offset.index()) } - /// Returns a reference to the types in the row. + /// Returns a reference to the types and row variables in the row. pub fn as_slice(&self) -> &[T] { &self.types } @@ -106,11 +106,19 @@ where /// Allow access (consumption) of the contained elements pub fn into_owned(self) -> Vec; + /// Returns `true` if the row contains no types or row variables + /// (so will necessarily be empty after substitution, too). + pub fn is_empty(&self) -> bool ; + + } + } +} + +impl TypeRow { + delegate! { + to self.types { /// Returns the number of types in the row. pub fn len(&self) -> usize; - - /// Returns `true` if the row contains no types. - pub fn is_empty(&self) -> bool ; } } } From e2a7e48afee161c54ab3b0b2e880c4017a2b92ad Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 12:14:44 +0000 Subject: [PATCH 37/57] conversions: more RowVarOrType::, no Type::new_row_var, + TypeRowBase From elem --- quantinuum-hugr/src/extension/infer/test.rs | 6 ++++-- quantinuum-hugr/src/hugr/validate/test.rs | 7 ++++--- .../src/std_extensions/arithmetic/conversions.rs | 4 ++-- .../src/std_extensions/arithmetic/int_ops.rs | 2 +- quantinuum-hugr/src/types/poly_func.rs | 13 +++++++------ quantinuum-hugr/src/types/type_row.rs | 12 ++++++++++++ 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/quantinuum-hugr/src/extension/infer/test.rs b/quantinuum-hugr/src/extension/infer/test.rs index 3b0ca6e34..be6ae396e 100644 --- a/quantinuum-hugr/src/extension/infer/test.rs +++ b/quantinuum-hugr/src/extension/infer/test.rs @@ -12,6 +12,7 @@ use crate::macros::const_extension_ids; use crate::ops::custom::{ExternalOp, OpaqueOp}; use crate::ops::{self, dataflow::IOTrait}; use crate::ops::{LeafOp, OpType}; +use crate::types::type_row::RowVarOrType; #[cfg(feature = "extension_inference")] use crate::{ builder::test::closed_dfg_root_hugr, @@ -472,11 +473,12 @@ fn make_block( } fn oneway(ty: Type) -> Vec { - vec![Type::new_sum([vec![ty].into()])] + vec![Type::new_sum([RowVarOrType::T(ty)])] } fn twoway(ty: Type) -> Vec { - vec![Type::new_sum([vec![ty.clone()].into(), vec![ty].into()])] + let r = RowVarOrType::T(ty); + vec![Type::new_sum([r.clone(), r])] } fn create_entry_exit( diff --git a/quantinuum-hugr/src/hugr/validate/test.rs b/quantinuum-hugr/src/hugr/validate/test.rs index b358a7fe3..f1528aaee 100644 --- a/quantinuum-hugr/src/hugr/validate/test.rs +++ b/quantinuum-hugr/src/hugr/validate/test.rs @@ -15,6 +15,7 @@ use crate::ops::{self, Const, LeafOp, OpType}; use crate::std_extensions::logic::test::{and_op, or_op}; use crate::std_extensions::logic::{self, NotOp}; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; +use crate::types::type_row::{RowVarOrType, TypeRowV}; use crate::types::{CustomType, FunctionType, PolyFuncType, Type, TypeBound, TypeRow}; use crate::{type_row, Direction, IncomingPort, Node}; @@ -518,7 +519,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { "myfunc", PolyFuncType::new( [BOUND], - FunctionType::new(vec![], vec![list_of_var.clone()]) + FunctionType::new(TypeRowV::default(), vec![list_of_var.clone()]) .with_extension_delta(collections::EXTENSION_NAME), ), )?; @@ -543,7 +544,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { #[test] fn inner_row_variables() -> Result<(), Box> { - let tv = Type::new_row_var(0, TypeBound::Any); + let tv = RowVarOrType::RV(0, TypeBound::Any); let inner_ft = Type::new_function(FunctionType::new_endo(vec![tv])); let mut fb = FunctionBuilder::new( "id", @@ -563,7 +564,7 @@ fn inner_row_variables() -> Result<(), Box> { #[test] fn no_outer_row_variables() -> Result<(), Box> { - let tv = Type::new_row_var(0, TypeBound::Any); + let tv = RowVarOrType::RV(0, TypeBound::Any); let fb = FunctionBuilder::new( "impossible_id_of_unknown_arity", PolyFuncType::new( diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs b/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs index 39fa73c5e..b5da37c37 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs @@ -12,7 +12,7 @@ use crate::{ }, ops::{custom::ExtensionOp, OpName}, type_row, - types::{FunctionType, PolyFuncType, TypeArg}, + types::{type_row::RowVarOrType, FunctionType, PolyFuncType, TypeArg}, Extension, }; @@ -45,7 +45,7 @@ impl MakeOpDef for ConvertOpDef { vec![LOG_WIDTH_TYPE_PARAM], FunctionType::new( type_row![FLOAT64_TYPE], - vec![sum_with_error(int_tv(0)).into()], + vec![RowVarOrType::T(sum_with_error(int_tv(0)).into())], ), ), diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs index 97c61ed2a..b12cc72f7 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs @@ -224,7 +224,7 @@ fn int_polytype( ) -> PolyFuncType { PolyFuncType::new( vec![LOG_WIDTH_TYPE_PARAM; n_vars], - FunctionType::new(input, output), + FunctionType::new(input.into(), output.into()), ) } diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index eaad18c5d..624f000f4 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -10,7 +10,7 @@ use super::{ type_param::{check_type_args, TypeArg, TypeParam}, type_row::RowVarOrType, }; -use super::{FunctionType, Signature, Substitution, Type, TypeBound}; +use super::{FunctionType, Signature, Substitution, TypeBound}; /// A polymorphic function type, e.g. of a [Graph], or perhaps an [OpDef]. /// (Nodes/operations in the Hugr are not polymorphic.) @@ -254,6 +254,7 @@ pub(crate) mod test { }; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; + use crate::types::type_row::{RowVarOrType, TypeRowV}; use crate::types::{CustomType, FunctionType, Type, TypeBound}; use crate::Extension; @@ -658,7 +659,7 @@ pub(crate) mod test { }], FunctionType::new( vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], - vec![Type::new_sum(vec![Type::new_row_var(0, TypeBound::Any)])], + vec![Type::new_sum(vec![RowVarOrType::RV(0, TypeBound::Any)])], ), &PRELUDE_REGISTRY, ) @@ -669,8 +670,8 @@ pub(crate) mod test { param: Box::new(TP), }], FunctionType::new( - vec![USIZE_T, Type::new_row_var(0, TypeBound::Any)], - vec![Type::new_sum(vec![Type::new_row_var(0, TypeBound::Any)])], + vec![USIZE_T.into(), RowVarOrType::RV(0, TypeBound::Any)], + vec![Type::new_sum(vec![RowVarOrType::RV(0, TypeBound::Any)])], ), &PRELUDE_REGISTRY, ) @@ -696,14 +697,14 @@ pub(crate) mod test { t2, FunctionType::new( vec![USIZE_T, USIZE_T, BOOL_T], - vec![Type::new_sum(vec![USIZE_T, BOOL_T])] + vec![Type::new_sum(vec![RowVarOrType::T(USIZE_T), BOOL_T.into()])] ) ); } #[test] fn row_variables_inner() { - let inner_fty = Type::new_function(FunctionType::new_endo(vec![Type::new_row_var( + let inner_fty = Type::new_function(FunctionType::new_endo(vec![RowVarOrType::RV( 0, TypeBound::Copyable, )])); diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index b26eaefef..1f090fbc0 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -185,6 +185,18 @@ where } } +impl From for TypeRowBase +where + T: Clone, + [T]: ToOwned>, +{ + fn from(value: T) -> Self { + Self { + types: vec![value].into(), + } + } +} + impl Deref for TypeRowBase where [T]: ToOwned>, From dde479507dbbd8aad769480a2587affff0f6529b Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 12:40:37 +0000 Subject: [PATCH 38/57] More test updates --- .../src/hugr/rewrite/inline_dfg.rs | 18 +++++++----------- quantinuum-hugr/src/hugr/rewrite/replace.rs | 19 ++++++++----------- .../src/hugr/rewrite/simple_replace.rs | 14 +++++++------- quantinuum-hugr/src/hugr/serialize.rs | 12 ++++++------ quantinuum-hugr/src/hugr/validate/test.rs | 18 ++++++------------ .../src/std_extensions/arithmetic/int_ops.rs | 13 ++++++++----- 6 files changed, 42 insertions(+), 52 deletions(-) diff --git a/quantinuum-hugr/src/hugr/rewrite/inline_dfg.rs b/quantinuum-hugr/src/hugr/rewrite/inline_dfg.rs index e5a6c4062..95b5f886d 100644 --- a/quantinuum-hugr/src/hugr/rewrite/inline_dfg.rs +++ b/quantinuum-hugr/src/hugr/rewrite/inline_dfg.rs @@ -143,7 +143,7 @@ mod test { use crate::std_extensions::arithmetic::float_types; use crate::std_extensions::arithmetic::int_ops::{self, IntOpDef}; use crate::std_extensions::arithmetic::int_types::{self, ConstIntU}; - use crate::types::FunctionType; + use crate::types::Signature; use crate::utils::test_quantum_extension; use crate::{type_row, Direction, HugrView, Node, Port}; use crate::{Hugr, Wire}; @@ -175,7 +175,7 @@ mod test { let int_ty = &int_types::INT_TYPES[6]; let mut outer = DFGBuilder::new( - FunctionType::new(vec![int_ty.clone(); 2], vec![int_ty.clone()]) + Signature::new(vec![int_ty.clone(); 2], vec![int_ty.clone()]) .with_extension_delta(delta.clone()), )?; let [a, b] = outer.input_wires_arr(); @@ -199,7 +199,7 @@ mod test { let c1 = nonlocal.then(|| make_const(&mut outer)); let inner = { let mut inner = outer.dfg_builder( - FunctionType::new_endo(vec![int_ty.clone()]).with_extension_delta(delta), + Signature::new_endo(vec![int_ty.clone()]).with_extension_delta(delta), None, [a], )?; @@ -252,7 +252,7 @@ mod test { #[test] fn permutation() -> Result<(), Box> { let mut h = DFGBuilder::new( - FunctionType::new_endo(type_row![QB_T, QB_T]) + Signature::new_endo(type_row![QB_T, QB_T]) .with_extension_delta(test_quantum_extension::EXTENSION_ID), )?; let [p, q] = h.input_wires_arr(); @@ -260,11 +260,7 @@ mod test { .add_dataflow_op(test_quantum_extension::h_gate(), [p])? .outputs_arr(); let swap = { - let swap = h.dfg_builder( - FunctionType::new_endo(type_row![QB_T, QB_T]), - None, - [p_h, q], - )?; + let swap = h.dfg_builder(Signature::new_endo(type_row![QB_T, QB_T]), None, [p_h, q])?; let [a, b] = swap.input_wires_arr(); swap.finish_with_outputs([b, a])? }; @@ -354,14 +350,14 @@ mod test { ]) .unwrap(); let mut outer = DFGBuilder::new( - FunctionType::new_endo(type_row![QB_T, QB_T]) + Signature::new_endo(type_row![QB_T, QB_T]) .with_extension_delta(float_types::EXTENSION_ID), )?; let [a, b] = outer.input_wires_arr(); let h_a = outer.add_dataflow_op(test_quantum_extension::h_gate(), [a])?; let h_b = outer.add_dataflow_op(test_quantum_extension::h_gate(), [b])?; let mut inner = outer.dfg_builder( - FunctionType::new_endo(type_row![QB_T]).with_extension_delta(float_types::EXTENSION_ID), + Signature::new_endo(type_row![QB_T]).with_extension_delta(float_types::EXTENSION_ID), None, h_b.outputs(), )?; diff --git a/quantinuum-hugr/src/hugr/rewrite/replace.rs b/quantinuum-hugr/src/hugr/rewrite/replace.rs index dc54f6652..717c26835 100644 --- a/quantinuum-hugr/src/hugr/rewrite/replace.rs +++ b/quantinuum-hugr/src/hugr/rewrite/replace.rs @@ -458,7 +458,7 @@ mod test { use crate::ops::handle::{BasicBlockID, ConstID, NodeHandle}; use crate::ops::{self, Case, DataflowBlock, LeafOp, OpTag, OpType, DFG}; use crate::std_extensions::collections; - use crate::types::{FunctionType, Type, TypeArg, TypeRow}; + use crate::types::{Signature, Type, TypeArg, TypeRow}; use crate::{type_row, Direction, Hugr, HugrView, OutgoingPort}; use super::{NewEdgeKind, NewEdgeSpec, ReplaceError, Replacement}; @@ -489,7 +489,7 @@ mod test { let mut cfg = CFGBuilder::new( // One might expect an extension_delta of "collections" here, but push/pop // have an empty delta themselves, pending https://github.com/CQCL/hugr/issues/388 - FunctionType::new_endo(just_list.clone()), + Signature::new_endo(just_list.clone()), )?; let pred_const = cfg.add_constant(ops::Const::unary_unit_sum()); @@ -520,7 +520,7 @@ mod test { // Replacement: one BB with two DFGs inside. // Use Hugr rather than Builder because DFGs must be empty (not even Input/Output). let mut replacement = Hugr::new(NodeType::new_open(ops::CFG { - signature: FunctionType::new_endo(just_list.clone()), + signature: Signature::new_endo(just_list.clone()), })); let r_bb = replacement.add_node_with_parent( replacement.root(), @@ -536,16 +536,13 @@ mod test { let r_df1 = replacement.add_node_with_parent( r_bb, DFG { - signature: FunctionType::new( - vec![listy.clone()], - simple_unary_plus(intermed.clone()), - ), + signature: Signature::new(vec![listy.clone()], simple_unary_plus(intermed.clone())), }, ); let r_df2 = replacement.add_node_with_parent( r_bb, DFG { - signature: FunctionType::new(intermed, simple_unary_plus(just_list.clone())), + signature: Signature::new(intermed, simple_unary_plus(just_list.clone())), }, ); [0, 1] @@ -626,7 +623,7 @@ mod test { OpType::CFG(c) => &c.signature.input, _ => panic!(), }, - op_sig.input() + &op_sig.input ); h.simple_entry_builder(op_sig.output, 1, op_sig.extension_reqs.clone())? } else { @@ -646,7 +643,7 @@ mod test { #[test] fn test_invalid() -> Result<(), Box> { - let utou = FunctionType::new_endo(vec![USIZE_T]); + let utou = Signature::new_endo(vec![USIZE_T]); let mk_op = |s| { LeafOp::from(ExternalOp::Opaque(OpaqueOp::new( ExtensionId::new("unknown_ext").unwrap(), @@ -656,7 +653,7 @@ mod test { utou.clone(), ))) }; - let mut h = DFGBuilder::new(FunctionType::new( + let mut h = DFGBuilder::new(Signature::new( type_row![USIZE_T, BOOL_T], type_row![USIZE_T], ))?; diff --git a/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs b/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs index ebee0d1bf..39e051ea2 100644 --- a/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs +++ b/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs @@ -212,7 +212,7 @@ pub(in crate::hugr::rewrite) mod test { use crate::ops::{OpTrait, OpType}; use crate::std_extensions::logic::test::and_op; use crate::type_row; - use crate::types::{FunctionType, Type}; + use crate::types::{FunctionType, Signature, Type}; use crate::utils::test_quantum_extension::{cx_gate, h_gate}; use crate::{IncomingPort, Node}; @@ -242,7 +242,7 @@ pub(in crate::hugr::rewrite) mod test { let q_out = func_builder.add_dataflow_op(h_gate(), vec![qb2])?; let mut inner_builder = func_builder.dfg_builder( - FunctionType::new(type_row![QB, QB], type_row![QB, QB]), + Signature::new(type_row![QB, QB], type_row![QB, QB]), None, [qb0, qb1], )?; @@ -275,7 +275,7 @@ pub(in crate::hugr::rewrite) mod test { /// └───┘└───┘ fn make_dfg_hugr() -> Result { let mut dfg_builder = - DFGBuilder::new(FunctionType::new(type_row![QB, QB], type_row![QB, QB]))?; + DFGBuilder::new(Signature::new(type_row![QB, QB], type_row![QB, QB]))?; let [wire0, wire1] = dfg_builder.input_wires_arr(); let wire2 = dfg_builder.add_dataflow_op(h_gate(), vec![wire0])?; let wire3 = dfg_builder.add_dataflow_op(h_gate(), vec![wire1])?; @@ -296,7 +296,7 @@ pub(in crate::hugr::rewrite) mod test { /// └───┘ fn make_dfg_hugr2() -> Result { let mut dfg_builder = - DFGBuilder::new(FunctionType::new(type_row![QB, QB], type_row![QB, QB]))?; + DFGBuilder::new(Signature::new(type_row![QB, QB], type_row![QB, QB]))?; let [wire0, wire1] = dfg_builder.input_wires_arr(); let wire2 = dfg_builder.add_dataflow_op(h_gate(), vec![wire1])?; let wire2out = wire2.outputs().exactly_one().unwrap(); @@ -466,7 +466,7 @@ pub(in crate::hugr::rewrite) mod test { #[test] fn test_replace_cx_cross() { let q_row: Vec = vec![QB, QB]; - let mut builder = DFGBuilder::new(FunctionType::new(q_row.clone(), q_row)).unwrap(); + let mut builder = DFGBuilder::new(Signature::new(q_row.clone(), q_row)).unwrap(); let mut circ = builder.as_circuit(builder.input_wires()); circ.append(cx_gate(), [0, 1]).unwrap(); circ.append(cx_gate(), [1, 0]).unwrap(); @@ -525,7 +525,7 @@ pub(in crate::hugr::rewrite) mod test { let two_bit = type_row![BOOL_T, BOOL_T]; let mut builder = - DFGBuilder::new(FunctionType::new(one_bit.clone(), one_bit.clone())).unwrap(); + DFGBuilder::new(Signature::new(one_bit.clone(), one_bit.clone())).unwrap(); let inw = builder.input_wires().exactly_one().unwrap(); let outw = builder .add_dataflow_op(and_op(), [inw, inw]) @@ -534,7 +534,7 @@ pub(in crate::hugr::rewrite) mod test { let [input, _] = builder.io(); let mut h = builder.finish_hugr_with_outputs(outw, &EMPTY_REG).unwrap(); - let mut builder = DFGBuilder::new(FunctionType::new(two_bit, one_bit)).unwrap(); + let mut builder = DFGBuilder::new(Signature::new(two_bit, one_bit)).unwrap(); let inw = builder.input_wires(); let outw = builder.add_dataflow_op(and_op(), inw).unwrap().outputs(); let [repl_input, repl_output] = builder.io(); diff --git a/quantinuum-hugr/src/hugr/serialize.rs b/quantinuum-hugr/src/hugr/serialize.rs index 5c6110f49..0844ee835 100644 --- a/quantinuum-hugr/src/hugr/serialize.rs +++ b/quantinuum-hugr/src/hugr/serialize.rs @@ -267,7 +267,7 @@ pub mod test { use crate::std_extensions::arithmetic::float_ops::FLOAT_OPS_REGISTRY; use crate::std_extensions::arithmetic::float_types::{ConstF64, FLOAT64_TYPE}; use crate::std_extensions::logic::NotOp; - use crate::types::{FunctionType, Type}; + use crate::types::{FunctionType, Signature, Type}; use crate::{type_row, OutgoingPort}; use itertools::Itertools; use jsonschema::{Draft, JSONSchema}; @@ -382,7 +382,7 @@ pub mod test { let outputs = g.num_outputs(node); match (inputs == 0, outputs == 0) { (false, false) => DFG { - signature: FunctionType::new(vec![NAT; inputs - 1], vec![NAT; outputs - 1]), + signature: Signature::new(vec![NAT; inputs - 1], vec![NAT; outputs - 1]), } .into(), (true, false) => Input::new(vec![NAT; outputs - 1]).into(), @@ -465,7 +465,7 @@ pub mod test { #[test] fn dfg_roundtrip() -> Result<(), Box> { let tp: Vec = vec![BOOL_T; 2]; - let mut dfg = DFGBuilder::new(FunctionType::new(tp.clone(), tp))?; + let mut dfg = DFGBuilder::new(Signature::new(tp.clone(), tp))?; let mut params: [_; 2] = dfg.input_wires_arr(); for p in params.iter_mut() { *p = dfg @@ -482,7 +482,7 @@ pub mod test { #[test] fn opaque_ops() -> Result<(), Box> { let tp: Vec = vec![BOOL_T; 1]; - let mut dfg = DFGBuilder::new(FunctionType::new_endo(tp))?; + let mut dfg = DFGBuilder::new(Signature::new_endo(tp))?; let [wire] = dfg.input_wires_arr(); // Add an extension operation @@ -504,7 +504,7 @@ pub mod test { #[test] fn hierarchy_order() -> Result<(), Box> { - let mut hugr = closed_dfg_root_hugr(FunctionType::new(vec![QB], vec![QB])); + let mut hugr = closed_dfg_root_hugr(Signature::new(vec![QB], vec![QB])); let [old_in, out] = hugr.get_io(hugr.root()).unwrap(); hugr.connect(old_in, 0, out, 0); @@ -527,7 +527,7 @@ pub mod test { // Miri doesn't run the extension registration required by `typetag` for registering `CustomConst`s. // https://github.com/rust-lang/miri/issues/450 fn constants_roundtrip() -> Result<(), Box> { - let mut builder = DFGBuilder::new(FunctionType::new(vec![], vec![FLOAT64_TYPE])).unwrap(); + let mut builder = DFGBuilder::new(Signature::new(vec![], vec![FLOAT64_TYPE])).unwrap(); let w = builder.add_load_const(ConstF64::new(0.5)); let hugr = builder.finish_hugr_with_outputs([w], &FLOAT_OPS_REGISTRY)?; diff --git a/quantinuum-hugr/src/hugr/validate/test.rs b/quantinuum-hugr/src/hugr/validate/test.rs index f1528aaee..4ca5f3bb6 100644 --- a/quantinuum-hugr/src/hugr/validate/test.rs +++ b/quantinuum-hugr/src/hugr/validate/test.rs @@ -16,7 +16,7 @@ use crate::std_extensions::logic::test::{and_op, or_op}; use crate::std_extensions::logic::{self, NotOp}; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; use crate::types::type_row::{RowVarOrType, TypeRowV}; -use crate::types::{CustomType, FunctionType, PolyFuncType, Type, TypeBound, TypeRow}; +use crate::types::{CustomType, FunctionType, PolyFuncType, Signature, Type, TypeBound, TypeRow}; use crate::{type_row, Direction, IncomingPort, Node}; const NAT: Type = crate::extension::prelude::USIZE_T; @@ -101,7 +101,7 @@ fn leaf_root() { #[test] fn dfg_root() { let dfg_op: OpType = ops::DFG { - signature: FunctionType::new_endo(type_row![BOOL_T]), + signature: Signature::new_endo(type_row![BOOL_T]), } .into(); @@ -213,17 +213,14 @@ fn df_children_restrictions() { #[test] fn test_ext_edge() { - let mut h = closed_dfg_root_hugr(FunctionType::new( - type_row![BOOL_T, BOOL_T], - type_row![BOOL_T], - )); + let mut h = closed_dfg_root_hugr(Signature::new(type_row![BOOL_T, BOOL_T], type_row![BOOL_T])); let [input, output] = h.get_io(h.root()).unwrap(); // Nested DFG BOOL_T -> BOOL_T let sub_dfg = h.add_node_with_parent( h.root(), ops::DFG { - signature: FunctionType::new_endo(type_row![BOOL_T]), + signature: Signature::new_endo(type_row![BOOL_T]), }, ); // this Xor has its 2nd input unconnected @@ -258,7 +255,7 @@ fn test_ext_edge() { #[test] fn test_local_const() { - let mut h = closed_dfg_root_hugr(FunctionType::new(type_row![BOOL_T], type_row![BOOL_T])); + let mut h = closed_dfg_root_hugr(Signature::new(type_row![BOOL_T], type_row![BOOL_T])); let [input, output] = h.get_io(h.root()).unwrap(); let and = h.add_node_with_parent(h.root(), and_op()); h.connect(input, 0, and, 0); @@ -289,10 +286,7 @@ fn test_local_const() { #[test] fn dfg_with_cycles() { - let mut h = closed_dfg_root_hugr(FunctionType::new( - type_row![BOOL_T, BOOL_T], - type_row![BOOL_T], - )); + let mut h = closed_dfg_root_hugr(Signature::new(type_row![BOOL_T, BOOL_T], type_row![BOOL_T])); let [input, output] = h.get_io(h.root()).unwrap(); let or = h.add_node_with_parent(h.root(), or_op()); let not1 = h.add_node_with_parent(h.root(), NotOp); diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs index b12cc72f7..502e173fc 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs @@ -331,7 +331,10 @@ impl IntOpDef { #[cfg(test)] mod test { - use crate::{ops::dataflow::DataflowOpTrait, std_extensions::arithmetic::int_types::int_type}; + use crate::{ + ops::dataflow::DataflowOpTrait, std_extensions::arithmetic::int_types::int_type, + types::Signature, + }; use super::*; @@ -356,7 +359,7 @@ mod test { .to_extension_op() .unwrap() .signature(), - FunctionType::new(vec![int_type(ta(3))], vec![int_type(ta(4))],) + Signature::new(vec![int_type(ta(3))], vec![int_type(ta(4))],) ); assert_eq!( IntOpDef::iwiden_s @@ -364,7 +367,7 @@ mod test { .to_extension_op() .unwrap() .signature(), - FunctionType::new(vec![int_type(ta(3))], vec![int_type(ta(3))],) + Signature::new(vec![int_type(ta(3))], vec![int_type(ta(3))],) ); assert_eq!( IntOpDef::inarrow_s @@ -372,7 +375,7 @@ mod test { .to_extension_op() .unwrap() .signature(), - FunctionType::new( + Signature::new( vec![int_type(ta(3))], vec![sum_with_error(int_type(ta(3))).into()], ) @@ -391,7 +394,7 @@ mod test { .to_extension_op() .unwrap() .signature(), - FunctionType::new( + Signature::new( vec![int_type(ta(2))], vec![sum_with_error(int_type(ta(1))).into()], ) From 9bb09bd41bb06005980b3ec9bd676caf253cf64c Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 12:42:00 +0000 Subject: [PATCH 39/57] fix declarative/signature.rs --- quantinuum-hugr/src/extension/declarative/signature.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/quantinuum-hugr/src/extension/declarative/signature.rs b/quantinuum-hugr/src/extension/declarative/signature.rs index b67d68068..3e746b33e 100644 --- a/quantinuum-hugr/src/extension/declarative/signature.rs +++ b/quantinuum-hugr/src/extension/declarative/signature.rs @@ -14,7 +14,8 @@ use smol_str::SmolStr; use crate::extension::prelude::PRELUDE_ID; use crate::extension::{CustomValidator, ExtensionSet, SignatureFunc, TypeDef, TypeParametrised}; use crate::types::type_param::TypeParam; -use crate::types::{CustomType, FunctionType, PolyFuncType, Type, TypeRow}; +use crate::types::type_row::TypeRowV; +use crate::types::{CustomType, FunctionType, PolyFuncType, Type}; use crate::Extension; use super::{DeclarationContext, ExtensionDeclarationError}; @@ -41,7 +42,7 @@ impl SignatureDeclaration { op_params: &[TypeParam], ) -> Result { let make_type_row = - |v: &[SignaturePortDeclaration]| -> Result { + |v: &[SignaturePortDeclaration]| -> Result { let types = v .iter() .map(|port_decl| port_decl.make_types(ext, ctx, op_params)) From 57c2163d26ea28d46baa40922e13d0e61dae4481 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 17:36:00 +0000 Subject: [PATCH 40/57] Split PolyFixedFunc off PolyFuncType, use for functions + Call --- quantinuum-hugr/src/builder.rs | 4 +- quantinuum-hugr/src/builder/build_traits.rs | 13 +-- quantinuum-hugr/src/builder/cfg.rs | 3 +- quantinuum-hugr/src/builder/circuit.rs | 9 +- quantinuum-hugr/src/builder/conditional.rs | 8 +- quantinuum-hugr/src/builder/dataflow.rs | 48 ++++------ quantinuum-hugr/src/builder/module.rs | 29 +++--- quantinuum-hugr/src/builder/tail_loop.rs | 4 +- quantinuum-hugr/src/extension/infer/test.rs | 4 +- quantinuum-hugr/src/extension/op_def.rs | 25 ++--- quantinuum-hugr/src/extension/prelude.rs | 2 +- quantinuum-hugr/src/hugr/hugrmut.rs | 4 +- quantinuum-hugr/src/hugr/rewrite/consts.rs | 5 +- .../src/hugr/rewrite/outline_cfg.rs | 4 +- .../src/hugr/rewrite/simple_replace.rs | 2 +- quantinuum-hugr/src/hugr/serialize.rs | 2 +- quantinuum-hugr/src/hugr/validate/test.rs | 50 +++++----- quantinuum-hugr/src/hugr/views.rs | 14 +-- quantinuum-hugr/src/hugr/views/descendants.rs | 8 +- quantinuum-hugr/src/hugr/views/sibling.rs | 2 +- .../src/hugr/views/sibling_subgraph.rs | 7 +- quantinuum-hugr/src/hugr/views/tests.rs | 4 +- quantinuum-hugr/src/ops/dataflow.rs | 19 ++-- quantinuum-hugr/src/ops/module.rs | 6 +- quantinuum-hugr/src/types.rs | 2 +- quantinuum-hugr/src/types/poly_func.rs | 93 ++++++++++++------- 26 files changed, 181 insertions(+), 190 deletions(-) diff --git a/quantinuum-hugr/src/builder.rs b/quantinuum-hugr/src/builder.rs index 3a563573e..0967909ec 100644 --- a/quantinuum-hugr/src/builder.rs +++ b/quantinuum-hugr/src/builder.rs @@ -223,7 +223,7 @@ pub(crate) mod test { use crate::hugr::{views::HugrView, HugrMut, NodeType}; use crate::ops; - use crate::types::{PolyFuncType, Signature, Type}; + use crate::types::{PolyFixedFunc, Signature, Type}; use crate::{type_row, Hugr}; use super::handle::BuildHandle; @@ -246,7 +246,7 @@ pub(crate) mod test { } pub(super) fn build_main( - signature: PolyFuncType, + signature: PolyFixedFunc, f: impl FnOnce(FunctionBuilder<&mut Hugr>) -> Result>, BuildError>, ) -> Result { let mut module_builder = ModuleBuilder::new(); diff --git a/quantinuum-hugr/src/builder/build_traits.rs b/quantinuum-hugr/src/builder/build_traits.rs index 879dee5bd..950385684 100644 --- a/quantinuum-hugr/src/builder/build_traits.rs +++ b/quantinuum-hugr/src/builder/build_traits.rs @@ -20,7 +20,7 @@ use crate::{ }; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError, PRELUDE_REGISTRY}; -use crate::types::{FunctionType, PolyFuncType, Signature, Type, TypeArg, TypeRow}; +use crate::types::{PolyFixedFunc, Signature, Type, TypeArg, TypeRow}; use itertools::Itertools; @@ -85,9 +85,10 @@ pub trait Container { fn define_function( &mut self, name: impl Into, - signature: PolyFuncType, + signature: impl Into, ) -> Result, BuildError> { - let body = fix_sig(signature.body().clone())?; + let signature = signature.into(); + let body = signature.body().clone(); let f_node = self.add_child_node(NodeType::new_pure(ops::FuncDefn { name: name.into(), signature, @@ -715,12 +716,6 @@ fn wire_up( )) } -pub(super) fn fix_sig(fnty: FunctionType) -> Result { - fnty.try_into().map_err(|(idx, bound)| { - BuildError::SignatureError(SignatureError::ContainsRowVars { idx, bound }) - }) -} - /// Trait implemented by builders of Dataflow Hugrs pub trait DataflowHugr: HugrBuilder + Dataflow { /// Set outputs of dataflow HUGR and return validated HUGR diff --git a/quantinuum-hugr/src/builder/cfg.rs b/quantinuum-hugr/src/builder/cfg.rs index c815fcbe8..48aa54eb1 100644 --- a/quantinuum-hugr/src/builder/cfg.rs +++ b/quantinuum-hugr/src/builder/cfg.rs @@ -403,7 +403,6 @@ pub(crate) mod test { use crate::hugr::validate::InterGraphEdgeError; use crate::hugr::ValidationError; - use crate::types::FunctionType; use crate::{builder::test::NAT, type_row}; use cool_asserts::assert_matches; @@ -413,7 +412,7 @@ pub(crate) mod test { let build_result = { let mut module_builder = ModuleBuilder::new(); let mut func_builder = module_builder - .define_function("main", FunctionType::new(vec![NAT], type_row![NAT]).into())?; + .define_function("main", Signature::new(vec![NAT], type_row![NAT]))?; let _f_id = { let [int] = func_builder.input_wires_arr(); diff --git a/quantinuum-hugr/src/builder/circuit.rs b/quantinuum-hugr/src/builder/circuit.rs index f8957e3a5..786d13454 100644 --- a/quantinuum-hugr/src/builder/circuit.rs +++ b/quantinuum-hugr/src/builder/circuit.rs @@ -247,13 +247,12 @@ mod test { extension::prelude::BOOL_T, ops::{custom::OpaqueOp, LeafOp}, type_row, - types::FunctionType, }; #[test] fn simple_linear() { let build_res = build_main( - FunctionType::new(type_row![QB, QB], type_row![QB, QB]).into(), + Signature::new(type_row![QB, QB], type_row![QB, QB]).into(), |mut f_build| { let wires = f_build.input_wires().map(Some).collect(); @@ -290,7 +289,7 @@ mod test { .into(), ); let build_res = build_main( - FunctionType::new(type_row![QB, QB, NAT], type_row![QB, QB, BOOL_T]).into(), + Signature::new(type_row![QB, QB, NAT], type_row![QB, QB, BOOL_T]).into(), |mut f_build| { let [q0, q1, angle]: [Wire; 3] = f_build.input_wires_arr(); @@ -315,7 +314,7 @@ mod test { #[test] fn ancillae() { let build_res = build_main( - FunctionType::new(type_row![QB], type_row![QB]).into(), + Signature::new(type_row![QB], type_row![QB]).into(), |mut f_build| { let mut circ = f_build.as_circuit(f_build.input_wires()); assert_eq!(circ.n_wires(), 1); @@ -351,7 +350,7 @@ mod test { #[test] fn circuit_builder_errors() { let _build_res = build_main( - FunctionType::new_endo(type_row![QB, QB]).into(), + Signature::new_endo(type_row![QB, QB]).into(), |mut f_build| { let mut circ = f_build.as_circuit(f_build.input_wires()); let [q0, q1] = circ.tracked_units_arr(); diff --git a/quantinuum-hugr/src/builder/conditional.rs b/quantinuum-hugr/src/builder/conditional.rs index f825ad445..d2d66270d 100644 --- a/quantinuum-hugr/src/builder/conditional.rs +++ b/quantinuum-hugr/src/builder/conditional.rs @@ -1,7 +1,7 @@ use crate::extension::ExtensionRegistry; use crate::hugr::views::HugrView; use crate::ops::dataflow::DataflowOpTrait; -use crate::types::{FunctionType, Signature, TypeRow}; +use crate::types::{Signature, TypeRow}; use crate::ops; use crate::ops::handle::CaseID; @@ -238,10 +238,8 @@ mod test { fn basic_conditional_module() -> Result<(), BuildError> { let build_result: Result = { let mut module_builder = ModuleBuilder::new(); - let mut fbuild = module_builder.define_function( - "main", - FunctionType::new(type_row![NAT], type_row![NAT]).into(), - )?; + let mut fbuild = module_builder + .define_function("main", Signature::new(type_row![NAT], type_row![NAT]))?; let tru_const = fbuild.add_constant(Const::true_val()); let _fdef = { let const_wire = fbuild.load_const(&tru_const); diff --git a/quantinuum-hugr/src/builder/dataflow.rs b/quantinuum-hugr/src/builder/dataflow.rs index 091d9775a..fedf2cde1 100644 --- a/quantinuum-hugr/src/builder/dataflow.rs +++ b/quantinuum-hugr/src/builder/dataflow.rs @@ -1,4 +1,4 @@ -use super::build_traits::{fix_sig, HugrBuilder, SubContainer}; +use super::build_traits::{HugrBuilder, SubContainer}; use super::handle::BuildHandle; use super::{BuildError, Container, Dataflow, DfgID, FuncID}; @@ -7,7 +7,7 @@ use std::marker::PhantomData; use crate::hugr::{HugrView, NodeType, ValidationError}; use crate::ops; -use crate::types::{PolyFuncType, Signature}; +use crate::types::{PolyFixedFunc, Signature}; use crate::extension::{ExtensionRegistry, ExtensionSet}; use crate::Node; @@ -147,8 +147,8 @@ impl FunctionBuilder { /// # Errors /// /// Error in adding DFG child nodes. - pub fn new(name: impl Into, signature: PolyFuncType) -> Result { - let body = fix_sig(signature.body().clone())?; + pub fn new(name: impl Into, signature: PolyFixedFunc) -> Result { + let body = signature.body().clone(); let op = ops::FuncDefn { signature, name: name.into(), @@ -208,23 +208,17 @@ pub(crate) mod test { use serde_json::json; use crate::builder::build_traits::DataflowHugr; - use crate::builder::{BuilderWiringError, DataflowSubContainer, ModuleBuilder}; + use crate::builder::{BuildError, BuilderWiringError, DataflowSubContainer, ModuleBuilder}; use crate::extension::prelude::BOOL_T; - use crate::extension::{ExtensionId, EMPTY_REG}; + use crate::extension::{ExtensionId, ExtensionSet, EMPTY_REG}; use crate::hugr::validate::InterGraphEdgeError; use crate::ops::{handle::NodeHandle, LeafOp, OpTag}; + use crate::builder::test::{n_identity, BIT, NAT, QB}; use crate::std_extensions::logic::test::and_op; - use crate::types::{FunctionType, Type}; + use crate::types::Type; use crate::utils::test_quantum_extension::h_gate; - use crate::{ - builder::{ - test::{n_identity, BIT, NAT, QB}, - BuildError, - }, - extension::ExtensionSet, - type_row, Wire, - }; + use crate::{type_row, Wire}; use super::super::test::simple_dfg_hugr; use super::*; @@ -236,7 +230,7 @@ pub(crate) mod test { let _f_id = { let mut func_builder = module_builder.define_function( "main", - FunctionType::new(type_row![NAT, QB], type_row![NAT, QB]).into(), + Signature::new(type_row![NAT, QB], type_row![NAT, QB]), )?; let [int, qb] = func_builder.input_wires_arr(); @@ -270,7 +264,7 @@ pub(crate) mod test { let f_build = module_builder.define_function( "main", - FunctionType::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]).into(), + Signature::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]), )?; f(f_build)?; @@ -318,10 +312,8 @@ pub(crate) mod test { let builder = || { let mut module_builder = ModuleBuilder::new(); - let f_build = module_builder.define_function( - "main", - FunctionType::new(type_row![QB], type_row![QB, QB]).into(), - )?; + let f_build = module_builder + .define_function("main", Signature::new(type_row![QB], type_row![QB, QB]))?; let [q1] = f_build.input_wires_arr(); f_build.finish_with_outputs([q1, q1])?; @@ -344,7 +336,7 @@ pub(crate) mod test { let builder = || -> Result { let mut f_build = FunctionBuilder::new( "main", - FunctionType::new(type_row![BIT], type_row![BIT]).into(), + Signature::new(type_row![BIT], type_row![BIT]).into(), )?; let [i1] = f_build.input_wires_arr(); @@ -366,10 +358,8 @@ pub(crate) mod test { #[test] fn error_on_linear_inter_graph_edge() -> Result<(), BuildError> { - let mut f_build = FunctionBuilder::new( - "main", - FunctionType::new(type_row![QB], type_row![QB]).into(), - )?; + let mut f_build = + FunctionBuilder::new("main", Signature::new(type_row![QB], type_row![QB]).into())?; let [i1] = f_build.input_wires_arr(); let noop = f_build.add_dataflow_op(LeafOp::Noop { ty: QB }, [i1])?; @@ -411,10 +401,8 @@ pub(crate) mod test { let mut module_builder = ModuleBuilder::new(); let (dfg_node, f_node) = { - let mut f_build = module_builder.define_function( - "main", - FunctionType::new(type_row![BIT], type_row![BIT]).into(), - )?; + let mut f_build = module_builder + .define_function("main", Signature::new(type_row![BIT], type_row![BIT]))?; let [i1] = f_build.input_wires_arr(); let dfg = f_build.add_hugr_with_wires(dfg_hugr, [i1])?; diff --git a/quantinuum-hugr/src/builder/module.rs b/quantinuum-hugr/src/builder/module.rs index 61e5c91d6..f30e8690f 100644 --- a/quantinuum-hugr/src/builder/module.rs +++ b/quantinuum-hugr/src/builder/module.rs @@ -1,5 +1,5 @@ use super::{ - build_traits::{fix_sig, HugrBuilder}, + build_traits::HugrBuilder, dataflow::{DFGBuilder, FunctionBuilder}, BuildError, Container, }; @@ -8,7 +8,7 @@ use crate::{ extension::ExtensionRegistry, hugr::{hugrmut::sealed::HugrMutInternals, views::HugrView, ValidationError}, ops, - types::{PolyFuncType, Type, TypeBound}, + types::{PolyFixedFunc, Type, TypeBound}, }; use crate::ops::handle::{AliasID, FuncID, NodeHandle}; @@ -84,7 +84,7 @@ impl + AsRef> ModuleBuilder { op_desc: "crate::ops::OpType::FuncDecl", })? .clone(); - let body = fix_sig(signature.body().clone())?; + let body = signature.body().clone(); self.hugr_mut() .replace_op( f_node, @@ -105,7 +105,7 @@ impl + AsRef> ModuleBuilder { pub fn declare( &mut self, name: impl Into, - signature: PolyFuncType, + signature: PolyFixedFunc, ) -> Result, BuildError> { // TODO add param names to metadata let declare_n = self.add_child_node(NodeType::new_pure(ops::FuncDecl { @@ -171,7 +171,7 @@ mod test { }, extension::{EMPTY_REG, PRELUDE_REGISTRY}, type_row, - types::FunctionType, + types::Signature, }; use super::*; @@ -182,7 +182,7 @@ mod test { let f_id = module_builder.declare( "main", - FunctionType::new(type_row![NAT], type_row![NAT]).into(), + Signature::new(type_row![NAT], type_row![NAT]).into(), )?; let mut f_build = module_builder.define_declaration(&f_id)?; @@ -205,11 +205,10 @@ mod test { let f_build = module_builder.define_function( "main", - FunctionType::new( + Signature::new( vec![qubit_state_type.get_alias_type()], vec![qubit_state_type.get_alias_type()], - ) - .into(), + ), )?; n_identity(f_build)?; module_builder.finish_hugr(&EMPTY_REG) @@ -223,14 +222,10 @@ mod test { let build_result = { let mut module_builder = ModuleBuilder::new(); - let mut f_build = module_builder.define_function( - "main", - FunctionType::new(type_row![NAT], type_row![NAT, NAT]).into(), - )?; - let local_build = f_build.define_function( - "local", - FunctionType::new(type_row![NAT], type_row![NAT, NAT]).into(), - )?; + let mut f_build = module_builder + .define_function("main", Signature::new(type_row![NAT], type_row![NAT, NAT]))?; + let local_build = f_build + .define_function("local", Signature::new(type_row![NAT], type_row![NAT, NAT]))?; let [wire] = local_build.input_wires_arr(); let f_id = local_build.finish_with_outputs([wire, wire])?; diff --git a/quantinuum-hugr/src/builder/tail_loop.rs b/quantinuum-hugr/src/builder/tail_loop.rs index 485082f04..7c03a98d8 100644 --- a/quantinuum-hugr/src/builder/tail_loop.rs +++ b/quantinuum-hugr/src/builder/tail_loop.rs @@ -126,9 +126,7 @@ mod test { let mut module_builder = ModuleBuilder::new(); let mut fbuild = module_builder.define_function( "main", - Signature::new(type_row![BIT], type_row![NAT]) - .with_extension_delta(PRELUDE_ID) - .into(), + Signature::new(type_row![BIT], type_row![NAT]).with_extension_delta(PRELUDE_ID), )?; let _fdef = { let [b1] = fbuild diff --git a/quantinuum-hugr/src/extension/infer/test.rs b/quantinuum-hugr/src/extension/infer/test.rs index be6ae396e..178033963 100644 --- a/quantinuum-hugr/src/extension/infer/test.rs +++ b/quantinuum-hugr/src/extension/infer/test.rs @@ -938,9 +938,7 @@ fn simple_funcdefn() -> Result<(), Box> { let mut builder = ModuleBuilder::new(); let mut func_builder = builder.define_function( "F", - FunctionType::new(vec![NAT], vec![NAT]) - .with_extension_delta(A) - .into(), + Signature::new(vec![NAT], vec![NAT]).with_extension_delta(A), )?; let [w] = func_builder.input_wires_arr(); diff --git a/quantinuum-hugr/src/extension/op_def.rs b/quantinuum-hugr/src/extension/op_def.rs index 4d0130a24..04be17660 100644 --- a/quantinuum-hugr/src/extension/op_def.rs +++ b/quantinuum-hugr/src/extension/op_def.rs @@ -17,8 +17,8 @@ use crate::Hugr; /// Trait necessary for binary computations of OpDef signature pub trait CustomSignatureFunc: Send + Sync { - /// Compute signature of node given - /// values for the type parameters, + /// Compute type scheme (perhaps polymorphic over type and/or row variables) + /// given values for the static type parameters, /// the operation definition and the extension registry. fn compute_signature<'o, 'a: 'o>( &'a self, @@ -26,8 +26,9 @@ pub trait CustomSignatureFunc: Send + Sync { def: &'o OpDef, extension_registry: &ExtensionRegistry, ) -> Result; - /// The declared type parameters which require values in order for signature to - /// be computed. + /// The declared type parameters which for which closed values + /// (closed == without any free variables) + /// which must be provided in order for signature to be computed. fn static_params(&self) -> &[TypeParam]; } @@ -247,12 +248,16 @@ impl SignatureFunc { } }; - let res = pf.instantiate(args, exts)?; + // The first instantiate returns a FunctionType, i.e. expressed using 'RowVarOrType's. + // try_into removes possibility of containing any RowVars by expressing directly using 'Type's. + let res = pf + .instantiate(args, exts)? + .try_into() + .map_err(|(idx, bound)| SignatureError::ContainsRowVars { idx, bound })?; // TODO bring this assert back once resource inference is done? // https://github.com/CQCL/hugr/issues/388 // debug_assert!(res.extension_reqs.contains(def.extension())); - res.try_into() - .map_err(|(idx, bound)| SignatureError::ContainsRowVars { idx, bound }) + Ok(res) } } @@ -481,10 +486,8 @@ mod test { use crate::ops::custom::ExternalOp; use crate::ops::LeafOp; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; - use crate::types::Type; - use crate::types::{ - type_param::TypeParam, FunctionType, PolyFuncType, Signature, TypeArg, TypeBound, - }; + use crate::types::{type_param::TypeParam, FunctionType, Signature, TypeArg, TypeBound}; + use crate::types::{PolyFuncType, Type}; use crate::Hugr; use crate::{const_extension_ids, Extension}; diff --git a/quantinuum-hugr/src/extension/prelude.rs b/quantinuum-hugr/src/extension/prelude.rs index 025a94d9c..ad753582d 100644 --- a/quantinuum-hugr/src/extension/prelude.rs +++ b/quantinuum-hugr/src/extension/prelude.rs @@ -238,7 +238,7 @@ impl CustomConst for ConstError { mod test { use crate::{ builder::{DFGBuilder, Dataflow, DataflowHugr}, - types::{FunctionType, Signature}, + types::Signature, }; use super::*; diff --git a/quantinuum-hugr/src/hugr/hugrmut.rs b/quantinuum-hugr/src/hugr/hugrmut.rs index a0be5aade..865ea4ea1 100644 --- a/quantinuum-hugr/src/hugr/hugrmut.rs +++ b/quantinuum-hugr/src/hugr/hugrmut.rs @@ -677,7 +677,7 @@ mod test { extension::PRELUDE_REGISTRY, macros::type_row, ops::{self, dataflow::IOTrait, LeafOp}, - types::{FunctionType, Type}, + types::{Signature, Type}, }; use super::*; @@ -696,7 +696,7 @@ mod test { module, ops::FuncDefn { name: "main".into(), - signature: FunctionType::new(type_row![NAT], type_row![NAT, NAT]).into(), + signature: Signature::new(type_row![NAT], type_row![NAT, NAT]).into(), }, ); diff --git a/quantinuum-hugr/src/hugr/rewrite/consts.rs b/quantinuum-hugr/src/hugr/rewrite/consts.rs index 3fbd0aabd..dc01449f9 100644 --- a/quantinuum-hugr/src/hugr/rewrite/consts.rs +++ b/quantinuum-hugr/src/hugr/rewrite/consts.rs @@ -121,15 +121,14 @@ mod test { hugr::HugrMut, ops::{handle::NodeHandle, LeafOp}, type_row, - types::FunctionType, + types::Signature, }; #[test] fn test_const_remove() -> Result<(), Box> { let mut build = ModuleBuilder::new(); let con_node = build.add_constant(ConstUsize::new(2)); - let mut dfg_build = - build.define_function("main", FunctionType::new_endo(type_row![]).into())?; + let mut dfg_build = build.define_function("main", Signature::new_endo(type_row![]))?; let load_1 = dfg_build.load_const(&con_node); let load_2 = dfg_build.load_const(&con_node); let tup = dfg_build.add_dataflow_op( diff --git a/quantinuum-hugr/src/hugr/rewrite/outline_cfg.rs b/quantinuum-hugr/src/hugr/rewrite/outline_cfg.rs index 43f3b12f9..8559adf72 100644 --- a/quantinuum-hugr/src/hugr/rewrite/outline_cfg.rs +++ b/quantinuum-hugr/src/hugr/rewrite/outline_cfg.rs @@ -258,7 +258,7 @@ mod test { use crate::hugr::views::sibling::SiblingMut; use crate::hugr::HugrMut; use crate::ops::handle::{BasicBlockID, CfgID, NodeHandle}; - use crate::types::FunctionType; + use crate::types::Signature; use crate::{type_row, HugrView, Node}; use cool_asserts::assert_matches; use itertools::Itertools; @@ -351,7 +351,7 @@ mod test { let mut fbuild = module_builder .define_function( "main", - FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]).into(), + Signature::new(type_row![USIZE_T], type_row![USIZE_T]), ) .unwrap(); let [i1] = fbuild.input_wires_arr(); diff --git a/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs b/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs index 39e051ea2..5c1e1fd52 100644 --- a/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs +++ b/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs @@ -234,7 +234,7 @@ pub(in crate::hugr::rewrite) mod test { let _f_id = { let mut func_builder = module_builder.define_function( "main", - FunctionType::new(type_row![QB, QB, QB], type_row![QB, QB, QB]).into(), + Signature::new(type_row![QB, QB, QB], type_row![QB, QB, QB]), )?; let [qb0, qb1, qb2] = func_builder.input_wires_arr(); diff --git a/quantinuum-hugr/src/hugr/serialize.rs b/quantinuum-hugr/src/hugr/serialize.rs index 0844ee835..c3203f781 100644 --- a/quantinuum-hugr/src/hugr/serialize.rs +++ b/quantinuum-hugr/src/hugr/serialize.rs @@ -436,7 +436,7 @@ pub mod test { let t_row = vec![Type::new_sum([type_row![NAT], type_row![QB]])]; let mut f_build = module_builder - .define_function("main", FunctionType::new(t_row.clone(), t_row).into()) + .define_function("main", Signature::new(t_row.clone(), t_row)) .unwrap(); let outputs = f_build diff --git a/quantinuum-hugr/src/hugr/validate/test.rs b/quantinuum-hugr/src/hugr/validate/test.rs index 4ca5f3bb6..dcbfbbc52 100644 --- a/quantinuum-hugr/src/hugr/validate/test.rs +++ b/quantinuum-hugr/src/hugr/validate/test.rs @@ -15,8 +15,8 @@ use crate::ops::{self, Const, LeafOp, OpType}; use crate::std_extensions::logic::test::{and_op, or_op}; use crate::std_extensions::logic::{self, NotOp}; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; -use crate::types::type_row::{RowVarOrType, TypeRowV}; -use crate::types::{CustomType, FunctionType, PolyFuncType, Signature, Type, TypeBound, TypeRow}; +use crate::types::type_row::RowVarOrType; +use crate::types::{CustomType, FunctionType, PolyFixedFunc, Signature, Type, TypeBound, TypeRow}; use crate::{type_row, Direction, IncomingPort, Node}; const NAT: Type = crate::extension::prelude::USIZE_T; @@ -27,7 +27,7 @@ const NAT: Type = crate::extension::prelude::USIZE_T; fn make_simple_hugr(copies: usize) -> (Hugr, Node) { let def_op: OpType = ops::FuncDefn { name: "main".into(), - signature: FunctionType::new(type_row![BOOL_T], vec![BOOL_T; copies]).into(), + signature: Signature::new(type_row![BOOL_T], vec![BOOL_T; copies]).into(), } .into(); @@ -60,7 +60,7 @@ fn add_df_children(b: &mut Hugr, parent: Node, copies: usize) -> (Node, Node, No fn invalid_root() { let declare_op: OpType = ops::FuncDecl { name: "main".into(), - signature: Default::default(), + signature: Signature::default().into(), } .into(); @@ -130,7 +130,7 @@ fn children_restrictions() { .unwrap(); // Add a definition without children - let def_sig = FunctionType::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]); + let def_sig = Signature::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]); let new_def = b.add_node_with_parent( root, ops::FuncDefn { @@ -308,7 +308,7 @@ fn identity_hugr_with_type(t: Type) -> (Hugr, Node) { b.root(), ops::FuncDefn { name: "main".into(), - signature: FunctionType::new(row.clone(), row.clone()).into(), + signature: Signature::new(row.clone(), row.clone()).into(), }, ); @@ -427,9 +427,9 @@ fn typevars_declared() -> Result<(), Box> { // Base case let f = FunctionBuilder::new( "myfunc", - PolyFuncType::new( + PolyFixedFunc::new( [TypeBound::Any.into()], - FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + Signature::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; let [w] = f.input_wires_arr(); @@ -437,9 +437,9 @@ fn typevars_declared() -> Result<(), Box> { // Type refers to undeclared variable let f = FunctionBuilder::new( "myfunc", - PolyFuncType::new( + PolyFixedFunc::new( [TypeBound::Any.into()], - FunctionType::new_endo(vec![Type::new_var_use(1, TypeBound::Any)]), + Signature::new_endo(vec![Type::new_var_use(1, TypeBound::Any)]), ), )?; let [w] = f.input_wires_arr(); @@ -447,9 +447,9 @@ fn typevars_declared() -> Result<(), Box> { // Variable declaration incorrectly copied to use site let f = FunctionBuilder::new( "myfunc", - PolyFuncType::new( + PolyFixedFunc::new( [TypeBound::Any.into()], - FunctionType::new_endo(vec![Type::new_var_use(1, TypeBound::Copyable)]), + Signature::new_endo(vec![Type::new_var_use(1, TypeBound::Copyable)]), ), )?; let [w] = f.input_wires_arr(); @@ -465,14 +465,14 @@ fn nested_typevars() -> Result<(), Box> { fn build(t: Type) -> Result { let mut outer = FunctionBuilder::new( "outer", - PolyFuncType::new( + PolyFixedFunc::new( [OUTER_BOUND.into()], - FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + Signature::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; let inner = outer.define_function( "inner", - PolyFuncType::new([INNER_BOUND.into()], FunctionType::new_endo(vec![t])), + PolyFixedFunc::new([INNER_BOUND.into()], Signature::new_endo(vec![t])), )?; let [w] = inner.input_wires_arr(); inner.finish_with_outputs([w])?; @@ -511,9 +511,9 @@ fn no_polymorphic_consts() -> Result<(), Box> { let reg = ExtensionRegistry::try_new([collections::EXTENSION.to_owned()]).unwrap(); let mut def = FunctionBuilder::new( "myfunc", - PolyFuncType::new( + PolyFixedFunc::new( [BOUND], - FunctionType::new(TypeRowV::default(), vec![list_of_var.clone()]) + Signature::new(type_row![], vec![list_of_var.clone()]) .with_extension_delta(collections::EXTENSION_NAME), ), )?; @@ -542,11 +542,11 @@ fn inner_row_variables() -> Result<(), Box> { let inner_ft = Type::new_function(FunctionType::new_endo(vec![tv])); let mut fb = FunctionBuilder::new( "id", - PolyFuncType::new( + PolyFixedFunc::new( [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Any }), }], - FunctionType::new_endo(vec![inner_ft.clone()]), + Signature::new_endo(vec![inner_ft.clone()]), ), )?; // All the wires here are carrying higher-order Function values @@ -558,14 +558,14 @@ fn inner_row_variables() -> Result<(), Box> { #[test] fn no_outer_row_variables() -> Result<(), Box> { - let tv = RowVarOrType::RV(0, TypeBound::Any); + let tv = Type::new_var_use(0, TypeBound::Any); let fb = FunctionBuilder::new( "impossible_id_of_unknown_arity", - PolyFuncType::new( + PolyFixedFunc::new( [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Any }), }], - FunctionType::new_endo(vec![tv]), + Signature::new_endo(vec![tv]), ), )?; // Input and Output nodes have a Port whose type is List(Type(Any)) @@ -588,12 +588,12 @@ fn test_polymorphic_call() -> Result<(), Box> { let mut m = ModuleBuilder::new(); let id = m.declare( "id", - PolyFuncType::new( + PolyFixedFunc::new( vec![TypeBound::Any.into()], - FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + Signature::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; - let mut f = m.define_function("main", FunctionType::new_endo(vec![USIZE_T]).into())?; + let mut f = m.define_function("main", Signature::new_endo(vec![USIZE_T]))?; let c = f.call(&id, &[USIZE_T.into()], f.input_wires(), &PRELUDE_REGISTRY)?; f.finish_with_outputs(c.outputs())?; let _ = m.finish_prelude_hugr()?; diff --git a/quantinuum-hugr/src/hugr/views.rs b/quantinuum-hugr/src/hugr/views.rs index 7bcc80abd..bad59d3c6 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::{EdgeKind, Signature}; -use crate::types::{PolyFuncType, Type}; +use crate::types::Type; +use crate::types::{EdgeKind, PolyFixedFunc, Signature}; use crate::{Direction, IncomingPort, Node, OutgoingPort, Port}; use itertools::Either; @@ -343,20 +343,20 @@ pub trait HugrView: sealed::HugrInternals { /// 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. /// + /// For HUGRs with another [`DataflowParent`][crate::ops::DataflowParent] root + /// operation, report the signature of the inner dataflow sibling graph. + /// /// Otherwise, returns `None`. - fn get_function_type(&self) -> Option { + 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), + _ => op.inner_function_type().map(PolyFixedFunc::from), } } diff --git a/quantinuum-hugr/src/hugr/views/descendants.rs b/quantinuum-hugr/src/hugr/views/descendants.rs index 8aa05138f..6aa0b231e 100644 --- a/quantinuum-hugr/src/hugr/views/descendants.rs +++ b/quantinuum-hugr/src/hugr/views/descendants.rs @@ -203,7 +203,7 @@ pub(super) mod test { builder::{Container, Dataflow, DataflowSubContainer, HugrBuilder, ModuleBuilder}, ops::handle::NodeHandle, type_row, - types::{FunctionType, Signature, Type}, + types::{Signature, Type}, utils::test_quantum_extension::h_gate, }; @@ -222,7 +222,7 @@ pub(super) mod test { let (f_id, inner_id) = { let mut func_builder = module_builder.define_function( "main", - FunctionType::new(type_row![NAT, QB], type_row![NAT, QB]).into(), + Signature::new(type_row![NAT, QB], type_row![NAT, QB]), )?; let [int, qb] = func_builder.input_wires_arr(); @@ -261,12 +261,12 @@ pub(super) mod test { assert_eq!( region.get_function_type(), - Some(FunctionType::new_endo(type_row![NAT, QB]).into()) + Some(Signature::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]).into()) + Some(Signature::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 74bee860a..8f482e7b4 100644 --- a/quantinuum-hugr/src/hugr/views/sibling.rs +++ b/quantinuum-hugr/src/hugr/views/sibling.rs @@ -406,7 +406,7 @@ mod test { fn nested_flat() -> Result<(), Box> { let mut module_builder = ModuleBuilder::new(); let fty = Signature::new(type_row![NAT], type_row![NAT]); - let mut fbuild = module_builder.define_function("main", fty.clone().into())?; + let mut fbuild = module_builder.define_function("main", fty.clone())?; let dfg = fbuild.dfg_builder(fty, None, fbuild.input_wires())?; let ins = dfg.input_wires(); let sub_dfg = dfg.finish_with_outputs(ins)?; diff --git a/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs b/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs index a4c2f5484..7d6fc7e20 100644 --- a/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs +++ b/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs @@ -684,7 +684,6 @@ mod tests { use cool_asserts::assert_matches; use crate::extension::PRELUDE_REGISTRY; - use crate::types::FunctionType; use crate::utils::test_quantum_extension::cx_gate; use crate::{ builder::{ @@ -732,7 +731,7 @@ mod tests { let mut mod_builder = ModuleBuilder::new(); let func = mod_builder.declare( "test", - FunctionType::new_endo(type_row![QB_T, QB_T, QB_T]).into(), + Signature::new_endo(type_row![QB_T, QB_T, QB_T]).into(), )?; let func_id = { let mut dfg = mod_builder.define_declaration(&func)?; @@ -748,7 +747,7 @@ mod tests { fn build_3not_hugr() -> Result<(Hugr, Node), BuildError> { let mut mod_builder = ModuleBuilder::new(); - let func = mod_builder.declare("test", FunctionType::new_endo(type_row![BOOL_T]).into())?; + let func = mod_builder.declare("test", Signature::new_endo(type_row![BOOL_T]).into())?; let func_id = { let mut dfg = mod_builder.define_declaration(&func)?; let outs1 = dfg.add_dataflow_op(NotOp, dfg.input_wires())?; @@ -767,7 +766,7 @@ mod tests { let mut mod_builder = ModuleBuilder::new(); let func = mod_builder.declare( "test", - FunctionType::new(type_row![BOOL_T], type_row![BOOL_T]).into(), + Signature::new(type_row![BOOL_T], type_row![BOOL_T]).into(), )?; let func_id = { let mut dfg = mod_builder.define_declaration(&func)?; diff --git a/quantinuum-hugr/src/hugr/views/tests.rs b/quantinuum-hugr/src/hugr/views/tests.rs index 47e4868e6..4901f10cc 100644 --- a/quantinuum-hugr/src/hugr/views/tests.rs +++ b/quantinuum-hugr/src/hugr/views/tests.rs @@ -6,7 +6,7 @@ use crate::{ extension::prelude::QB_T, ops::handle::{DataflowOpID, NodeHandle}, type_row, - types::{FunctionType, Signature}, + types::Signature, utils::test_quantum_extension::cx_gate, Hugr, HugrView, }; @@ -178,7 +178,7 @@ fn test_dataflow_ports_only() { let local_and = dfg .define_function( "and", - FunctionType::new(type_row![BOOL_T; 2], type_row![BOOL_T]).into(), + Signature::new(type_row![BOOL_T; 2], type_row![BOOL_T]), ) .unwrap(); let first_input = local_and.input().out_wire(0); diff --git a/quantinuum-hugr/src/ops/dataflow.rs b/quantinuum-hugr/src/ops/dataflow.rs index 790074f50..41f923f91 100644 --- a/quantinuum-hugr/src/ops/dataflow.rs +++ b/quantinuum-hugr/src/ops/dataflow.rs @@ -4,7 +4,7 @@ use super::{impl_op_name, OpTag, OpTrait}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::ops::StaticTag; -use crate::types::{EdgeKind, Signature, PolyFuncType, Type, TypeArg, TypeRow}; +use crate::types::{EdgeKind, PolyFixedFunc, PolyFuncType, Signature, Type, TypeArg, TypeRow}; use crate::IncomingPort; pub(crate) trait DataflowOpTrait { @@ -153,7 +153,7 @@ impl StaticTag for T { #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Call { /// Signature of function being called - func_sig: PolyFuncType, + func_sig: PolyFixedFunc, type_args: Vec, instantiation: Signature, // Cache, so we can fail in try_new() not in signature() } @@ -181,14 +181,12 @@ impl Call { /// /// [TypeParam]: crate::types::type_param::TypeParam pub fn try_new( - func_sig: PolyFuncType, + func_sig: PolyFixedFunc, type_args: impl Into>, exts: &ExtensionRegistry, ) -> Result { let type_args = type_args.into(); - let instantiation = func_sig.instantiate(&type_args, exts)? - .try_into() - .map_err(|(idx, _)|SignatureError::RowTypeVarOutsideRow { idx })?; + let instantiation = func_sig.instantiate(&type_args, exts)?; Ok(Self { func_sig, type_args, @@ -198,7 +196,7 @@ impl Call { #[inline] /// Return the signature of the function called by this op. - pub fn called_function_type(&self) -> &PolyFuncType { + pub fn called_function_type(&self) -> &PolyFixedFunc { &self.func_sig } @@ -246,9 +244,10 @@ impl DataflowOpTrait for CallIndirect { fn signature(&self) -> Signature { let mut s = self.signature.clone(); - s.input - .to_mut() - .insert(0, Type::new_function(self.signature.clone())); + s.input.to_mut().insert( + 0, + Type::new_function(PolyFixedFunc::from(self.signature.clone())), + ); s } } diff --git a/quantinuum-hugr/src/ops/module.rs b/quantinuum-hugr/src/ops/module.rs index eaf52ce27..742518b18 100644 --- a/quantinuum-hugr/src/ops/module.rs +++ b/quantinuum-hugr/src/ops/module.rs @@ -2,7 +2,7 @@ use smol_str::SmolStr; -use crate::types::{EdgeKind, PolyFuncType, Signature}; +use crate::types::{EdgeKind, PolyFixedFunc, Signature}; use crate::types::{Type, TypeBound}; use super::dataflow::DataflowParent; @@ -37,7 +37,7 @@ pub struct FuncDefn { /// Name of function pub name: String, /// Signature of the function - pub signature: PolyFuncType, + pub signature: PolyFixedFunc, } impl_op_name!(FuncDefn); @@ -71,7 +71,7 @@ pub struct FuncDecl { /// Name of function pub name: String, /// Signature of the function - pub signature: PolyFuncType, + pub signature: PolyFixedFunc, } impl_op_name!(FuncDecl); diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index fbcf946df..2f9ce2aa2 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -12,7 +12,7 @@ pub use crate::ops::constant::{ConstTypeError, CustomCheckFailure}; use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; -pub use poly_func::PolyFuncType; +pub use poly_func::{PolyFixedFunc, PolyFuncType}; pub use signature::{FunctionType, Signature}; use smol_str::SmolStr; pub use type_param::TypeArg; diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index 624f000f4..bf9e86310 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -7,10 +7,12 @@ use crate::{ use itertools::Itertools; use super::{ + signature::FuncTypeBase, type_param::{check_type_args, TypeArg, TypeParam}, type_row::RowVarOrType, + Type, }; -use super::{FunctionType, Signature, Substitution, TypeBound}; +use super::{FunctionType, Substitution, TypeBound}; /// A polymorphic function type, e.g. of a [Graph], or perhaps an [OpDef]. /// (Nodes/operations in the Hugr are not polymorphic.) @@ -25,7 +27,11 @@ use super::{FunctionType, Signature, Substitution, TypeBound}; "params.iter().map(ToString::to_string).join(\" \")", "body" )] -pub struct PolyFuncType { +pub struct PolyFuncBase +where + T: 'static, + [T]: ToOwned>, +{ /// The declared type parameters, i.e., these must be instantiated with /// the same number of [TypeArg]s before the function can be called. Note that within /// the [Self::body], variable (DeBruijn) index 0 is element 0 of this array, i.e. the @@ -34,11 +40,16 @@ pub struct PolyFuncType { /// [TypeArg]: super::type_param::TypeArg params: Vec, /// Template for the function. May contain variables up to length of [Self::params] - body: FunctionType, + body: FuncTypeBase, } - -impl From for PolyFuncType { - fn from(body: FunctionType) -> Self { +pub type PolyFuncType = PolyFuncBase; +pub type PolyFixedFunc = PolyFuncBase; + +impl From> for PolyFuncBase +where + [T]: ToOwned>, +{ + fn from(body: FuncTypeBase) -> Self { Self { params: vec![], body, @@ -46,29 +57,35 @@ impl From for PolyFuncType { } } -impl From for PolyFuncType { - fn from(value: Signature) -> Self { - FunctionType::from(value).into() +impl From for PolyFuncType { + fn from(value: PolyFixedFunc) -> Self { + Self { + params: value.params, + body: value.body.into(), + } } } -impl PolyFuncType { +impl PolyFuncBase +where + [T]: ToOwned>, +{ /// The type parameters, aka binders, over which this type is polymorphic pub fn params(&self) -> &[TypeParam] { &self.params } /// The body of the type, a function type. - pub fn body(&self) -> &FunctionType { + pub fn body(&self) -> &FuncTypeBase { &self.body } - /// Create a new PolyFuncType given the kinds of the variables it declares + /// Create a new PolyFuncBase given the kinds of the variables it declares /// and the underlying [FunctionType]. - pub fn new(params: impl Into>, body: FunctionType) -> Self { + pub fn new(params: impl Into>, body: impl Into>) -> Self { Self { params: params.into(), - body, + body: body.into(), } } @@ -98,7 +115,7 @@ impl PolyFuncType { // Avoid using complex code for simple Monomorphic case return self.body.substitute(t).into(); } - PolyFuncType { + PolyFuncBase { params: self.params.clone(), body: self.body.substitute(&InsideBinders { num_binders: self.params.len(), @@ -107,7 +124,7 @@ impl PolyFuncType { } } - /// (Perhaps-partially) instantiates this [PolyFuncType] into another with fewer binders. + /// (Perhaps-partially) instantiates this [PolyFuncBase] into another with fewer binders. /// Note that indices into `args` correspond to the same index within [Self::params], /// so we instantiate the lowest-index [Self::params] first, even though these /// would be considered "innermost" / "closest" according to DeBruijn numbering. @@ -137,7 +154,7 @@ impl PolyFuncType { }) } - /// Instantiates an outer [PolyFuncType], i.e. with no free variables + /// Instantiates an outer [PolyFuncBase], i.e. with no free variables /// (as ensured by [Self::validate]), into a monomorphic type. /// /// # Errors @@ -147,7 +164,7 @@ impl PolyFuncType { &self, args: &[TypeArg], ext_reg: &ExtensionRegistry, - ) -> Result { + ) -> Result, SignatureError> { // Check that args are applicable, and that we have a value for each binder, // i.e. each possible free variable within the body. check_type_args(args, &self.params)?; @@ -209,7 +226,7 @@ impl<'a> Substitution for Renumber<'a> { } } -/// Given a [Substitution] defined outside a binder (i.e. [PolyFuncType]), +/// Given a [Substitution] defined outside a binder (i.e. [PolyFuncBase]), /// applies that transformer to types inside the binder (i.e. arguments/results of said function) struct InsideBinders<'a> { /// The number of binders we have entered since (beneath where) we started to apply @@ -253,22 +270,26 @@ pub(crate) mod test { ExtensionId, ExtensionRegistry, SignatureError, TypeDefBound, PRELUDE, PRELUDE_REGISTRY, }; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; + use crate::types::signature::FuncTypeBase; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; - use crate::types::type_row::{RowVarOrType, TypeRowV}; - use crate::types::{CustomType, FunctionType, Type, TypeBound}; + use crate::types::type_row::RowVarOrType; + use crate::types::{CustomType, FunctionType, PolyFuncType, Type, TypeBound}; use crate::Extension; - use super::PolyFuncType; + use super::PolyFuncBase; lazy_static! { static ref REGISTRY: ExtensionRegistry = ExtensionRegistry::try_new([PRELUDE.to_owned(), EXTENSION.to_owned()]).unwrap(); } - impl PolyFuncType { + impl PolyFuncBase + where + [T]: ToOwned>, + { fn new_validated( params: impl Into>, - body: FunctionType, + body: FuncTypeBase, extension_registry: &ExtensionRegistry, ) -> Result { let res = Self::new(params, body); @@ -282,7 +303,7 @@ pub(crate) mod test { let list_def = EXTENSION.get_type(&LIST_TYPENAME).unwrap(); let tyvar = TypeArg::new_var_use(0, TypeBound::Any.into()); let list_of_var = Type::new_extension(list_def.instantiate([tyvar.clone()])?); - let list_len = PolyFuncType::new_validated( + let list_len = PolyFuncBase::new_validated( [TypeBound::Any.into()], FunctionType::new(vec![list_of_var], vec![USIZE_T]), ®ISTRY, @@ -318,7 +339,7 @@ pub(crate) mod test { // Valid schema... let good_array = Type::new_extension(ar_def.instantiate([tyvar.clone(), szvar.clone()])?); let good_ts = - PolyFuncType::new_validated(typarams.clone(), id_fn(good_array), &PRELUDE_REGISTRY)?; + PolyFuncBase::new_validated(typarams.clone(), id_fn(good_array), &PRELUDE_REGISTRY)?; // Sanity check (good args) good_ts.instantiate( @@ -357,7 +378,7 @@ pub(crate) mod test { TypeBound::Any, )); let bad_ts = - PolyFuncType::new_validated(typarams.clone(), id_fn(bad_array), &PRELUDE_REGISTRY); + PolyFuncBase::new_validated(typarams.clone(), id_fn(bad_array), &PRELUDE_REGISTRY); assert_eq!(bad_ts.err(), Some(arg_err)); Ok(()) @@ -380,7 +401,7 @@ pub(crate) mod test { }, ] { let invalid_ts = - PolyFuncType::new_validated([decl.clone()], body_type.clone(), ®ISTRY); + PolyFuncBase::new_validated([decl.clone()], body_type.clone(), ®ISTRY); assert_eq!( invalid_ts.err(), Some(SignatureError::TypeVarDoesNotMatchDeclaration { @@ -390,7 +411,7 @@ pub(crate) mod test { ); } // Variable not declared at all - let invalid_ts = PolyFuncType::new_validated([], body_type, ®ISTRY); + let invalid_ts = PolyFuncBase::new_validated([], body_type, ®ISTRY); assert_eq!( invalid_ts.err(), Some(SignatureError::FreeTypeVar { @@ -422,7 +443,7 @@ pub(crate) mod test { let reg = ExtensionRegistry::try_new([e]).unwrap(); let make_scheme = |tp: TypeParam| { - PolyFuncType::new_validated( + PolyFuncBase::new_validated( [tp.clone()], id_fn(Type::new_extension(CustomType::new( TYPE_NAME, @@ -492,7 +513,7 @@ pub(crate) mod test { #[test] fn partial_instantiate() -> Result<(), SignatureError> { // forall A,N.(Array -> A) - let array_max = PolyFuncType::new_validated( + let array_max = PolyFuncBase::new_validated( vec![TypeBound::Any.into(), TypeParam::max_nat()], FunctionType::new( vec![array_type( @@ -514,7 +535,7 @@ pub(crate) mod test { assert_eq!(actual, concrete.into()); // forall N.(Array -> usize) - let partial = PolyFuncType::new_validated( + let partial = PolyFuncBase::new_validated( vec![TypeParam::max_nat()], FunctionType::new( vec![array_type( @@ -544,7 +565,7 @@ pub(crate) mod test { // forall A. A -> (forall C. C -> List(Tuple(C, A)) pub(crate) fn nested_func() -> PolyFuncType { - PolyFuncType::new_validated( + PolyFuncBase::new_validated( vec![TypeBound::Any.into()], FunctionType::new( vec![Type::new_var_use(0, TypeBound::Any)], @@ -651,7 +672,7 @@ pub(crate) mod test { fn row_variables() { const TP: TypeParam = TypeParam::Type { b: TypeBound::Any }; // Mismatched TypeBound (Copyable vs Any) - PolyFuncType::new_validated( + PolyFuncBase::new_validated( [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Copyable, @@ -665,7 +686,7 @@ pub(crate) mod test { ) .unwrap_err(); - let pf = PolyFuncType::new_validated( + let pf = PolyFuncBase::new_validated( [TypeParam::List { param: Box::new(TP), }], @@ -708,7 +729,7 @@ pub(crate) mod test { 0, TypeBound::Copyable, )])); - let pf = PolyFuncType::new_validated( + let pf = PolyFuncBase::new_validated( [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Copyable, From 446640d105c613f89fdd66e59e8abb1fa8d58203 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 27 Mar 2024 18:28:48 +0000 Subject: [PATCH 41/57] Add trait TypeRowElem w/ subst_row, validate - maybe in wrong place --- quantinuum-hugr/src/builder/build_traits.rs | 2 +- quantinuum-hugr/src/builder/dataflow.rs | 2 +- quantinuum-hugr/src/extension/infer/test.rs | 2 +- .../src/hugr/rewrite/simple_replace.rs | 2 +- quantinuum-hugr/src/hugr/serialize.rs | 2 +- quantinuum-hugr/src/ops/dataflow.rs | 2 +- quantinuum-hugr/src/types.rs | 42 +--------- quantinuum-hugr/src/types/poly_func.rs | 16 ++-- quantinuum-hugr/src/types/signature.rs | 84 ++++++++++++++++--- quantinuum-hugr/src/types/type_row.rs | 6 +- 10 files changed, 92 insertions(+), 68 deletions(-) diff --git a/quantinuum-hugr/src/builder/build_traits.rs b/quantinuum-hugr/src/builder/build_traits.rs index 950385684..3f89b66cf 100644 --- a/quantinuum-hugr/src/builder/build_traits.rs +++ b/quantinuum-hugr/src/builder/build_traits.rs @@ -19,7 +19,7 @@ use crate::{ types::EdgeKind, }; -use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError, PRELUDE_REGISTRY}; +use crate::extension::{ExtensionRegistry, ExtensionSet, PRELUDE_REGISTRY}; use crate::types::{PolyFixedFunc, Signature, Type, TypeArg, TypeRow}; use itertools::Itertools; diff --git a/quantinuum-hugr/src/builder/dataflow.rs b/quantinuum-hugr/src/builder/dataflow.rs index fedf2cde1..3c4219e4d 100644 --- a/quantinuum-hugr/src/builder/dataflow.rs +++ b/quantinuum-hugr/src/builder/dataflow.rs @@ -56,7 +56,7 @@ impl + AsRef> DFGBuilder { parent, NodeType::new( output, - input_extensions.map(|inp| inp.union(signature.extension_reqs)), + input_extensions.map(|inp| inp.union(extension_reqs)), ), ); diff --git a/quantinuum-hugr/src/extension/infer/test.rs b/quantinuum-hugr/src/extension/infer/test.rs index 178033963..13d7d7e79 100644 --- a/quantinuum-hugr/src/extension/infer/test.rs +++ b/quantinuum-hugr/src/extension/infer/test.rs @@ -21,7 +21,7 @@ use crate::{ }; use crate::type_row; -use crate::types::{FunctionType, Signature, Type, TypeRow}; +use crate::types::{Signature, Type, TypeRow}; use cool_asserts::assert_matches; use itertools::Itertools; diff --git a/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs b/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs index 5c1e1fd52..26cc1f5c3 100644 --- a/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs +++ b/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs @@ -212,7 +212,7 @@ pub(in crate::hugr::rewrite) mod test { use crate::ops::{OpTrait, OpType}; use crate::std_extensions::logic::test::and_op; use crate::type_row; - use crate::types::{FunctionType, Signature, Type}; + use crate::types::{Signature, Type}; use crate::utils::test_quantum_extension::{cx_gate, h_gate}; use crate::{IncomingPort, Node}; diff --git a/quantinuum-hugr/src/hugr/serialize.rs b/quantinuum-hugr/src/hugr/serialize.rs index c3203f781..d87d9e27f 100644 --- a/quantinuum-hugr/src/hugr/serialize.rs +++ b/quantinuum-hugr/src/hugr/serialize.rs @@ -267,7 +267,7 @@ pub mod test { use crate::std_extensions::arithmetic::float_ops::FLOAT_OPS_REGISTRY; use crate::std_extensions::arithmetic::float_types::{ConstF64, FLOAT64_TYPE}; use crate::std_extensions::logic::NotOp; - use crate::types::{FunctionType, Signature, Type}; + use crate::types::{Signature, Type}; use crate::{type_row, OutgoingPort}; use itertools::Itertools; use jsonschema::{Draft, JSONSchema}; diff --git a/quantinuum-hugr/src/ops/dataflow.rs b/quantinuum-hugr/src/ops/dataflow.rs index 41f923f91..3f4be1272 100644 --- a/quantinuum-hugr/src/ops/dataflow.rs +++ b/quantinuum-hugr/src/ops/dataflow.rs @@ -4,7 +4,7 @@ use super::{impl_op_name, OpTag, OpTrait}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::ops::StaticTag; -use crate::types::{EdgeKind, PolyFixedFunc, PolyFuncType, Signature, Type, TypeArg, TypeRow}; +use crate::types::{EdgeKind, PolyFixedFunc, Signature, Type, TypeArg, TypeRow}; use crate::IncomingPort; pub(crate) trait DataflowOpTrait { diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index 2f9ce2aa2..b01313272 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -27,6 +27,7 @@ use crate::ops::AliasDecl; use crate::type_row; use std::fmt::Debug; +use self::signature::TypeRowElem; use self::type_param::TypeParam; use self::type_row::{RowVarOrType, TypeRowV}; @@ -246,14 +247,6 @@ impl TypeEnum { /// pub struct Type(TypeEnum, TypeBound); -fn validate_each<'a>( - extension_registry: &ExtensionRegistry, - var_decls: &[TypeParam], - mut iter: impl Iterator, -) -> Result<(), SignatureError> { - iter.try_for_each(|t| t.validate(extension_registry, var_decls)) -} - impl Type { /// An empty `TypeRow`. Provided here for convenience pub const EMPTY_TYPEROW: TypeRow = type_row![]; @@ -352,7 +345,8 @@ impl Type { match &self.0 { TypeEnum::Sum(SumType::General { rows }) => rows .iter() - .try_for_each(|row| valid_row(row, extension_registry, var_decls)), + .flat_map(TypeRowV::iter) + .try_for_each(|rvt| rvt.validate(extension_registry, var_decls)), TypeEnum::Sum(SumType::Unit { .. }) => Ok(()), // No leaves there TypeEnum::Alias(_) => Ok(()), TypeEnum::Extension(custy) => custy.validate(extension_registry, var_decls), @@ -368,7 +362,7 @@ impl Type { TypeEnum::Extension(cty) => Type::new_extension(cty.substitute(t)), TypeEnum::Function(bf) => Type::new_function(bf.substitute(t)), TypeEnum::Sum(SumType::General { rows }) => { - Type::new_sum(rows.iter().map(|x| subst_row(x, t))) + Type::new_sum(rows.iter().map(|x| TypeRowElem::subst_row(x, t))) } } } @@ -397,34 +391,6 @@ pub(crate) trait Substitution { fn extension_registry(&self) -> &ExtensionRegistry; } -fn valid_row( - row: &TypeRowV, - exts: &ExtensionRegistry, - var_decls: &[TypeParam], -) -> Result<(), SignatureError> { - row.iter().try_for_each(|t| match t { - RowVarOrType::T(t) => t.validate(exts, var_decls), - RowVarOrType::RV(idx, bound) => { - let t = TypeParam::List { - param: Box::new((*bound).into()), - }; - check_typevar_decl(var_decls, *idx, &t) - } - }) -} - -fn subst_row(row: &TypeRowV, tr: &impl Substitution) -> TypeRowV { - let res = row - .iter() - .flat_map(|ty| match ty { - RowVarOrType::RV(idx, bound) => tr.apply_rowvar(*idx, *bound), - RowVarOrType::T(t) => vec![RowVarOrType::T(t.substitute(tr))], - }) - .collect::>() - .into(); - res -} - pub(crate) fn check_typevar_decl( decls: &[TypeParam], idx: usize, diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index bf9e86310..137422684 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -7,12 +7,12 @@ use crate::{ use itertools::Itertools; use super::{ - signature::FuncTypeBase, + signature::{FuncTypeBase, TypeRowElem}, type_param::{check_type_args, TypeArg, TypeParam}, type_row::RowVarOrType, Type, }; -use super::{FunctionType, Substitution, TypeBound}; +use super::{Substitution, TypeBound}; /// A polymorphic function type, e.g. of a [Graph], or perhaps an [OpDef]. /// (Nodes/operations in the Hugr are not polymorphic.) @@ -29,7 +29,7 @@ use super::{FunctionType, Substitution, TypeBound}; )] pub struct PolyFuncBase where - T: 'static, + T: TypeRowElem, [T]: ToOwned>, { /// The declared type parameters, i.e., these must be instantiated with @@ -45,7 +45,7 @@ where pub type PolyFuncType = PolyFuncBase; pub type PolyFixedFunc = PolyFuncBase; -impl From> for PolyFuncBase +impl From> for PolyFuncBase where [T]: ToOwned>, { @@ -66,7 +66,7 @@ impl From for PolyFuncType { } } -impl PolyFuncBase +impl PolyFuncBase where [T]: ToOwned>, { @@ -186,7 +186,7 @@ impl<'a> Substitution for SubstValues<'a> { arg.clone() } - fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { + fn apply_rowvar(&self, idx: usize, _bound: TypeBound) -> Vec { let arg = self .0 .get(idx) @@ -276,14 +276,14 @@ pub(crate) mod test { use crate::types::{CustomType, FunctionType, PolyFuncType, Type, TypeBound}; use crate::Extension; - use super::PolyFuncBase; + use super::{PolyFuncBase, TypeRowElem}; lazy_static! { static ref REGISTRY: ExtensionRegistry = ExtensionRegistry::try_new([PRELUDE.to_owned(), EXTENSION.to_owned()]).unwrap(); } - impl PolyFuncBase + impl PolyFuncBase where [T]: ToOwned>, { diff --git a/quantinuum-hugr/src/types/signature.rs b/quantinuum-hugr/src/types/signature.rs index 0a7d6fb15..ff70c2a1c 100644 --- a/quantinuum-hugr/src/types/signature.rs +++ b/quantinuum-hugr/src/types/signature.rs @@ -6,7 +6,7 @@ use std::fmt::{self, Display, Write}; use super::type_param::TypeParam; use super::type_row::{RowVarOrType, TypeRowBase}; -use super::{subst_row, valid_row, Substitution, Type, TypeBound, TypeRowV}; +use super::{check_typevar_decl, Substitution, Type, TypeBound}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::{Direction, IncomingPort, OutgoingPort, Port}; @@ -16,7 +16,7 @@ use crate::{Direction, IncomingPort, OutgoingPort, Port}; /// and also the target (value) of a call (static). pub struct FuncTypeBase where - T: 'static, + T: TypeRowElem, [T]: ToOwned>, { /// Value inputs of the function. @@ -27,9 +27,22 @@ where pub extension_reqs: ExtensionSet, } +pub(super) trait TypeRowElem: 'static + Sized + Clone +where + [Self]: ToOwned>, +{ + fn validate( + &self, + extension_registry: &ExtensionRegistry, + var_decls: &[TypeParam], + ) -> Result<(), SignatureError>; + + fn subst_row(row: &TypeRowBase, tr: &impl Substitution) -> TypeRowBase; +} + impl Default for FuncTypeBase where - T: 'static, + T: TypeRowElem, [T]: ToOwned>, { fn default() -> Self { @@ -44,12 +57,57 @@ where /// The type of a function, e.g. passing around a pointer/static ref to it. pub type FunctionType = FuncTypeBase; +impl TypeRowElem for RowVarOrType { + fn validate( + &self, + extension_registry: &ExtensionRegistry, + var_decls: &[TypeParam], + ) -> Result<(), SignatureError> { + match self { + RowVarOrType::T(t) => t.validate(extension_registry, var_decls), + RowVarOrType::RV(idx, bound) => { + let t = TypeParam::List { + param: Box::new((*bound).into()), + }; + check_typevar_decl(var_decls, *idx, &t) + } + } + } + + fn subst_row(row: &TypeRowBase, tr: &impl Substitution) -> TypeRowBase { + row.iter() + .flat_map(|ty| match ty { + RowVarOrType::RV(idx, bound) => tr.apply_rowvar(*idx, *bound), + RowVarOrType::T(t) => vec![RowVarOrType::T(t.substitute(tr))], + }) + .collect::>() + .into() + } +} + /// The type of a node. Fixed/known arity of inputs + outputs. pub type Signature = FuncTypeBase; +impl TypeRowElem for Type { + fn validate( + &self, + extension_registry: &ExtensionRegistry, + var_decls: &[TypeParam], + ) -> Result<(), SignatureError> { + self.validate(extension_registry, var_decls) + } + + fn subst_row(row: &TypeRowBase, tr: &impl Substitution) -> TypeRowBase { + row.iter() + .map(|t| t.substitute(tr)) + .collect::>() + .into() + } +} + impl FuncTypeBase where - T: 'static + Clone, + T: TypeRowElem, [T]: ToOwned>, { /// Builder method, add extension_reqs to an FunctionType @@ -72,36 +130,36 @@ where let linear = linear.into(); Self::new(linear.clone(), linear) } -} -impl FunctionType { pub(crate) fn validate( &self, extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - valid_row(&self.input, extension_registry, var_decls)?; - valid_row(&self.output, extension_registry, var_decls)?; + self.input + .iter() + .chain(self.output.iter()) + .try_for_each(|e| e.validate(extension_registry, var_decls))?; self.extension_reqs.validate(var_decls) } pub(crate) fn substitute(&self, tr: &impl Substitution) -> Self { Self { - input: subst_row(&self.input, tr), - output: subst_row(&self.output, tr), + input: TypeRowElem::subst_row(&self.input, tr), + output: TypeRowElem::subst_row(&self.output, tr), extension_reqs: self.extension_reqs.substitute(tr), } } #[inline] /// Returns the input row - pub fn input(&self) -> &TypeRowV { + pub fn input(&self) -> &TypeRowBase { &self.input } #[inline] /// Returns the output row - pub fn output(&self) -> &TypeRowV { + pub fn output(&self) -> &TypeRowBase { &self.output } } @@ -248,7 +306,7 @@ impl TryFrom for Signature { } } -impl Display for FuncTypeBase +impl Display for FuncTypeBase where [T]: ToOwned>, { diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index 1f090fbc0..3c4cd138c 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -156,9 +156,9 @@ where } } -impl Into> for TypeRow { - fn into(self) -> Cow<'static, [RowVarOrType]> { - self.types +impl From for Cow<'static, [RowVarOrType]> { + fn from(val: TypeRow) -> Self { + val.types .into_owned() .into_iter() .map(RowVarOrType::from) From 699e44ba60d61cfd3d563fe5406fe828d13c9f59 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 2 Apr 2024 09:22:32 +0100 Subject: [PATCH 42/57] Fix row variables - var cannot range over unknown #variants of a Sum type --- quantinuum-hugr/benches/benchmarks/hugr.rs | 8 ++++---- quantinuum-hugr/benches/benchmarks/types.rs | 2 +- quantinuum-hugr/src/types/poly_func.rs | 7 +++++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/quantinuum-hugr/benches/benchmarks/hugr.rs b/quantinuum-hugr/benches/benchmarks/hugr.rs index 7da7b4c12..a8ad110cb 100644 --- a/quantinuum-hugr/benches/benchmarks/hugr.rs +++ b/quantinuum-hugr/benches/benchmarks/hugr.rs @@ -4,12 +4,12 @@ use criterion::{black_box, criterion_group, AxisScale, Criterion, PlotConfigurat use hugr::builder::{BuildError, CFGBuilder, DFGBuilder, Dataflow, DataflowHugr, HugrBuilder}; use hugr::extension::prelude::{BOOL_T, USIZE_T}; use hugr::extension::ExtensionSet; -use hugr::types::FunctionType; +use hugr::types::Signature; use hugr::{type_row, Hugr}; pub fn simple_dfg_hugr() -> Hugr { let dfg_builder = - DFGBuilder::new(FunctionType::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap(); + DFGBuilder::new(Signature::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap(); let [i1] = dfg_builder.input_wires_arr(); dfg_builder.finish_prelude_hugr_with_outputs([i1]).unwrap() } @@ -27,7 +27,7 @@ pub fn simple_cfg_builder + AsRef>( entry_b.finish_with_outputs(sum, [])? }; let mut middle_b = cfg_builder - .simple_block_builder(FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]), 1)?; + .simple_block_builder(Signature::new(type_row![USIZE_T], type_row![USIZE_T]), 1)?; let middle = { let c = middle_b.add_load_const(hugr::ops::Const::unary_unit_sum()); let [inw] = middle_b.input_wires_arr(); @@ -42,7 +42,7 @@ pub fn simple_cfg_builder + AsRef>( pub fn simple_cfg_hugr() -> Hugr { let mut cfg_builder = - CFGBuilder::new(FunctionType::new(type_row![USIZE_T], type_row![USIZE_T])).unwrap(); + CFGBuilder::new(Signature::new(type_row![USIZE_T], type_row![USIZE_T])).unwrap(); simple_cfg_builder(&mut cfg_builder).unwrap(); cfg_builder.finish_prelude_hugr().unwrap() } diff --git a/quantinuum-hugr/benches/benchmarks/types.rs b/quantinuum-hugr/benches/benchmarks/types.rs index 3b599983c..b391f1133 100644 --- a/quantinuum-hugr/benches/benchmarks/types.rs +++ b/quantinuum-hugr/benches/benchmarks/types.rs @@ -13,7 +13,7 @@ fn make_complex_type() -> Type { let q_register = Type::new_tuple(vec![qb; 8]); let b_register = Type::new_tuple(vec![int; 8]); let q_alias = Type::new_alias(AliasDecl::new("QReg", TypeBound::Any)); - let sum = Type::new_sum([vec![q_register].into(), vec![q_alias].into()]); + let sum = Type::new_sum([vec![q_register], vec![q_alias]]); Type::new_function(FunctionType::new(vec![sum], vec![b_register])) } diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index 137422684..b0ac0a89e 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -692,7 +692,7 @@ pub(crate) mod test { }], FunctionType::new( vec![USIZE_T.into(), RowVarOrType::RV(0, TypeBound::Any)], - vec![Type::new_sum(vec![RowVarOrType::RV(0, TypeBound::Any)])], + vec![Type::new_tuple(RowVarOrType::RV(0, TypeBound::Any))], ), &PRELUDE_REGISTRY, ) @@ -718,7 +718,10 @@ pub(crate) mod test { t2, FunctionType::new( vec![USIZE_T, USIZE_T, BOOL_T], - vec![Type::new_sum(vec![RowVarOrType::T(USIZE_T), BOOL_T.into()])] + vec![Type::new_tuple(vec![ + RowVarOrType::T(USIZE_T), + BOOL_T.into() + ])] ) ); } From 63a0b991e258ef7b8cb4b0acecc09e5548e94c7e Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 2 Apr 2024 09:23:55 +0100 Subject: [PATCH 43/57] Rename: TypeRowV -> TypeRowVarLen --- .../src/extension/declarative/signature.rs | 4 ++-- quantinuum-hugr/src/types.rs | 24 +++++++++---------- quantinuum-hugr/src/types/type_row.rs | 6 ++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/quantinuum-hugr/src/extension/declarative/signature.rs b/quantinuum-hugr/src/extension/declarative/signature.rs index 3e746b33e..9a32024ea 100644 --- a/quantinuum-hugr/src/extension/declarative/signature.rs +++ b/quantinuum-hugr/src/extension/declarative/signature.rs @@ -14,7 +14,7 @@ use smol_str::SmolStr; use crate::extension::prelude::PRELUDE_ID; use crate::extension::{CustomValidator, ExtensionSet, SignatureFunc, TypeDef, TypeParametrised}; use crate::types::type_param::TypeParam; -use crate::types::type_row::TypeRowV; +use crate::types::type_row::TypeRowVarLen; use crate::types::{CustomType, FunctionType, PolyFuncType, Type}; use crate::Extension; @@ -42,7 +42,7 @@ impl SignatureDeclaration { op_params: &[TypeParam], ) -> Result { let make_type_row = - |v: &[SignaturePortDeclaration]| -> Result { + |v: &[SignaturePortDeclaration]| -> Result { let types = v .iter() .map(|port_decl| port_decl.make_types(ext, ctx, op_params)) diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index b01313272..1c7b5db99 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -29,7 +29,7 @@ use std::fmt::Debug; use self::signature::TypeRowElem; use self::type_param::TypeParam; -use self::type_row::{RowVarOrType, TypeRowV}; +use self::type_row::{RowVarOrType, TypeRowVarLen}; /// A unique identifier for a type. pub type TypeName = SmolStr; @@ -114,7 +114,7 @@ pub enum SumType { Unit { size: u8 }, // TODO what about a type variable of BoundedUSize /// General case of a Sum type. #[allow(missing_docs)] - General { rows: Vec }, + General { rows: Vec }, } impl std::fmt::Display for SumType { @@ -136,12 +136,12 @@ impl SumType { /// Initialize a new sum type. pub fn new(variants: impl IntoIterator) -> Self where - V: Into, + V: Into, { let rows = variants.into_iter().map(Into::into).collect_vec(); let len: usize = rows.len(); - if len <= (u8::MAX as usize) && rows.iter().all(TypeRowV::is_empty) { + if len <= (u8::MAX as usize) && rows.iter().all(TypeRowVarLen::is_empty) { Self::Unit { size: len as u8 } } else { Self::General { rows } @@ -149,7 +149,7 @@ impl SumType { } /// Report the tag'th variant, if it exists. - pub fn get_variant(&self, tag: usize) -> Option<&TypeRowV> { + pub fn get_variant(&self, tag: usize) -> Option<&TypeRowVarLen> { match self { SumType::Unit { size } if tag < (*size as usize) => Some(Type::EMPTY_VL_TYPEROW_REF), SumType::General { rows } => rows.get(tag), @@ -207,7 +207,7 @@ impl TypeEnum { TypeEnum::Sum(SumType::Unit { size: _ }) => TypeBound::Eq, TypeEnum::Sum(SumType::General { rows }) => least_upper_bound( rows.iter() - .flat_map(TypeRowV::iter) + .flat_map(TypeRowVarLen::iter) .map(RowVarOrType::least_upper_bound), ), } @@ -256,8 +256,8 @@ impl Type { const EMPTY_TYPEROW_REF: &'static TypeRow = &Self::EMPTY_TYPEROW; - const EMPTY_VL_TYPEROW: TypeRowV = TypeRowV::new(); - const EMPTY_VL_TYPEROW_REF: &'static TypeRowV = &Self::EMPTY_VL_TYPEROW; + const EMPTY_VL_TYPEROW: TypeRowVarLen = TypeRowVarLen::new(); + const EMPTY_VL_TYPEROW_REF: &'static TypeRowVarLen = &Self::EMPTY_VL_TYPEROW; /// Initialize a new function type. pub fn new_function(fun_ty: impl Into) -> Self { @@ -266,7 +266,7 @@ impl Type { /// Initialize a new tuple type by providing the elements. #[inline(always)] - pub fn new_tuple(types: impl Into) -> Self { + pub fn new_tuple(types: impl Into) -> Self { let row = types.into(); match row.len() { 0 => Self::UNIT, @@ -276,7 +276,7 @@ impl Type { /// Initialize a new sum type by providing the possible variant types. #[inline(always)] - pub fn new_sum>(variants: impl IntoIterator) -> Self where { + pub fn new_sum>(variants: impl IntoIterator) -> Self where { Self::new(TypeEnum::Sum(SumType::new(variants))) } @@ -345,7 +345,7 @@ impl Type { match &self.0 { TypeEnum::Sum(SumType::General { rows }) => rows .iter() - .flat_map(TypeRowV::iter) + .flat_map(TypeRowVarLen::iter) .try_for_each(|rvt| rvt.validate(extension_registry, var_decls)), TypeEnum::Sum(SumType::Unit { .. }) => Ok(()), // No leaves there TypeEnum::Alias(_) => Ok(()), @@ -463,7 +463,7 @@ pub(crate) mod test { #[test] fn sum_construct() { - let pred1 = Type::new_sum([TypeRowV::new(), TypeRowV::new()]); + let pred1 = Type::new_sum([TypeRowVarLen::new(), TypeRowVarLen::new()]); let pred2 = Type::new_unit_sum(2); assert_eq!(pred1, pred2); diff --git a/quantinuum-hugr/src/types/type_row.rs b/quantinuum-hugr/src/types/type_row.rs index 3c4cd138c..2ed6d8aae 100644 --- a/quantinuum-hugr/src/types/type_row.rs +++ b/quantinuum-hugr/src/types/type_row.rs @@ -54,7 +54,7 @@ where } pub type TypeRow = TypeRowBase; -pub type TypeRowV = TypeRowBase; +pub type TypeRowVarLen = TypeRowBase; impl Display for TypeRowBase where @@ -166,7 +166,7 @@ impl From for Cow<'static, [RowVarOrType]> { } } -impl From for TypeRowV +impl From for TypeRowVarLen where RowVarOrType: From, F: IntoIterator, @@ -228,7 +228,7 @@ impl IntoIterator for TypeRow { } } -impl TryInto for TypeRowV { +impl TryInto for TypeRowVarLen { type Error = (usize, TypeBound); fn try_into(self) -> Result { From c987ed5b1fd093fec9cceb82a8b0eed7c3e88269 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 2 Apr 2024 09:26:21 +0100 Subject: [PATCH 44/57] Rename: FunctionType -> FuncTypeVarLen --- quantinuum-hugr/benches/benchmarks/types.rs | 4 +- quantinuum-hugr/src/builder.rs | 6 +-- quantinuum-hugr/src/builder/cfg.rs | 8 ++-- .../src/extension/declarative/signature.rs | 4 +- quantinuum-hugr/src/extension/infer/test.rs | 8 ++-- quantinuum-hugr/src/extension/op_def.rs | 16 +++---- quantinuum-hugr/src/extension/prelude.rs | 6 +-- quantinuum-hugr/src/extension/simple_op.rs | 4 +- quantinuum-hugr/src/extension/type_def.rs | 4 +- quantinuum-hugr/src/hugr.rs | 4 +- quantinuum-hugr/src/hugr/validate/test.rs | 29 +++++++------ quantinuum-hugr/src/lib.rs | 12 +++--- quantinuum-hugr/src/macros.rs | 4 +- quantinuum-hugr/src/ops/constant.rs | 4 +- quantinuum-hugr/src/ops/dataflow.rs | 2 +- quantinuum-hugr/src/ops/leaf.rs | 2 +- .../std_extensions/arithmetic/conversions.rs | 6 +-- .../std_extensions/arithmetic/float_ops.rs | 8 ++-- .../src/std_extensions/arithmetic/int_ops.rs | 4 +- .../src/std_extensions/collections.rs | 6 +-- quantinuum-hugr/src/std_extensions/logic.rs | 6 +-- quantinuum-hugr/src/types.rs | 8 ++-- quantinuum-hugr/src/types/poly_func.rs | 42 +++++++++---------- quantinuum-hugr/src/types/serialize.rs | 4 +- quantinuum-hugr/src/types/signature.rs | 10 ++--- quantinuum-hugr/src/utils.rs | 14 +++---- 26 files changed, 114 insertions(+), 111 deletions(-) diff --git a/quantinuum-hugr/benches/benchmarks/types.rs b/quantinuum-hugr/benches/benchmarks/types.rs index b391f1133..c8e5a1e2f 100644 --- a/quantinuum-hugr/benches/benchmarks/types.rs +++ b/quantinuum-hugr/benches/benchmarks/types.rs @@ -2,7 +2,7 @@ #![allow(clippy::unit_arg)] use hugr::extension::prelude::{QB_T, USIZE_T}; use hugr::ops::AliasDecl; -use hugr::types::{FunctionType, Type, TypeBound}; +use hugr::types::{FuncTypeVarLen, Type, TypeBound}; use criterion::{black_box, criterion_group, AxisScale, Criterion, PlotConfiguration}; @@ -14,7 +14,7 @@ fn make_complex_type() -> Type { let b_register = Type::new_tuple(vec![int; 8]); let q_alias = Type::new_alias(AliasDecl::new("QReg", TypeBound::Any)); let sum = Type::new_sum([vec![q_register], vec![q_alias]]); - Type::new_function(FunctionType::new(vec![sum], vec![b_register])) + Type::new_function(FuncTypeVarLen::new(vec![sum], vec![b_register])) } fn bench_construction(c: &mut Criterion) { diff --git a/quantinuum-hugr/src/builder.rs b/quantinuum-hugr/src/builder.rs index 0967909ec..8120e1b88 100644 --- a/quantinuum-hugr/src/builder.rs +++ b/quantinuum-hugr/src/builder.rs @@ -30,7 +30,7 @@ //! # use hugr::builder::{BuildError, BuildHandle, Container, DFGBuilder, Dataflow, DataflowHugr, ModuleBuilder, DataflowSubContainer, HugrBuilder}; //! use hugr::extension::prelude::BOOL_T; //! use hugr::std_extensions::logic::{NotOp, LOGIC_REG}; -//! use hugr::types::FunctionType; +//! use hugr::types::FuncTypeVarLen; //! //! # fn doctest() -> Result<(), BuildError> { //! let hugr = { @@ -42,7 +42,7 @@ //! let _dfg_handle = { //! let mut dfg = module_builder.define_function( //! "main", -//! FunctionType::new(vec![BOOL_T], vec![BOOL_T]).into(), +//! FuncTypeVarLen::new(vec![BOOL_T], vec![BOOL_T]).into(), //! )?; //! //! // Get the wires from the function inputs. @@ -59,7 +59,7 @@ //! let _circuit_handle = { //! let mut dfg = module_builder.define_function( //! "circuit", -//! FunctionType::new(vec![BOOL_T, BOOL_T], vec![BOOL_T, BOOL_T]).into(), +//! FuncTypeVarLen::new(vec![BOOL_T, BOOL_T], vec![BOOL_T, BOOL_T]).into(), //! )?; //! let mut circuit = dfg.as_circuit(dfg.input_wires()); //! diff --git a/quantinuum-hugr/src/builder/cfg.rs b/quantinuum-hugr/src/builder/cfg.rs index 48aa54eb1..49fb9f6d5 100644 --- a/quantinuum-hugr/src/builder/cfg.rs +++ b/quantinuum-hugr/src/builder/cfg.rs @@ -47,7 +47,7 @@ use crate::{ /// builder::{BuildError, CFGBuilder, Container, Dataflow, HugrBuilder}, /// Hugr, /// extension::{ExtensionSet, prelude}, -/// types::{FunctionType, Type, SumType}, +/// types::{FuncTypeVarLen, Type, SumType}, /// ops, /// type_row, /// }; @@ -55,7 +55,7 @@ use crate::{ /// const NAT: Type = prelude::USIZE_T; /// /// fn make_cfg() -> Result { -/// let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; +/// let mut cfg_builder = CFGBuilder::new(FuncTypeVarLen::new(type_row![NAT], type_row![NAT]))?; /// /// // Outputs from basic blocks must be packed in a sum which corresponds to /// // which successor to pick. We'll either choose the first branch and pass @@ -85,7 +85,7 @@ use crate::{ /// // entry node's `other_outputs`. /// let mut successor_builder = /// cfg_builder.simple_block_builder( -/// FunctionType::new(type_row![NAT, NAT], type_row![NAT]), +/// FuncTypeVarLen::new(type_row![NAT, NAT], type_row![NAT]), /// 1 // only one successor to this block /// )?; /// let successor_a = { @@ -100,7 +100,7 @@ use crate::{ /// /// // The only argument to this block is the entry node's `other_outputs`. /// let mut successor_builder = -/// cfg_builder.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?; +/// cfg_builder.simple_block_builder(FuncTypeVarLen::new(type_row![NAT], type_row![NAT]), 1)?; /// let successor_b = { /// let sum_unary = successor_builder.add_load_const(ops::Const::unary_unit_sum()); /// let [in_wire] = successor_builder.input_wires_arr(); diff --git a/quantinuum-hugr/src/extension/declarative/signature.rs b/quantinuum-hugr/src/extension/declarative/signature.rs index 9a32024ea..d490de6bd 100644 --- a/quantinuum-hugr/src/extension/declarative/signature.rs +++ b/quantinuum-hugr/src/extension/declarative/signature.rs @@ -15,7 +15,7 @@ use crate::extension::prelude::PRELUDE_ID; use crate::extension::{CustomValidator, ExtensionSet, SignatureFunc, TypeDef, TypeParametrised}; use crate::types::type_param::TypeParam; use crate::types::type_row::TypeRowVarLen; -use crate::types::{CustomType, FunctionType, PolyFuncType, Type}; +use crate::types::{CustomType, FuncTypeVarLen, PolyFuncType, Type}; use crate::Extension; use super::{DeclarationContext, ExtensionDeclarationError}; @@ -51,7 +51,7 @@ impl SignatureDeclaration { Ok(types.into()) }; - let body = FunctionType { + let body = FuncTypeVarLen { input: make_type_row(&self.inputs)?, output: make_type_row(&self.outputs)?, extension_reqs: self.extensions.clone(), diff --git a/quantinuum-hugr/src/extension/infer/test.rs b/quantinuum-hugr/src/extension/infer/test.rs index 13d7d7e79..2c5311377 100644 --- a/quantinuum-hugr/src/extension/infer/test.rs +++ b/quantinuum-hugr/src/extension/infer/test.rs @@ -156,7 +156,7 @@ fn plus() -> Result<(), InferExtensionError> { // because of a missing lift node fn missing_lift_node() { let mut hugr = Hugr::new(NodeType::new_pure(ops::DFG { - signature: FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(A), + signature: FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).with_extension_delta(A), })); let input = hugr.add_node_with_parent( @@ -217,7 +217,7 @@ fn dangling_src() -> Result<(), Box> { let rs = ExtensionSet::singleton(&"R".try_into().unwrap()); let mut hugr = closed_dfg_root_hugr( - FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(rs.clone()), + FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).with_extension_delta(rs.clone()), ); let [input, output] = hugr.get_io(hugr.root()).unwrap(); @@ -961,7 +961,7 @@ fn funcdefn_signature_mismatch() -> Result<(), Box> { let mut builder = ModuleBuilder::new(); let mut func_builder = builder.define_function( "F", - FunctionType::new(vec![NAT], vec![NAT]) + FuncTypeVarLen::new(vec![NAT], vec![NAT]) .with_extension_delta(A) .into(), )?; @@ -996,7 +996,7 @@ fn funcdefn_signature_mismatch2() -> Result<(), Box> { let mut builder = ModuleBuilder::new(); let func_builder = builder.define_function( "F", - FunctionType::new(vec![NAT], vec![NAT]) + FuncTypeVarLen::new(vec![NAT], vec![NAT]) .with_extension_delta(A) .into(), )?; diff --git a/quantinuum-hugr/src/extension/op_def.rs b/quantinuum-hugr/src/extension/op_def.rs index 04be17660..4eaaa9b9a 100644 --- a/quantinuum-hugr/src/extension/op_def.rs +++ b/quantinuum-hugr/src/extension/op_def.rs @@ -12,7 +12,7 @@ use super::{ }; use crate::types::type_param::{check_type_args, TypeArg, TypeParam}; -use crate::types::{FunctionType, PolyFuncType, Signature}; +use crate::types::{FuncTypeVarLen, PolyFuncType, Signature}; use crate::Hugr; /// Trait necessary for binary computations of OpDef signature @@ -194,9 +194,9 @@ impl From for SignatureFunc { } } -impl From for SignatureFunc { +impl From for SignatureFunc { // ALAN might want to be Signature? - fn from(v: FunctionType) -> Self { + fn from(v: FuncTypeVarLen) -> Self { Self::TypeScheme(CustomValidator::from_polyfunc(v)) } } @@ -248,7 +248,7 @@ impl SignatureFunc { } }; - // The first instantiate returns a FunctionType, i.e. expressed using 'RowVarOrType's. + // The first instantiate returns a FuncTypeVarLen, i.e. expressed using 'RowVarOrType's. // try_into removes possibility of containing any RowVars by expressing directly using 'Type's. let res = pf .instantiate(args, exts)? @@ -486,7 +486,7 @@ mod test { use crate::ops::custom::ExternalOp; use crate::ops::LeafOp; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; - use crate::types::{type_param::TypeParam, FunctionType, Signature, TypeArg, TypeBound}; + use crate::types::{type_param::TypeParam, FuncTypeVarLen, Signature, TypeArg, TypeBound}; use crate::types::{PolyFuncType, Type}; use crate::Hugr; use crate::{const_extension_ids, Extension}; @@ -503,7 +503,7 @@ mod test { let list_of_var = Type::new_extension(list_def.instantiate(vec![TypeArg::new_var_use(0, TP)])?); const OP_NAME: SmolStr = SmolStr::new_inline("Reverse"); - let type_scheme = PolyFuncType::new(vec![TP], FunctionType::new_endo(vec![list_of_var])); + let type_scheme = PolyFuncType::new(vec![TP], FuncTypeVarLen::new_endo(vec![list_of_var])); let def = e.add_op(OP_NAME, "desc".into(), type_scheme)?; def.add_lower_func(LowerFunc::FixedHugr(ExtensionSet::new(), Hugr::default())); @@ -553,7 +553,7 @@ mod test { .collect(); Ok(PolyFuncType::new( vec![TP.to_owned()], - FunctionType::new(tvs.clone(), vec![Type::new_tuple(tvs)]), + FuncTypeVarLen::new(tvs.clone(), vec![Type::new_tuple(tvs)]), )) } @@ -630,7 +630,7 @@ mod test { "".into(), PolyFuncType::new( vec![TypeBound::Any.into()], - FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + FuncTypeVarLen::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; let tv = Type::new_var_use(1, TypeBound::Eq); diff --git a/quantinuum-hugr/src/extension/prelude.rs b/quantinuum-hugr/src/extension/prelude.rs index ad753582d..21f09c790 100644 --- a/quantinuum-hugr/src/extension/prelude.rs +++ b/quantinuum-hugr/src/extension/prelude.rs @@ -11,7 +11,7 @@ use crate::{ type_row, types::{ type_param::{TypeArg, TypeParam}, - CustomType, FunctionType, PolyFuncType, Type, TypeBound, + CustomType, FuncTypeVarLen, PolyFuncType, Type, TypeBound, }, Extension, }; @@ -32,7 +32,7 @@ impl SignatureFromArgs for ArrayOpCustom { Ok(PolyFuncType::new( vec![TypeBound::Any.into()], - FunctionType::new(var_arg_row, other_row), + FuncTypeVarLen::new(var_arg_row, other_row), )) } @@ -92,7 +92,7 @@ lazy_static! { .add_op( SmolStr::new_inline(PANIC_OP_ID), "Panic with input error".to_string(), - FunctionType::new(type_row![Type::new_extension(ERROR_CUSTOM_TYPE)], type_row![]), + FuncTypeVarLen::new(type_row![Type::new_extension(ERROR_CUSTOM_TYPE)], type_row![]), ) .unwrap(); prelude diff --git a/quantinuum-hugr/src/extension/simple_op.rs b/quantinuum-hugr/src/extension/simple_op.rs index ff4b62778..acbe93868 100644 --- a/quantinuum-hugr/src/extension/simple_op.rs +++ b/quantinuum-hugr/src/extension/simple_op.rs @@ -225,7 +225,7 @@ impl From for OpType { #[cfg(test)] mod test { - use crate::{const_extension_ids, type_row, types::FunctionType}; + use crate::{const_extension_ids, type_row, types::FuncTypeVarLen}; use super::*; use lazy_static::lazy_static; @@ -238,7 +238,7 @@ mod test { impl MakeOpDef for DummyEnum { fn signature(&self) -> SignatureFunc { - FunctionType::new_endo(type_row![]).into() + FuncTypeVarLen::new_endo(type_row![]).into() } fn from_def(_op_def: &OpDef) -> Result { diff --git a/quantinuum-hugr/src/extension/type_def.rs b/quantinuum-hugr/src/extension/type_def.rs index 50363a7b7..558ac9382 100644 --- a/quantinuum-hugr/src/extension/type_def.rs +++ b/quantinuum-hugr/src/extension/type_def.rs @@ -169,7 +169,7 @@ mod test { use crate::extension::SignatureError; use crate::std_extensions::arithmetic::float_types::FLOAT64_TYPE; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; - use crate::types::{FunctionType, Type, TypeBound}; + use crate::types::{FuncTypeVarLen, Type, TypeBound}; use super::{TypeDef, TypeDefBound}; @@ -186,7 +186,7 @@ mod test { }; let typ = Type::new_extension( def.instantiate(vec![TypeArg::Type { - ty: Type::new_function(FunctionType::default()), + ty: Type::new_function(FuncTypeVarLen::default()), }]) .unwrap(), ); diff --git a/quantinuum-hugr/src/hugr.rs b/quantinuum-hugr/src/hugr.rs index a14f7df13..ef7986376 100644 --- a/quantinuum-hugr/src/hugr.rs +++ b/quantinuum-hugr/src/hugr.rs @@ -380,13 +380,13 @@ mod test { use crate::hugr::HugrMut; use crate::ops::LeafOp; use crate::type_row; - use crate::types::{FunctionType, Type}; + use crate::types::{FuncTypeVarLen, Type}; const BIT: Type = crate::extension::prelude::USIZE_T; let r = ExtensionSet::singleton(&"R".try_into().unwrap()); let mut hugr = closed_dfg_root_hugr( - FunctionType::new(type_row![BIT], type_row![BIT]).with_extension_delta(r.clone()), + FuncTypeVarLen::new(type_row![BIT], type_row![BIT]).with_extension_delta(r.clone()), ); let [input, output] = hugr.get_io(hugr.root()).unwrap(); let lift = hugr.add_node_with_parent( diff --git a/quantinuum-hugr/src/hugr/validate/test.rs b/quantinuum-hugr/src/hugr/validate/test.rs index dcbfbbc52..b82ed594f 100644 --- a/quantinuum-hugr/src/hugr/validate/test.rs +++ b/quantinuum-hugr/src/hugr/validate/test.rs @@ -16,7 +16,9 @@ use crate::std_extensions::logic::test::{and_op, or_op}; use crate::std_extensions::logic::{self, NotOp}; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; use crate::types::type_row::RowVarOrType; -use crate::types::{CustomType, FunctionType, PolyFixedFunc, Signature, Type, TypeBound, TypeRow}; +use crate::types::{ + CustomType, FuncTypeVarLen, PolyFixedFunc, Signature, Type, TypeBound, TypeRow, +}; use crate::{type_row, Direction, IncomingPort, Node}; const NAT: Type = crate::extension::prelude::USIZE_T; @@ -539,7 +541,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { #[test] fn inner_row_variables() -> Result<(), Box> { let tv = RowVarOrType::RV(0, TypeBound::Any); - let inner_ft = Type::new_function(FunctionType::new_endo(vec![tv])); + let inner_ft = Type::new_function(FuncTypeVarLen::new_endo(vec![tv])); let mut fb = FunctionBuilder::new( "id", PolyFixedFunc::new( @@ -656,7 +658,7 @@ mod extension_tests { b.replace_op( copy, NodeType::new_pure(ops::CFG { - signature: FunctionType::new(type_row![BOOL_T], type_row![BOOL_T]), + signature: FuncTypeVarLen::new(type_row![BOOL_T], type_row![BOOL_T]), }), ) .unwrap(); @@ -738,7 +740,7 @@ mod extension_tests { // The DFG node declares that it has an empty extension delta, // but it's child graph adds extension "XB", causing a mismatch. let mut hugr = Hugr::new(NodeType::new_pure(ops::DFG { - signature: FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]), + signature: FuncTypeVarLen::new(type_row![USIZE_T], type_row![USIZE_T]), })); let input = hugr.add_node_with_parent( @@ -785,12 +787,12 @@ mod extension_tests { let mut module_builder = ModuleBuilder::new(); let mut main = module_builder.define_function( "main", - FunctionType::new(type_row![NAT], type_row![NAT]).into(), + FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).into(), )?; let [main_input] = main.input_wires_arr(); let f_builder = main.dfg_builder( - FunctionType::new(type_row![NAT], type_row![NAT]), + FuncTypeVarLen::new(type_row![NAT], type_row![NAT]), // Inner DFG has extension requirements that the wire wont satisfy Some(ExtensionSet::from_iter([XA, XB])), [main_input], @@ -818,12 +820,13 @@ mod extension_tests { fn too_many_extension() -> Result<(), BuildError> { let mut module_builder = ModuleBuilder::new(); - let main_sig = FunctionType::new(type_row![NAT], type_row![NAT]).into(); + let main_sig = FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).into(); let mut main = module_builder.define_function("main", main_sig)?; let [main_input] = main.input_wires_arr(); - let inner_sig = FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(XA); + let inner_sig = + FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).with_extension_delta(XA); let f_builder = main.dfg_builder(inner_sig, Some(ExtensionSet::new()), [main_input])?; let f_inputs = f_builder.input_wires(); @@ -850,7 +853,7 @@ mod extension_tests { let all_rs = ExtensionSet::from_iter([XA, XB]); - let main_sig = FunctionType::new(type_row![], type_row![NAT]) + let main_sig = FuncTypeVarLen::new(type_row![], type_row![NAT]) .with_extension_delta(all_rs.clone()) .into(); @@ -858,7 +861,7 @@ mod extension_tests { let [left_wire] = main .dfg_builder( - FunctionType::new(type_row![], type_row![NAT]), + FuncTypeVarLen::new(type_row![], type_row![NAT]), Some(XA.into()), [], )? @@ -867,7 +870,7 @@ mod extension_tests { let [right_wire] = main .dfg_builder( - FunctionType::new(type_row![], type_row![NAT]), + FuncTypeVarLen::new(type_row![], type_row![NAT]), Some(XB.into()), [], )? @@ -875,7 +878,7 @@ mod extension_tests { .outputs_arr(); let builder = main.dfg_builder( - FunctionType::new(type_row![NAT, NAT], type_row![NAT]), + FuncTypeVarLen::new(type_row![NAT, NAT], type_row![NAT]), Some(all_rs), [left_wire, right_wire], )?; @@ -896,7 +899,7 @@ mod extension_tests { #[test] fn parent_signature_mismatch() { let main_signature = - FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(XA); + FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).with_extension_delta(XA); let mut hugr = Hugr::new(NodeType::new_pure(ops::DFG { signature: main_signature, diff --git a/quantinuum-hugr/src/lib.rs b/quantinuum-hugr/src/lib.rs index e83ea9fbd..831420485 100644 --- a/quantinuum-hugr/src/lib.rs +++ b/quantinuum-hugr/src/lib.rs @@ -31,7 +31,7 @@ //! use hugr::extension::prelude::{BOOL_T, QB_T}; //! use hugr::hugr::Hugr; //! use hugr::type_row; -//! use hugr::types::FunctionType; +//! use hugr::types::FuncTypeVarLen; //! //! // The type of qubits, `QB_T` is in the prelude but, by default, no gateset //! // is defined. This module provides Hadamard and CX gates. @@ -45,18 +45,18 @@ //! }, //! ops::LeafOp, //! type_row, -//! types::{FunctionType, PolyFuncType}, +//! types::{FuncTypeVarLen, PolyFuncType}, //! Extension, //! }; //! //! use lazy_static::lazy_static; //! //! fn one_qb_func() -> PolyFuncType { -//! FunctionType::new_endo(type_row![QB_T]).into() +//! FuncTypeVarLen::new_endo(type_row![QB_T]).into() //! } //! //! fn two_qb_func() -> PolyFuncType { -//! FunctionType::new_endo(type_row![QB_T, QB_T]).into() +//! FuncTypeVarLen::new_endo(type_row![QB_T, QB_T]).into() //! } //! /// The extension identifier. //! pub const EXTENSION_ID: ExtensionId = ExtensionId::new_unchecked("mini.quantum"); @@ -75,7 +75,7 @@ //! .add_op( //! SmolStr::new_inline("Measure"), //! "Measure a qubit, returning the qubit and the measurement result.".into(), -//! FunctionType::new(type_row![QB_T], type_row![QB_T, BOOL_T]), +//! FuncTypeVarLen::new(type_row![QB_T], type_row![QB_T, BOOL_T]), //! ) //! .unwrap(); //! @@ -117,7 +117,7 @@ //! // └───┘└───┘└╥┘ //! // c: ╚═ //! fn make_dfg_hugr() -> Result { -//! let mut dfg_builder = DFGBuilder::new(FunctionType::new( +//! let mut dfg_builder = DFGBuilder::new(FuncTypeVarLen::new( //! type_row![QB_T, QB_T], //! type_row![QB_T, QB_T, BOOL_T], //! ))?; diff --git a/quantinuum-hugr/src/macros.rs b/quantinuum-hugr/src/macros.rs index fdeacfe2d..00308d41b 100644 --- a/quantinuum-hugr/src/macros.rs +++ b/quantinuum-hugr/src/macros.rs @@ -43,11 +43,11 @@ pub(crate) use impl_box_clone; /// Example: /// ``` /// # use hugr::macros::type_row; -/// # use hugr::types::{FunctionType, Type, TypeRow}; +/// # use hugr::types::{FuncTypeVarLen, Type, TypeRow}; /// const U: Type = Type::UNIT; /// let static_row: TypeRow = type_row![U, U]; /// let dynamic_row: TypeRow = vec![U, U, U].into(); -/// let sig = FunctionType::new(static_row, dynamic_row); +/// let sig = FuncTypeVarLen::new(static_row, dynamic_row); /// /// let repeated_row: TypeRow = type_row![U; 3]; /// assert_eq!(repeated_row, *sig.output()); diff --git a/quantinuum-hugr/src/ops/constant.rs b/quantinuum-hugr/src/ops/constant.rs index f59da31e3..964543d5e 100644 --- a/quantinuum-hugr/src/ops/constant.rs +++ b/quantinuum-hugr/src/ops/constant.rs @@ -296,7 +296,7 @@ mod test { std_extensions::arithmetic::float_types::{self, ConstF64, FLOAT64_TYPE}, type_row, types::type_param::TypeArg, - types::{CustomType, FunctionType, Type, TypeBound, TypeRow}, + types::{CustomType, FuncTypeVarLen, Type, TypeBound, TypeRow}, }; use cool_asserts::assert_matches; use rstest::{fixture, rstest}; @@ -416,7 +416,7 @@ mod test { fn function_value(simple_dfg_hugr: Hugr) { let v = Const::function(simple_dfg_hugr).unwrap(); - let correct_type = Type::new_function(FunctionType::new_endo(type_row![ + let correct_type = Type::new_function(FuncTypeVarLen::new_endo(type_row![ crate::extension::prelude::BOOL_T ])); diff --git a/quantinuum-hugr/src/ops/dataflow.rs b/quantinuum-hugr/src/ops/dataflow.rs index 3f4be1272..3cb36e2d3 100644 --- a/quantinuum-hugr/src/ops/dataflow.rs +++ b/quantinuum-hugr/src/ops/dataflow.rs @@ -210,7 +210,7 @@ impl Call { /// # use hugr::types::Signature; /// # use hugr::extension::prelude::QB_T; /// # use hugr::extension::PRELUDE_REGISTRY; - /// let signature = FunctionType::new(vec![QB_T, QB_T], vec![QB_T, QB_T]); + /// let signature = FuncTypeVarLen::new(vec![QB_T, QB_T], vec![QB_T, QB_T]); /// let call = Call::try_new(signature.into(), &[], &PRELUDE_REGISTRY).unwrap(); /// let op = OpType::Call(call.clone()); /// assert_eq!(op.static_input_port(), Some(call.called_function_port())); diff --git a/quantinuum-hugr/src/ops/leaf.rs b/quantinuum-hugr/src/ops/leaf.rs index 5e871a7f1..b883511fb 100644 --- a/quantinuum-hugr/src/ops/leaf.rs +++ b/quantinuum-hugr/src/ops/leaf.rs @@ -176,7 +176,7 @@ impl DataflowOpTrait for LeafOp { /// The signature of the operation. fn signature(&self) -> Signature { - // Static signatures. The `TypeRow`s in the `FunctionType` use a + // Static signatures. The `TypeRow`s in the `FuncTypeVarLen` use a // copy-on-write strategy, so we can avoid unnecessary allocations. match self { diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs b/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs index b5da37c37..5506a31a4 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs @@ -12,7 +12,7 @@ use crate::{ }, ops::{custom::ExtensionOp, OpName}, type_row, - types::{type_row::RowVarOrType, FunctionType, PolyFuncType, TypeArg}, + types::{type_row::RowVarOrType, FuncTypeVarLen, PolyFuncType, TypeArg}, Extension, }; @@ -43,7 +43,7 @@ impl MakeOpDef for ConvertOpDef { match self { trunc_s | trunc_u => PolyFuncType::new( vec![LOG_WIDTH_TYPE_PARAM], - FunctionType::new( + FuncTypeVarLen::new( type_row![FLOAT64_TYPE], vec![RowVarOrType::T(sum_with_error(int_tv(0)).into())], ), @@ -51,7 +51,7 @@ impl MakeOpDef for ConvertOpDef { convert_s | convert_u => PolyFuncType::new( vec![LOG_WIDTH_TYPE_PARAM], - FunctionType::new(vec![int_tv(0)], type_row![FLOAT64_TYPE]), + FuncTypeVarLen::new(vec![int_tv(0)], type_row![FLOAT64_TYPE]), ), } .into() diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/float_ops.rs b/quantinuum-hugr/src/std_extensions/arithmetic/float_ops.rs index 9b4438340..64012c68d 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/float_ops.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/float_ops.rs @@ -10,7 +10,7 @@ use crate::{ ExtensionId, ExtensionRegistry, ExtensionSet, OpDef, SignatureFunc, PRELUDE, }, type_row, - types::FunctionType, + types::FuncTypeVarLen, Extension, }; use lazy_static::lazy_static; @@ -50,12 +50,12 @@ impl MakeOpDef for FloatOps { match self { feq | fne | flt | fgt | fle | fge => { - FunctionType::new(type_row![FLOAT64_TYPE; 2], type_row![BOOL_T]) + FuncTypeVarLen::new(type_row![FLOAT64_TYPE; 2], type_row![BOOL_T]) } fmax | fmin | fadd | fsub | fmul | fdiv => { - FunctionType::new(type_row![FLOAT64_TYPE; 2], type_row![FLOAT64_TYPE]) + FuncTypeVarLen::new(type_row![FLOAT64_TYPE; 2], type_row![FLOAT64_TYPE]) } - fneg | fabs | ffloor | fceil => FunctionType::new_endo(type_row![FLOAT64_TYPE]), + fneg | fabs | ffloor | fceil => FuncTypeVarLen::new_endo(type_row![FLOAT64_TYPE]), } .into() } diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs index 502e173fc..4c2098004 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs @@ -9,7 +9,7 @@ use crate::extension::{ use crate::ops::custom::ExtensionOp; use crate::ops::OpName; use crate::type_row; -use crate::types::{FunctionType, PolyFuncType}; +use crate::types::{FuncTypeVarLen, PolyFuncType}; use crate::utils::collect_array; use crate::{ @@ -224,7 +224,7 @@ fn int_polytype( ) -> PolyFuncType { PolyFuncType::new( vec![LOG_WIDTH_TYPE_PARAM; n_vars], - FunctionType::new(input.into(), output.into()), + FuncTypeVarLen::new(input.into(), output.into()), ) } diff --git a/quantinuum-hugr/src/std_extensions/collections.rs b/quantinuum-hugr/src/std_extensions/collections.rs index 4a6decb6b..35b1613a2 100644 --- a/quantinuum-hugr/src/std_extensions/collections.rs +++ b/quantinuum-hugr/src/std_extensions/collections.rs @@ -17,7 +17,7 @@ use crate::{ ops::{self, custom::ExtensionOp, OpName}, types::{ type_param::{TypeArg, TypeParam}, - CustomCheckFailure, CustomType, FunctionType, PolyFuncType, Type, TypeBound, + CustomCheckFailure, CustomType, FuncTypeVarLen, PolyFuncType, Type, TypeBound, }, Extension, }; @@ -156,7 +156,7 @@ fn extension() -> Extension { "Pop from back of list".into(), PolyFuncType::new( vec![TP], - FunctionType::new(vec![l.clone()], vec![l.clone(), e.clone()]), + FuncTypeVarLen::new(vec![l.clone()], vec![l.clone(), e.clone()]), ), ) .unwrap() @@ -165,7 +165,7 @@ fn extension() -> Extension { .add_op( PUSH_NAME, "Push to back of list".into(), - PolyFuncType::new(vec![TP], FunctionType::new(vec![l.clone(), e], vec![l])), + PolyFuncType::new(vec![TP], FuncTypeVarLen::new(vec![l.clone(), e], vec![l])), ) .unwrap() .set_constant_folder(PushFold); diff --git a/quantinuum-hugr/src/std_extensions/logic.rs b/quantinuum-hugr/src/std_extensions/logic.rs index fe1f3177c..841bb9e94 100644 --- a/quantinuum-hugr/src/std_extensions/logic.rs +++ b/quantinuum-hugr/src/std_extensions/logic.rs @@ -13,7 +13,7 @@ use crate::{ type_row, types::{ type_param::{TypeArg, TypeParam}, - FunctionType, + FuncTypeVarLen, }, Extension, IncomingPort, }; @@ -112,7 +112,7 @@ impl MakeOpDef for NotOp { } fn signature(&self) -> SignatureFunc { - FunctionType::new_endo(type_row![BOOL_T]).into() + FuncTypeVarLen::new_endo(type_row![BOOL_T]).into() } fn description(&self) -> String { "logical 'not'".into() @@ -135,7 +135,7 @@ fn logic_op_sig() -> impl SignatureFromArgs { return Err(SignatureError::InvalidTypeArgs); }; let var_arg_row = vec![BOOL_T; n as usize]; - Ok(FunctionType::new(var_arg_row, vec![BOOL_T]).into()) + Ok(FuncTypeVarLen::new(var_arg_row, vec![BOOL_T]).into()) } fn static_params(&self) -> &[TypeParam] { diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index 1c7b5db99..cfd4ae651 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -13,7 +13,7 @@ use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; pub use poly_func::{PolyFixedFunc, PolyFuncType}; -pub use signature::{FunctionType, Signature}; +pub use signature::{FuncTypeVarLen, Signature}; use smol_str::SmolStr; pub use type_param::TypeArg; pub use type_row::TypeRow; @@ -238,9 +238,9 @@ impl TypeEnum { /// ``` /// /// ``` -/// # use hugr::types::{Type, TypeBound, FunctionType}; +/// # use hugr::types::{Type, TypeBound, FuncTypeVarLen}; /// -/// let func_type = Type::new_function(FunctionType::default()); +/// let func_type = Type::new_function(FuncTypeVarLen::default()); /// assert_eq!(func_type.least_upper_bound(), TypeBound::Copyable); /// /// ``` @@ -435,7 +435,7 @@ pub(crate) mod test { fn construct() { let t: Type = Type::new_tuple(vec![ USIZE_T, - Type::new_function(FunctionType::default()), + Type::new_function(FuncTypeVarLen::default()), Type::new_extension(CustomType::new( "my_custom", [], diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index b0ac0a89e..61f817f5c 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -81,7 +81,7 @@ where } /// Create a new PolyFuncBase given the kinds of the variables it declares - /// and the underlying [FunctionType]. + /// and the underlying [FuncTypeVarLen]. pub fn new(params: impl Into>, body: impl Into>) -> Self { Self { params: params.into(), @@ -273,7 +273,7 @@ pub(crate) mod test { use crate::types::signature::FuncTypeBase; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; use crate::types::type_row::RowVarOrType; - use crate::types::{CustomType, FunctionType, PolyFuncType, Type, TypeBound}; + use crate::types::{CustomType, FuncTypeVarLen, PolyFuncType, Type, TypeBound}; use crate::Extension; use super::{PolyFuncBase, TypeRowElem}; @@ -305,14 +305,14 @@ pub(crate) mod test { let list_of_var = Type::new_extension(list_def.instantiate([tyvar.clone()])?); let list_len = PolyFuncBase::new_validated( [TypeBound::Any.into()], - FunctionType::new(vec![list_of_var], vec![USIZE_T]), + FuncTypeVarLen::new(vec![list_of_var], vec![USIZE_T]), ®ISTRY, )?; let t = list_len.instantiate(&[TypeArg::Type { ty: USIZE_T }], ®ISTRY)?; assert_eq!( t, - FunctionType::new( + FuncTypeVarLen::new( vec![Type::new_extension( list_def .instantiate([TypeArg::Type { ty: USIZE_T }]) @@ -325,8 +325,8 @@ pub(crate) mod test { Ok(()) } - fn id_fn(t: Type) -> FunctionType { - FunctionType::new(vec![t.clone()], vec![t]) + fn id_fn(t: Type) -> FuncTypeVarLen { + FuncTypeVarLen::new(vec![t.clone()], vec![t]) } #[test] @@ -504,7 +504,7 @@ pub(crate) mod test { fn new_pf1(param: TypeParam, input: Type, output: Type) -> PolyFuncType { PolyFuncType { params: vec![param], - body: FunctionType::new(vec![input], vec![output]), + body: FuncTypeVarLen::new(vec![input], vec![output]), } } @@ -515,7 +515,7 @@ pub(crate) mod test { // forall A,N.(Array -> A) let array_max = PolyFuncBase::new_validated( vec![TypeBound::Any.into(), TypeParam::max_nat()], - FunctionType::new( + FuncTypeVarLen::new( vec![array_type( TypeArg::new_var_use(1, TypeParam::max_nat()), Type::new_var_use(0, TypeBound::Any), @@ -525,7 +525,7 @@ pub(crate) mod test { &PRELUDE_REGISTRY, )?; - let concrete = FunctionType::new( + let concrete = FuncTypeVarLen::new( vec![array_type(TypeArg::BoundedNat { n: 3 }, USIZE_T)], vec![USIZE_T], ); @@ -537,7 +537,7 @@ pub(crate) mod test { // forall N.(Array -> usize) let partial = PolyFuncBase::new_validated( vec![TypeParam::max_nat()], - FunctionType::new( + FuncTypeVarLen::new( vec![array_type( TypeArg::new_var_use(0, TypeParam::max_nat()), USIZE_T, @@ -567,7 +567,7 @@ pub(crate) mod test { pub(crate) fn nested_func() -> PolyFuncType { PolyFuncBase::new_validated( vec![TypeBound::Any.into()], - FunctionType::new( + FuncTypeVarLen::new( vec![Type::new_var_use(0, TypeBound::Any)], vec![Type::new_function(new_pf1( TypeBound::Copyable.into(), @@ -589,7 +589,7 @@ pub(crate) mod test { let arg = array_type(TypeArg::BoundedNat { n: 5 }, USIZE_T); // `arg` -> (forall C. C -> List(Tuple(C, `arg`))) - let outer_applied = FunctionType::new( + let outer_applied = FuncTypeVarLen::new( vec![arg.clone()], // This had index 0, but is replaced vec![Type::new_function(new_pf1( TypeBound::Copyable.into(), @@ -621,7 +621,7 @@ pub(crate) mod test { assert_eq!( res, // F -> forall C. (C -> List(Tuple(C, F))) - FunctionType::new( + FuncTypeVarLen::new( vec![Type::new_var_use(FREE, TypeBound::Eq)], vec![Type::new_function(new_pf1( TypeBound::Copyable.into(), @@ -653,7 +653,7 @@ pub(crate) mod test { .unwrap(); assert_eq!( res, - FunctionType::new( + FuncTypeVarLen::new( vec![rhs(FREE)], // Input: forall TEQ. (TEQ -> Array(TEQ, FREE)) // Output: forall C. C -> List(Tuple(C, Input)) vec![Type::new_function(new_pf1( @@ -678,7 +678,7 @@ pub(crate) mod test { b: TypeBound::Copyable, }), }], - FunctionType::new( + FuncTypeVarLen::new( vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], vec![Type::new_sum(vec![RowVarOrType::RV(0, TypeBound::Any)])], ), @@ -690,7 +690,7 @@ pub(crate) mod test { [TypeParam::List { param: Box::new(TP), }], - FunctionType::new( + FuncTypeVarLen::new( vec![USIZE_T.into(), RowVarOrType::RV(0, TypeBound::Any)], vec![Type::new_tuple(RowVarOrType::RV(0, TypeBound::Any))], ), @@ -716,7 +716,7 @@ pub(crate) mod test { .unwrap(); assert_eq!( t2, - FunctionType::new( + FuncTypeVarLen::new( vec![USIZE_T, USIZE_T, BOOL_T], vec![Type::new_tuple(vec![ RowVarOrType::T(USIZE_T), @@ -728,7 +728,7 @@ pub(crate) mod test { #[test] fn row_variables_inner() { - let inner_fty = Type::new_function(FunctionType::new_endo(vec![RowVarOrType::RV( + let inner_fty = Type::new_function(FuncTypeVarLen::new_endo(vec![RowVarOrType::RV( 0, TypeBound::Copyable, )])); @@ -738,12 +738,12 @@ pub(crate) mod test { b: TypeBound::Copyable, }), }], - FunctionType::new(vec![USIZE_T, inner_fty.clone()], vec![inner_fty]), + FuncTypeVarLen::new(vec![USIZE_T, inner_fty.clone()], vec![inner_fty]), &PRELUDE_REGISTRY, ) .unwrap(); - let inner3 = Type::new_function(FunctionType::new_endo(vec![USIZE_T, BOOL_T, USIZE_T])); + let inner3 = Type::new_function(FuncTypeVarLen::new_endo(vec![USIZE_T, BOOL_T, USIZE_T])); let t3 = pf .instantiate( &[TypeArg::Sequence { @@ -754,7 +754,7 @@ pub(crate) mod test { .unwrap(); assert_eq!( t3, - FunctionType::new(vec![USIZE_T, inner3.clone()], vec![inner3]) + FuncTypeVarLen::new(vec![USIZE_T, inner3.clone()], vec![inner3]) ); } } diff --git a/quantinuum-hugr/src/types/serialize.rs b/quantinuum-hugr/src/types/serialize.rs index 423bde785..f5de34fe6 100644 --- a/quantinuum-hugr/src/types/serialize.rs +++ b/quantinuum-hugr/src/types/serialize.rs @@ -81,12 +81,12 @@ mod test { use crate::hugr::serialize::test::ser_roundtrip; use crate::std_extensions::arithmetic::float_types::FLOAT64_TYPE; use crate::type_row; - use crate::types::FunctionType; + use crate::types::FuncTypeVarLen; use crate::types::Type; #[test] fn serialize_types_roundtrip() { - let g: Type = Type::new_function(FunctionType::default()); + let g: Type = Type::new_function(FuncTypeVarLen::default()); assert_eq!(ser_roundtrip(&g), g); diff --git a/quantinuum-hugr/src/types/signature.rs b/quantinuum-hugr/src/types/signature.rs index ff70c2a1c..0bfbeb922 100644 --- a/quantinuum-hugr/src/types/signature.rs +++ b/quantinuum-hugr/src/types/signature.rs @@ -55,7 +55,7 @@ where } /// The type of a function, e.g. passing around a pointer/static ref to it. -pub type FunctionType = FuncTypeBase; +pub type FuncTypeVarLen = FuncTypeBase; impl TypeRowElem for RowVarOrType { fn validate( @@ -110,7 +110,7 @@ where T: TypeRowElem, [T]: ToOwned>, { - /// Builder method, add extension_reqs to an FunctionType + /// Builder method, add extension_reqs to an FuncTypeVarLen pub fn with_extension_delta(mut self, rs: impl Into) -> Self { self.extension_reqs = self.extension_reqs.union(rs.into()); self @@ -284,7 +284,7 @@ impl Signature { } } -impl From for FunctionType { +impl From for FuncTypeVarLen { fn from(sig: Signature) -> Self { Self { input: sig.input.into(), @@ -294,10 +294,10 @@ impl From for FunctionType { } } -impl TryFrom for Signature { +impl TryFrom for Signature { type Error = (usize, TypeBound); - fn try_from(funty: FunctionType) -> Result { + fn try_from(funty: FuncTypeVarLen) -> Result { Ok(Self { input: funty.input.try_into()?, output: funty.output.try_into()?, diff --git a/quantinuum-hugr/src/utils.rs b/quantinuum-hugr/src/utils.rs index b8230de33..1e7c1d278 100644 --- a/quantinuum-hugr/src/utils.rs +++ b/quantinuum-hugr/src/utils.rs @@ -108,18 +108,18 @@ pub(crate) mod test_quantum_extension { ops::LeafOp, std_extensions::arithmetic::float_types, type_row, - types::{FunctionType, PolyFuncType}, + types::{FuncTypeVarLen, PolyFuncType}, Extension, }; use lazy_static::lazy_static; fn one_qb_func() -> PolyFuncType { - FunctionType::new_endo(type_row![QB_T]).into() + FuncTypeVarLen::new_endo(type_row![QB_T]).into() } fn two_qb_func() -> PolyFuncType { - FunctionType::new_endo(type_row![QB_T, QB_T]).into() + FuncTypeVarLen::new_endo(type_row![QB_T, QB_T]).into() } /// The extension identifier. pub const EXTENSION_ID: ExtensionId = ExtensionId::new_unchecked("test.quantum"); @@ -133,7 +133,7 @@ pub(crate) mod test_quantum_extension { .add_op( SmolStr::new_inline("RzF64"), "Rotation specified by float".into(), - FunctionType::new(type_row![QB_T, float_types::FLOAT64_TYPE], type_row![QB_T]), + FuncTypeVarLen::new(type_row![QB_T, float_types::FLOAT64_TYPE], type_row![QB_T]), ) .unwrap(); @@ -145,7 +145,7 @@ pub(crate) mod test_quantum_extension { .add_op( SmolStr::new_inline("Measure"), "Measure a qubit, returning the qubit and the measurement result.".into(), - FunctionType::new(type_row![QB_T], type_row![QB_T, BOOL_T]), + FuncTypeVarLen::new(type_row![QB_T], type_row![QB_T, BOOL_T]), ) .unwrap(); @@ -153,7 +153,7 @@ pub(crate) mod test_quantum_extension { .add_op( SmolStr::new_inline("QAlloc"), "Allocate a new qubit.".into(), - FunctionType::new(type_row![], type_row![QB_T]), + FuncTypeVarLen::new(type_row![], type_row![QB_T]), ) .unwrap(); @@ -161,7 +161,7 @@ pub(crate) mod test_quantum_extension { .add_op( SmolStr::new_inline("QDiscard"), "Discard a qubit.".into(), - FunctionType::new(type_row![QB_T], type_row![]), + FuncTypeVarLen::new(type_row![QB_T], type_row![]), ) .unwrap(); From 4a35720b127b190e3a8dbde71f654b8f16ddf606 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 2 Apr 2024 09:27:36 +0100 Subject: [PATCH 45/57] Rename: Signature -> FunctionType --- quantinuum-hugr/benches/benchmarks/hugr.rs | 8 +-- quantinuum-hugr/src/algorithm/const_fold.rs | 22 +++++--- quantinuum-hugr/src/algorithm/nest_cfgs.rs | 22 ++++---- quantinuum-hugr/src/builder.rs | 9 ++-- quantinuum-hugr/src/builder/build_traits.rs | 6 +-- quantinuum-hugr/src/builder/cfg.rs | 24 ++++----- quantinuum-hugr/src/builder/circuit.rs | 12 ++--- quantinuum-hugr/src/builder/conditional.rs | 10 ++-- quantinuum-hugr/src/builder/dataflow.rs | 42 ++++++++------- quantinuum-hugr/src/builder/module.rs | 18 ++++--- quantinuum-hugr/src/builder/tail_loop.rs | 6 +-- quantinuum-hugr/src/extension/infer/test.rs | 52 ++++++++++--------- quantinuum-hugr/src/extension/op_def.rs | 16 +++--- quantinuum-hugr/src/extension/prelude.rs | 6 +-- quantinuum-hugr/src/hugr.rs | 4 +- quantinuum-hugr/src/hugr/hugrmut.rs | 4 +- quantinuum-hugr/src/hugr/rewrite/consts.rs | 4 +- .../src/hugr/rewrite/inline_dfg.rs | 18 ++++--- .../src/hugr/rewrite/outline_cfg.rs | 4 +- quantinuum-hugr/src/hugr/rewrite/replace.rs | 17 +++--- .../src/hugr/rewrite/simple_replace.rs | 16 +++--- quantinuum-hugr/src/hugr/serialize.rs | 14 ++--- quantinuum-hugr/src/hugr/validate/test.rs | 46 +++++++++------- quantinuum-hugr/src/hugr/views.rs | 6 +-- quantinuum-hugr/src/hugr/views/descendants.rs | 10 ++-- .../src/hugr/views/root_checked.rs | 4 +- quantinuum-hugr/src/hugr/views/sibling.rs | 4 +- .../src/hugr/views/sibling_subgraph.rs | 20 +++---- quantinuum-hugr/src/hugr/views/tests.rs | 17 +++--- quantinuum-hugr/src/ops.rs | 8 +-- quantinuum-hugr/src/ops/constant.rs | 6 +-- quantinuum-hugr/src/ops/controlflow.rs | 22 ++++---- quantinuum-hugr/src/ops/custom.rs | 20 +++---- quantinuum-hugr/src/ops/dataflow.rs | 34 ++++++------ quantinuum-hugr/src/ops/leaf.rs | 22 ++++---- quantinuum-hugr/src/ops/module.rs | 4 +- .../src/std_extensions/arithmetic/int_ops.rs | 10 ++-- quantinuum-hugr/src/types.rs | 2 +- quantinuum-hugr/src/types/signature.rs | 12 ++--- 39 files changed, 306 insertions(+), 275 deletions(-) diff --git a/quantinuum-hugr/benches/benchmarks/hugr.rs b/quantinuum-hugr/benches/benchmarks/hugr.rs index a8ad110cb..7da7b4c12 100644 --- a/quantinuum-hugr/benches/benchmarks/hugr.rs +++ b/quantinuum-hugr/benches/benchmarks/hugr.rs @@ -4,12 +4,12 @@ use criterion::{black_box, criterion_group, AxisScale, Criterion, PlotConfigurat use hugr::builder::{BuildError, CFGBuilder, DFGBuilder, Dataflow, DataflowHugr, HugrBuilder}; use hugr::extension::prelude::{BOOL_T, USIZE_T}; use hugr::extension::ExtensionSet; -use hugr::types::Signature; +use hugr::types::FunctionType; use hugr::{type_row, Hugr}; pub fn simple_dfg_hugr() -> Hugr { let dfg_builder = - DFGBuilder::new(Signature::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap(); + DFGBuilder::new(FunctionType::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap(); let [i1] = dfg_builder.input_wires_arr(); dfg_builder.finish_prelude_hugr_with_outputs([i1]).unwrap() } @@ -27,7 +27,7 @@ pub fn simple_cfg_builder + AsRef>( entry_b.finish_with_outputs(sum, [])? }; let mut middle_b = cfg_builder - .simple_block_builder(Signature::new(type_row![USIZE_T], type_row![USIZE_T]), 1)?; + .simple_block_builder(FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]), 1)?; let middle = { let c = middle_b.add_load_const(hugr::ops::Const::unary_unit_sum()); let [inw] = middle_b.input_wires_arr(); @@ -42,7 +42,7 @@ pub fn simple_cfg_builder + AsRef>( pub fn simple_cfg_hugr() -> Hugr { let mut cfg_builder = - CFGBuilder::new(Signature::new(type_row![USIZE_T], type_row![USIZE_T])).unwrap(); + CFGBuilder::new(FunctionType::new(type_row![USIZE_T], type_row![USIZE_T])).unwrap(); simple_cfg_builder(&mut cfg_builder).unwrap(); cfg_builder.finish_prelude_hugr().unwrap() } diff --git a/quantinuum-hugr/src/algorithm/const_fold.rs b/quantinuum-hugr/src/algorithm/const_fold.rs index d14393815..15b792687 100644 --- a/quantinuum-hugr/src/algorithm/const_fold.rs +++ b/quantinuum-hugr/src/algorithm/const_fold.rs @@ -4,7 +4,7 @@ use std::collections::{BTreeSet, HashMap}; use itertools::Itertools; -use crate::types::{Signature, SumType}; +use crate::types::{FunctionType, SumType}; use crate::{ builder::{DFGBuilder, Dataflow, DataflowHugr}, extension::{ConstFoldResult, ExtensionRegistry}, @@ -75,7 +75,7 @@ pub fn fold_leaf_op(op: &LeafOp, consts: &[(IncomingPort, Const)]) -> ConstFoldR /// against `reg`. fn const_graph(consts: Vec, reg: &ExtensionRegistry) -> Hugr { let const_types = consts.iter().map(Const::const_type).collect_vec(); - let mut b = DFGBuilder::new(Signature::new(type_row![], const_types)).unwrap(); + let mut b = DFGBuilder::new(FunctionType::new(type_row![], const_types)).unwrap(); let outputs = consts .into_iter() @@ -219,7 +219,7 @@ mod test { use crate::std_extensions::arithmetic::float_types::{ConstF64, FLOAT64_TYPE}; use crate::std_extensions::arithmetic::int_types::{ConstIntU, INT_TYPES}; use crate::std_extensions::logic::{self, NaryLogic}; - use crate::types::Signature; + use crate::types::FunctionType; use rstest::rstest; @@ -253,8 +253,11 @@ mod test { int(x.0 - x.1) == 2 */ let sum_type = sum_with_error(INT_TYPES[5].to_owned()); - let mut build = - DFGBuilder::new(Signature::new(type_row![], vec![sum_type.clone().into()])).unwrap(); + let mut build = DFGBuilder::new(FunctionType::new( + type_row![], + vec![sum_type.clone().into()], + )) + .unwrap(); let tup = build.add_load_const(Const::tuple([f2c(5.6), f2c(3.2)])); @@ -303,7 +306,7 @@ mod test { #[case] ins: [bool; 3], #[case] out: bool, ) -> Result<(), Box> { - let mut build = DFGBuilder::new(Signature::new(type_row![], vec![BOOL_T])).unwrap(); + let mut build = DFGBuilder::new(FunctionType::new(type_row![], vec![BOOL_T])).unwrap(); let ins = ins.map(|b| build.add_load_const(Const::from_bool(b))); let logic_op = build.add_dataflow_op(op.with_n_inputs(ins.len() as u64), ins)?; @@ -332,8 +335,11 @@ mod test { ]) .unwrap(); let list: Const = ListValue::new(BOOL_T, [Const::unit_sum(0, 1).unwrap()]).into(); - let mut build = - DFGBuilder::new(Signature::new(type_row![], vec![list.const_type().clone()])).unwrap(); + let mut build = DFGBuilder::new(FunctionType::new( + type_row![], + vec![list.const_type().clone()], + )) + .unwrap(); let list_wire = build.add_load_const(list.clone()); diff --git a/quantinuum-hugr/src/algorithm/nest_cfgs.rs b/quantinuum-hugr/src/algorithm/nest_cfgs.rs index 385d67b45..174af2b3d 100644 --- a/quantinuum-hugr/src/algorithm/nest_cfgs.rs +++ b/quantinuum-hugr/src/algorithm/nest_cfgs.rs @@ -580,7 +580,7 @@ pub(crate) mod test { use crate::hugr::views::RootChecked; use crate::ops::handle::{BasicBlockID, ConstID, NodeHandle}; use crate::ops::Const; - use crate::types::{Signature, Type}; + use crate::types::{FunctionType, Type}; use crate::{type_row, Hugr}; const NAT: Type = USIZE_T; @@ -603,7 +603,7 @@ pub(crate) mod test { // /-> left --\ // entry -> split > merge -> head -> tail -> exit // \-> right -/ \-<--<-/ - let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; let pred_const = cfg_builder.add_constant(Const::unit_sum(0, 2).expect("0 < 2")); let const_unit = cfg_builder.add_constant(Const::unary_unit_sum()); @@ -823,7 +823,7 @@ pub(crate) mod test { unit_const: &ConstID, ) -> Result<(BasicBlockID, BasicBlockID), BuildError> { let split = n_identity( - cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 2)?, + cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 2)?, const_pred, )?; let merge = build_then_else_merge_from_if(cfg, unit_const, split)?; @@ -836,15 +836,15 @@ pub(crate) mod test { split: BasicBlockID, ) -> Result { let merge = n_identity( - cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, + cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, unit_const, )?; let left = n_identity( - cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, + cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, unit_const, )?; let right = n_identity( - cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, + cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, unit_const, )?; cfg.branch(&split, 0, &left)?; @@ -861,7 +861,7 @@ pub(crate) mod test { header: BasicBlockID, ) -> Result { let tail = n_identity( - cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 2)?, + cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 2)?, const_pred, )?; cfg.branch(&tail, 1, &header)?; @@ -875,7 +875,7 @@ pub(crate) mod test { unit_const: &ConstID, ) -> Result<(BasicBlockID, BasicBlockID), BuildError> { let header = n_identity( - cfg.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, + cfg.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, unit_const, )?; let tail = build_loop_from_header(cfg, const_pred, header)?; @@ -886,7 +886,7 @@ pub(crate) mod test { pub fn build_cond_then_loop_cfg( separate: bool, ) -> Result<(Hugr, BasicBlockID, BasicBlockID), BuildError> { - let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; let pred_const = cfg_builder.add_constant(Const::unit_sum(0, 2).expect("0 < 2")); let const_unit = cfg_builder.add_constant(Const::unary_unit_sum()); @@ -898,7 +898,7 @@ pub(crate) mod test { let head = if separate { let h = n_identity( cfg_builder - .simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?, + .simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?, &const_unit, )?; cfg_builder.branch(&merge, 0, &h)?; @@ -919,7 +919,7 @@ pub(crate) mod test { pub(crate) fn build_conditional_in_loop_cfg( separate_headers: bool, ) -> Result<(Hugr, BasicBlockID, BasicBlockID), BuildError> { - let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; let (head, tail) = build_conditional_in_loop(&mut cfg_builder, separate_headers)?; let h = cfg_builder.finish_prelude_hugr()?; Ok((h, head, tail)) diff --git a/quantinuum-hugr/src/builder.rs b/quantinuum-hugr/src/builder.rs index 8120e1b88..e7e9ffe14 100644 --- a/quantinuum-hugr/src/builder.rs +++ b/quantinuum-hugr/src/builder.rs @@ -223,7 +223,7 @@ pub(crate) mod test { use crate::hugr::{views::HugrView, HugrMut, NodeType}; use crate::ops; - use crate::types::{PolyFixedFunc, Signature, Type}; + use crate::types::{FunctionType, PolyFixedFunc, Type}; use crate::{type_row, Hugr}; use super::handle::BuildHandle; @@ -258,7 +258,8 @@ pub(crate) mod test { #[fixture] pub(crate) fn simple_dfg_hugr() -> Hugr { - let dfg_builder = DFGBuilder::new(Signature::new(type_row![BIT], type_row![BIT])).unwrap(); + let dfg_builder = + DFGBuilder::new(FunctionType::new(type_row![BIT], type_row![BIT])).unwrap(); let [i1] = dfg_builder.input_wires_arr(); dfg_builder.finish_prelude_hugr_with_outputs([i1]).unwrap() } @@ -266,7 +267,7 @@ pub(crate) mod test { #[fixture] pub(crate) fn simple_cfg_hugr() -> Hugr { let mut cfg_builder = - CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT])).unwrap(); + CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT])).unwrap(); super::cfg::test::build_basic_cfg(&mut cfg_builder).unwrap(); cfg_builder.finish_prelude_hugr().unwrap() } @@ -275,7 +276,7 @@ pub(crate) mod test { /// for tests which want to avoid having open extension variables after /// inference. Using DFGBuilder will default to a root node with an open /// extension variable - pub(crate) fn closed_dfg_root_hugr(signature: Signature) -> Hugr { + pub(crate) fn closed_dfg_root_hugr(signature: FunctionType) -> Hugr { let mut hugr = Hugr::new(NodeType::new_pure(ops::DFG { signature: signature.clone(), })); diff --git a/quantinuum-hugr/src/builder/build_traits.rs b/quantinuum-hugr/src/builder/build_traits.rs index 3f89b66cf..7bcb592e0 100644 --- a/quantinuum-hugr/src/builder/build_traits.rs +++ b/quantinuum-hugr/src/builder/build_traits.rs @@ -20,7 +20,7 @@ use crate::{ }; use crate::extension::{ExtensionRegistry, ExtensionSet, PRELUDE_REGISTRY}; -use crate::types::{PolyFixedFunc, Signature, Type, TypeArg, TypeRow}; +use crate::types::{FunctionType, PolyFixedFunc, Type, TypeArg, TypeRow}; use itertools::Itertools; @@ -297,7 +297,7 @@ pub trait Dataflow: Container { // TODO: Should this be one function, or should there be a temporary "op" one like with the others? fn dfg_builder( &mut self, - signature: Signature, + signature: FunctionType, input_extensions: Option, input_wires: impl IntoIterator, ) -> Result, BuildError> { @@ -335,7 +335,7 @@ pub trait Dataflow: Container { self, NodeType::new( ops::CFG { - signature: Signature::new(inputs.clone(), output_types.clone()) + signature: FunctionType::new(inputs.clone(), output_types.clone()) .with_extension_delta(extension_delta), }, input_extensions.into(), diff --git a/quantinuum-hugr/src/builder/cfg.rs b/quantinuum-hugr/src/builder/cfg.rs index 49fb9f6d5..072ce5b08 100644 --- a/quantinuum-hugr/src/builder/cfg.rs +++ b/quantinuum-hugr/src/builder/cfg.rs @@ -7,7 +7,7 @@ use super::{ use crate::extension::{ExtensionRegistry, ExtensionSet}; use crate::ops::{self, handle::NodeHandle, DataflowBlock, DataflowParent, ExitBlock, OpType}; -use crate::types::Signature; +use crate::types::FunctionType; use crate::{hugr::views::HugrView, types::TypeRow}; use crate::Node; @@ -153,7 +153,7 @@ impl + AsRef> SubContainer for CFGBuilder { impl CFGBuilder { /// New CFG rooted HUGR builder - pub fn new(signature: Signature) -> Result { + pub fn new(signature: FunctionType) -> Result { let cfg_op = ops::CFG { signature: signature.clone(), }; @@ -251,7 +251,7 @@ impl + AsRef> CFGBuilder { /// This function will return an error if there is an error adding the node. pub fn simple_block_builder( &mut self, - signature: Signature, + signature: FunctionType, n_cases: usize, ) -> Result, BuildError> { self.block_builder( @@ -412,7 +412,7 @@ pub(crate) mod test { let build_result = { let mut module_builder = ModuleBuilder::new(); let mut func_builder = module_builder - .define_function("main", Signature::new(vec![NAT], type_row![NAT]))?; + .define_function("main", FunctionType::new(vec![NAT], type_row![NAT]))?; let _f_id = { let [int] = func_builder.input_wires_arr(); @@ -439,7 +439,7 @@ pub(crate) mod test { } #[test] fn basic_cfg_hugr() -> Result<(), BuildError> { - let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; build_basic_cfg(&mut cfg_builder)?; assert_matches!(cfg_builder.finish_prelude_hugr(), Ok(_)); @@ -458,8 +458,8 @@ pub(crate) mod test { let sum = entry_b.make_sum(1, sum2_variants, [inw])?; entry_b.finish_with_outputs(sum, [])? }; - let mut middle_b = - cfg_builder.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?; + let mut middle_b = cfg_builder + .simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?; let middle = { let c = middle_b.add_load_const(ops::Const::unary_unit_sum()); let [inw] = middle_b.input_wires_arr(); @@ -473,7 +473,7 @@ pub(crate) mod test { } #[test] fn test_dom_edge() -> Result<(), BuildError> { - let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; let sum_tuple_const = cfg_builder.add_constant(ops::Const::unary_unit_sum()); let sum_variants = vec![type_row![]]; @@ -486,7 +486,7 @@ pub(crate) mod test { entry_b.finish_with_outputs(sum, [])? }; let mut middle_b = - cfg_builder.simple_block_builder(Signature::new(type_row![], type_row![NAT]), 1)?; + cfg_builder.simple_block_builder(FunctionType::new(type_row![], type_row![NAT]), 1)?; let middle = { let c = middle_b.load_const(&sum_tuple_const); middle_b.finish_with_outputs(c, [inw])? @@ -501,11 +501,11 @@ pub(crate) mod test { #[test] fn test_non_dom_edge() -> Result<(), BuildError> { - let mut cfg_builder = CFGBuilder::new(Signature::new(type_row![NAT], type_row![NAT]))?; + let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; let sum_tuple_const = cfg_builder.add_constant(ops::Const::unary_unit_sum()); let sum_variants = vec![type_row![]]; - let mut middle_b = - cfg_builder.simple_block_builder(Signature::new(type_row![NAT], type_row![NAT]), 1)?; + let mut middle_b = cfg_builder + .simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?; let [inw] = middle_b.input_wires_arr(); let middle = { let c = middle_b.load_const(&sum_tuple_const); diff --git a/quantinuum-hugr/src/builder/circuit.rs b/quantinuum-hugr/src/builder/circuit.rs index 786d13454..eb220043e 100644 --- a/quantinuum-hugr/src/builder/circuit.rs +++ b/quantinuum-hugr/src/builder/circuit.rs @@ -237,7 +237,7 @@ mod test { use super::*; use cool_asserts::assert_matches; - use crate::types::Signature; + use crate::types::FunctionType; use crate::utils::test_quantum_extension::{cx_gate, h_gate, measure, q_alloc, q_discard}; use crate::{ builder::{ @@ -252,7 +252,7 @@ mod test { #[test] fn simple_linear() { let build_res = build_main( - Signature::new(type_row![QB, QB], type_row![QB, QB]).into(), + FunctionType::new(type_row![QB, QB], type_row![QB, QB]).into(), |mut f_build| { let wires = f_build.input_wires().map(Some).collect(); @@ -284,12 +284,12 @@ mod test { "MyOp", "unknown op".to_string(), vec![], - Signature::new(vec![QB, NAT], vec![QB]), + FunctionType::new(vec![QB, NAT], vec![QB]), )) .into(), ); let build_res = build_main( - Signature::new(type_row![QB, QB, NAT], type_row![QB, QB, BOOL_T]).into(), + FunctionType::new(type_row![QB, QB, NAT], type_row![QB, QB, BOOL_T]).into(), |mut f_build| { let [q0, q1, angle]: [Wire; 3] = f_build.input_wires_arr(); @@ -314,7 +314,7 @@ mod test { #[test] fn ancillae() { let build_res = build_main( - Signature::new(type_row![QB], type_row![QB]).into(), + FunctionType::new(type_row![QB], type_row![QB]).into(), |mut f_build| { let mut circ = f_build.as_circuit(f_build.input_wires()); assert_eq!(circ.n_wires(), 1); @@ -350,7 +350,7 @@ mod test { #[test] fn circuit_builder_errors() { let _build_res = build_main( - Signature::new_endo(type_row![QB, QB]).into(), + FunctionType::new_endo(type_row![QB, QB]).into(), |mut f_build| { let mut circ = f_build.as_circuit(f_build.input_wires()); let [q0, q1] = circ.tracked_units_arr(); diff --git a/quantinuum-hugr/src/builder/conditional.rs b/quantinuum-hugr/src/builder/conditional.rs index d2d66270d..c0e9eaf1d 100644 --- a/quantinuum-hugr/src/builder/conditional.rs +++ b/quantinuum-hugr/src/builder/conditional.rs @@ -1,7 +1,7 @@ use crate::extension::ExtensionRegistry; use crate::hugr::views::HugrView; use crate::ops::dataflow::DataflowOpTrait; -use crate::types::{Signature, TypeRow}; +use crate::types::{FunctionType, TypeRow}; use crate::ops; use crate::ops::handle::CaseID; @@ -121,7 +121,7 @@ impl + AsRef> ConditionalBuilder { let outputs = cond.outputs; let case_op = ops::Case { - signature: Signature::new(inputs.clone(), outputs.clone()) + signature: FunctionType::new(inputs.clone(), outputs.clone()) .with_extension_delta(extension_delta.clone()), }; let case_node = @@ -137,7 +137,7 @@ impl + AsRef> ConditionalBuilder { let dfg_builder = DFGBuilder::create_with_io( self.hugr_mut(), case_node, - Signature::new(inputs, outputs).with_extension_delta(extension_delta), + FunctionType::new(inputs, outputs).with_extension_delta(extension_delta), None, )?; @@ -191,7 +191,7 @@ impl ConditionalBuilder { impl CaseBuilder { /// Initialize a Case rooted HUGR - pub fn new(signature: Signature) -> Result { + pub fn new(signature: FunctionType) -> Result { let op = ops::Case { signature: signature.clone(), }; @@ -239,7 +239,7 @@ mod test { let build_result: Result = { let mut module_builder = ModuleBuilder::new(); let mut fbuild = module_builder - .define_function("main", Signature::new(type_row![NAT], type_row![NAT]))?; + .define_function("main", FunctionType::new(type_row![NAT], type_row![NAT]))?; let tru_const = fbuild.add_constant(Const::true_val()); let _fdef = { let const_wire = fbuild.load_const(&tru_const); diff --git a/quantinuum-hugr/src/builder/dataflow.rs b/quantinuum-hugr/src/builder/dataflow.rs index 3c4219e4d..18e47b320 100644 --- a/quantinuum-hugr/src/builder/dataflow.rs +++ b/quantinuum-hugr/src/builder/dataflow.rs @@ -7,7 +7,7 @@ use std::marker::PhantomData; use crate::hugr::{HugrView, NodeType, ValidationError}; use crate::ops; -use crate::types::{PolyFixedFunc, Signature}; +use crate::types::{FunctionType, PolyFixedFunc}; use crate::extension::{ExtensionRegistry, ExtensionSet}; use crate::Node; @@ -26,10 +26,10 @@ impl + AsRef> DFGBuilder { pub(super) fn create_with_io( mut base: T, parent: Node, - signature: Signature, + signature: FunctionType, input_extensions: Option, ) -> Result { - let Signature { + let FunctionType { input, output, extension_reqs, @@ -76,7 +76,7 @@ impl DFGBuilder { /// # Errors /// /// Error in adding DFG child nodes. - pub fn new(signature: Signature) -> Result, BuildError> { + pub fn new(signature: FunctionType) -> Result, BuildError> { let dfg_op = ops::DFG { signature: signature.clone(), }; @@ -230,7 +230,7 @@ pub(crate) mod test { let _f_id = { let mut func_builder = module_builder.define_function( "main", - Signature::new(type_row![NAT, QB], type_row![NAT, QB]), + FunctionType::new(type_row![NAT, QB], type_row![NAT, QB]), )?; let [int, qb] = func_builder.input_wires_arr(); @@ -238,7 +238,7 @@ pub(crate) mod test { let q_out = func_builder.add_dataflow_op(h_gate(), vec![qb])?; let inner_builder = func_builder.dfg_builder( - Signature::new(type_row![NAT], type_row![NAT]), + FunctionType::new(type_row![NAT], type_row![NAT]), None, [int], )?; @@ -264,7 +264,7 @@ pub(crate) mod test { let f_build = module_builder.define_function( "main", - Signature::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]), + FunctionType::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]), )?; f(f_build)?; @@ -313,7 +313,7 @@ pub(crate) mod test { let mut module_builder = ModuleBuilder::new(); let f_build = module_builder - .define_function("main", Signature::new(type_row![QB], type_row![QB, QB]))?; + .define_function("main", FunctionType::new(type_row![QB], type_row![QB, QB]))?; let [q1] = f_build.input_wires_arr(); f_build.finish_with_outputs([q1, q1])?; @@ -336,7 +336,7 @@ pub(crate) mod test { let builder = || -> Result { let mut f_build = FunctionBuilder::new( "main", - Signature::new(type_row![BIT], type_row![BIT]).into(), + FunctionType::new(type_row![BIT], type_row![BIT]).into(), )?; let [i1] = f_build.input_wires_arr(); @@ -344,7 +344,7 @@ pub(crate) mod test { let i1 = noop.out_wire(0); let mut nested = - f_build.dfg_builder(Signature::new(type_row![], type_row![BIT]), None, [])?; + f_build.dfg_builder(FunctionType::new(type_row![], type_row![BIT]), None, [])?; let id = nested.add_dataflow_op(LeafOp::Noop { ty: BIT }, [i1])?; @@ -358,15 +358,17 @@ pub(crate) mod test { #[test] fn error_on_linear_inter_graph_edge() -> Result<(), BuildError> { - let mut f_build = - FunctionBuilder::new("main", Signature::new(type_row![QB], type_row![QB]).into())?; + let mut f_build = FunctionBuilder::new( + "main", + FunctionType::new(type_row![QB], type_row![QB]).into(), + )?; let [i1] = f_build.input_wires_arr(); let noop = f_build.add_dataflow_op(LeafOp::Noop { ty: QB }, [i1])?; let i1 = noop.out_wire(0); let mut nested = - f_build.dfg_builder(Signature::new(type_row![], type_row![QB]), None, [])?; + f_build.dfg_builder(FunctionType::new(type_row![], type_row![QB]), None, [])?; let id_res = nested.add_dataflow_op(LeafOp::Noop { ty: QB }, [i1]); @@ -392,7 +394,7 @@ pub(crate) mod test { #[test] fn insert_hugr() -> Result<(), BuildError> { // Create a simple DFG - let mut dfg_builder = DFGBuilder::new(Signature::new(type_row![BIT], type_row![BIT]))?; + let mut dfg_builder = DFGBuilder::new(FunctionType::new(type_row![BIT], type_row![BIT]))?; let [i1] = dfg_builder.input_wires_arr(); dfg_builder.set_metadata("x", 42); let dfg_hugr = dfg_builder.finish_hugr_with_outputs([i1], &EMPTY_REG)?; @@ -402,7 +404,7 @@ pub(crate) mod test { let (dfg_node, f_node) = { let mut f_build = module_builder - .define_function("main", Signature::new(type_row![BIT], type_row![BIT]))?; + .define_function("main", FunctionType::new(type_row![BIT], type_row![BIT]))?; let [i1] = f_build.input_wires_arr(); let dfg = f_build.add_hugr_with_wires(dfg_hugr, [i1])?; @@ -430,15 +432,15 @@ pub(crate) mod test { let abc_extensions = ab_extensions.clone().union(xc.clone().into()); let parent_sig = - Signature::new(type_row![BIT], type_row![BIT]).with_extension_delta(abc_extensions); + FunctionType::new(type_row![BIT], type_row![BIT]).with_extension_delta(abc_extensions); let mut parent = DFGBuilder::new(parent_sig)?; let add_c_sig = - Signature::new(type_row![BIT], type_row![BIT]).with_extension_delta(xc.clone()); + FunctionType::new(type_row![BIT], type_row![BIT]).with_extension_delta(xc.clone()); let [w] = parent.input_wires_arr(); - let add_ab_sig = Signature::new(type_row![BIT], type_row![BIT]) + let add_ab_sig = FunctionType::new(type_row![BIT], type_row![BIT]) .with_extension_delta(ab_extensions.clone()); // A box which adds extensions A and B, via child Lift nodes @@ -494,7 +496,7 @@ pub(crate) mod test { #[test] fn non_cfg_ancestor() -> Result<(), BuildError> { - let unit_sig = Signature::new(type_row![Type::UNIT], type_row![Type::UNIT]); + let unit_sig = FunctionType::new(type_row![Type::UNIT], type_row![Type::UNIT]); let mut b = DFGBuilder::new(unit_sig.clone())?; let b_child = b.dfg_builder(unit_sig.clone(), None, [b.input().out_wire(0)])?; let b_child_in_wire = b_child.input().out_wire(0); @@ -518,7 +520,7 @@ pub(crate) mod test { #[test] fn no_relation_edge() -> Result<(), BuildError> { - let unit_sig = Signature::new(type_row![Type::UNIT], type_row![Type::UNIT]); + let unit_sig = FunctionType::new(type_row![Type::UNIT], type_row![Type::UNIT]); let mut b = DFGBuilder::new(unit_sig.clone())?; let mut b_child = b.dfg_builder(unit_sig.clone(), None, [b.input().out_wire(0)])?; let b_child_child = diff --git a/quantinuum-hugr/src/builder/module.rs b/quantinuum-hugr/src/builder/module.rs index f30e8690f..058ef7e5b 100644 --- a/quantinuum-hugr/src/builder/module.rs +++ b/quantinuum-hugr/src/builder/module.rs @@ -171,7 +171,7 @@ mod test { }, extension::{EMPTY_REG, PRELUDE_REGISTRY}, type_row, - types::Signature, + types::FunctionType, }; use super::*; @@ -182,7 +182,7 @@ mod test { let f_id = module_builder.declare( "main", - Signature::new(type_row![NAT], type_row![NAT]).into(), + FunctionType::new(type_row![NAT], type_row![NAT]).into(), )?; let mut f_build = module_builder.define_declaration(&f_id)?; @@ -205,7 +205,7 @@ mod test { let f_build = module_builder.define_function( "main", - Signature::new( + FunctionType::new( vec![qubit_state_type.get_alias_type()], vec![qubit_state_type.get_alias_type()], ), @@ -222,10 +222,14 @@ mod test { let build_result = { let mut module_builder = ModuleBuilder::new(); - let mut f_build = module_builder - .define_function("main", Signature::new(type_row![NAT], type_row![NAT, NAT]))?; - let local_build = f_build - .define_function("local", Signature::new(type_row![NAT], type_row![NAT, NAT]))?; + let mut f_build = module_builder.define_function( + "main", + FunctionType::new(type_row![NAT], type_row![NAT, NAT]), + )?; + let local_build = f_build.define_function( + "local", + FunctionType::new(type_row![NAT], type_row![NAT, NAT]), + )?; let [wire] = local_build.input_wires_arr(); let f_id = local_build.finish_with_outputs([wire, wire])?; diff --git a/quantinuum-hugr/src/builder/tail_loop.rs b/quantinuum-hugr/src/builder/tail_loop.rs index 7c03a98d8..d70f0d4e8 100644 --- a/quantinuum-hugr/src/builder/tail_loop.rs +++ b/quantinuum-hugr/src/builder/tail_loop.rs @@ -1,7 +1,7 @@ use crate::ops; use crate::hugr::{views::HugrView, NodeType}; -use crate::types::{Signature, TypeRow}; +use crate::types::{FunctionType, TypeRow}; use crate::{Hugr, Node}; use super::build_traits::SubContainer; @@ -20,7 +20,7 @@ impl + AsRef> TailLoopBuilder { loop_node: Node, tail_loop: &ops::TailLoop, ) -> Result { - let signature = Signature::new(tail_loop.body_input_row(), tail_loop.body_output_row()); + let signature = FunctionType::new(tail_loop.body_input_row(), tail_loop.body_output_row()); let dfg_build = DFGBuilder::create_with_io(base, loop_node, signature, None)?; Ok(TailLoopBuilder::from_dfg_builder(dfg_build)) @@ -126,7 +126,7 @@ mod test { let mut module_builder = ModuleBuilder::new(); let mut fbuild = module_builder.define_function( "main", - Signature::new(type_row![BIT], type_row![NAT]).with_extension_delta(PRELUDE_ID), + FunctionType::new(type_row![BIT], type_row![NAT]).with_extension_delta(PRELUDE_ID), )?; let _fdef = { let [b1] = fbuild diff --git a/quantinuum-hugr/src/extension/infer/test.rs b/quantinuum-hugr/src/extension/infer/test.rs index 2c5311377..1bb382372 100644 --- a/quantinuum-hugr/src/extension/infer/test.rs +++ b/quantinuum-hugr/src/extension/infer/test.rs @@ -21,7 +21,7 @@ use crate::{ }; use crate::type_row; -use crate::types::{Signature, Type, TypeRow}; +use crate::types::{FunctionType, Type, TypeRow}; use cool_asserts::assert_matches; use itertools::Itertools; @@ -41,7 +41,7 @@ const_extension_ids! { // them. fn from_graph() -> Result<(), Box> { let rs = ExtensionSet::from_iter([A, B, C]); - let main_sig = Signature::new(type_row![NAT, NAT], type_row![NAT]).with_extension_delta(rs); + let main_sig = FunctionType::new(type_row![NAT, NAT], type_row![NAT]).with_extension_delta(rs); let op = ops::DFG { signature: main_sig, @@ -58,14 +58,14 @@ fn from_graph() -> Result<(), Box> { assert_matches!(hugr.get_io(hugr.root()), Some(_)); - let add_a_sig = Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(A); + let add_a_sig = FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(A); - let add_b_sig = Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(B); + let add_b_sig = FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(B); - let add_ab_sig = Signature::new(type_row![NAT], type_row![NAT]) + let add_ab_sig = FunctionType::new(type_row![NAT], type_row![NAT]) .with_extension_delta(ExtensionSet::from_iter([A, B])); - let mult_c_sig = Signature::new(type_row![NAT, NAT], type_row![NAT]).with_extension_delta(C); + let mult_c_sig = FunctionType::new(type_row![NAT, NAT], type_row![NAT]).with_extension_delta(C); let add_a = hugr.add_node_with_parent( hugr.root(), @@ -221,7 +221,8 @@ fn dangling_src() -> Result<(), Box> { ); let [input, output] = hugr.get_io(hugr.root()).unwrap(); - let add_r_sig = Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(rs.clone()); + let add_r_sig = + FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(rs.clone()); let add_r = hugr.add_node_with_parent( hugr.root(), @@ -231,11 +232,11 @@ fn dangling_src() -> Result<(), Box> { ); // Dangling thingy - let src_sig = Signature::new(type_row![], type_row![NAT]); + let src_sig = FunctionType::new(type_row![], type_row![NAT]); let src = hugr.add_node_with_parent(hugr.root(), ops::DFG { signature: src_sig }); - let mult_sig = Signature::new(type_row![NAT, NAT], type_row![NAT]); + let mult_sig = FunctionType::new(type_row![NAT, NAT], type_row![NAT]); // Mult has open extension requirements, which we should solve to be "R" let mult = hugr.add_node_with_parent( hugr.root(), @@ -281,7 +282,7 @@ fn create_with_io( hugr: &mut Hugr, parent: Node, op: impl Into, - op_sig: Signature, + op_sig: FunctionType, ) -> Result<[Node; 3], Box> { let op: OpType = op.into(); @@ -354,7 +355,7 @@ fn test_conditional_inference() -> Result<(), Box> { let conditional_node = hugr.root(); let case_op = ops::Case { - signature: Signature::new(inputs, outputs).with_extension_delta(rs), + signature: FunctionType::new(inputs, outputs).with_extension_delta(rs), }; let case0_node = build_case(&mut hugr, conditional_node, case_op.clone(), A, B)?; @@ -377,7 +378,7 @@ fn test_conditional_inference() -> Result<(), Box> { #[test] fn extension_adding_sequence() -> Result<(), Box> { - let df_sig = Signature::new(type_row![NAT], type_row![NAT]); + let df_sig = FunctionType::new(type_row![NAT], type_row![NAT]); let mut hugr = Hugr::new(NodeType::new_open(ops::DFG { signature: df_sig @@ -438,7 +439,7 @@ fn extension_adding_sequence() -> Result<(), Box> { Ok(()) } -fn make_opaque(extension: impl Into, signature: Signature) -> ops::LeafOp { +fn make_opaque(extension: impl Into, signature: FunctionType) -> ops::LeafOp { let opaque = ops::custom::OpaqueOp::new(extension.into(), "", "".into(), vec![], signature); ops::custom::ExternalOp::from(opaque).into() } @@ -452,7 +453,7 @@ fn make_block( ) -> Result> { let sum_rows: Vec<_> = sum_rows.into_iter().collect(); let sum_type = Type::new_sum(sum_rows.clone()); - let dfb_sig = Signature::new(inputs.clone(), vec![sum_type]) + let dfb_sig = FunctionType::new(inputs.clone(), vec![sum_type]) .with_extension_delta(extension_delta.clone()); let dfb = ops::DataflowBlock { inputs, @@ -544,7 +545,7 @@ fn infer_cfg_test() -> Result<(), Box> { let bc = ExtensionSet::from_iter([B, C]); let mut hugr = Hugr::new(NodeType::new_open(ops::CFG { - signature: Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(abc), + signature: FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(abc), })); let root = hugr.root(); @@ -562,7 +563,7 @@ fn infer_cfg_test() -> Result<(), Box> { entry, make_opaque( A, - Signature::new(vec![NAT], twoway(NAT)).with_extension_delta(A), + FunctionType::new(vec![NAT], twoway(NAT)).with_extension_delta(A), ), ); @@ -642,7 +643,7 @@ fn infer_cfg_test() -> Result<(), Box> { #[test] fn multi_entry() -> Result<(), Box> { let mut hugr = Hugr::new(NodeType::new_open(ops::CFG { - signature: Signature::new(type_row![NAT], type_row![NAT]), // maybe add extensions? + signature: FunctionType::new(type_row![NAT], type_row![NAT]), // maybe add extensions? })); let cfg = hugr.root(); let ([entry, entry_in, entry_out], exit) = create_entry_exit( @@ -656,7 +657,7 @@ fn multi_entry() -> Result<(), Box> { let entry_mid = hugr.add_node_with_parent( entry, - make_opaque(UNKNOWN_EXTENSION, Signature::new(vec![NAT], twoway(NAT))), + make_opaque(UNKNOWN_EXTENSION, FunctionType::new(vec![NAT], twoway(NAT))), ); hugr.connect(entry_in, 0, entry_mid, 0); @@ -728,7 +729,8 @@ fn make_looping_cfg( .union(bb2_ext.clone()); let mut hugr = Hugr::new(NodeType::new_open(ops::CFG { - signature: Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(hugr_delta), + signature: FunctionType::new(type_row![NAT], type_row![NAT]) + .with_extension_delta(hugr_delta), })); let root = hugr.root(); @@ -746,7 +748,7 @@ fn make_looping_cfg( entry, make_opaque( UNKNOWN_EXTENSION, - Signature::new(vec![NAT], oneway(NAT)).with_extension_delta(entry_ext), + FunctionType::new(vec![NAT], oneway(NAT)).with_extension_delta(entry_ext), ), ); @@ -803,7 +805,7 @@ fn simple_cfg_loop() -> Result<(), Box> { let mut hugr = Hugr::new(NodeType::new( ops::CFG { - signature: Signature::new(type_row![NAT], type_row![NAT]).with_extension_delta(A), + signature: FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(A), }, Some(A.into()), )); @@ -821,7 +823,7 @@ fn simple_cfg_loop() -> Result<(), Box> { let entry_mid = hugr.add_node_with_parent( entry, - make_opaque(UNKNOWN_EXTENSION, Signature::new(vec![NAT], oneway(NAT))), + make_opaque(UNKNOWN_EXTENSION, FunctionType::new(vec![NAT], oneway(NAT))), ); hugr.connect(entry_in, 0, entry_mid, 0); @@ -849,7 +851,7 @@ fn simple_cfg_loop() -> Result<(), Box> { #[test] fn plus_on_self() -> Result<(), Box> { let ext = ExtensionId::new("unknown1").unwrap(); - let ft = Signature::new_endo(type_row![QB_T, QB_T]).with_extension_delta(ext.clone()); + let ft = FunctionType::new_endo(type_row![QB_T, QB_T]).with_extension_delta(ext.clone()); let mut dfg = DFGBuilder::new(ft.clone())?; // While https://github.com/CQCL/hugr/issues/388 is unsolved, @@ -863,7 +865,7 @@ fn plus_on_self() -> Result<(), Box> { ft, )) .into(); - let unary_sig = Signature::new_endo(type_row![QB_T]).with_extension_delta(ext.clone()); + let unary_sig = FunctionType::new_endo(type_row![QB_T]).with_extension_delta(ext.clone()); let unop: LeafOp = ExternalOp::Opaque(OpaqueOp::new( ext, "1qb_op", @@ -938,7 +940,7 @@ fn simple_funcdefn() -> Result<(), Box> { let mut builder = ModuleBuilder::new(); let mut func_builder = builder.define_function( "F", - Signature::new(vec![NAT], vec![NAT]).with_extension_delta(A), + FunctionType::new(vec![NAT], vec![NAT]).with_extension_delta(A), )?; let [w] = func_builder.input_wires_arr(); diff --git a/quantinuum-hugr/src/extension/op_def.rs b/quantinuum-hugr/src/extension/op_def.rs index 4eaaa9b9a..d901c6c7e 100644 --- a/quantinuum-hugr/src/extension/op_def.rs +++ b/quantinuum-hugr/src/extension/op_def.rs @@ -12,7 +12,7 @@ use super::{ }; use crate::types::type_param::{check_type_args, TypeArg, TypeParam}; -use crate::types::{FuncTypeVarLen, PolyFuncType, Signature}; +use crate::types::{FuncTypeVarLen, FunctionType, PolyFuncType}; use crate::Hugr; /// Trait necessary for binary computations of OpDef signature @@ -231,7 +231,7 @@ impl SignatureFunc { def: &OpDef, args: &[TypeArg], exts: &ExtensionRegistry, - ) -> Result { + ) -> Result { let temp: PolyFuncType; let (pf, args) = match &self { SignatureFunc::TypeScheme(custom) => { @@ -357,7 +357,7 @@ impl OpDef { &self, args: &[TypeArg], exts: &ExtensionRegistry, - ) -> Result { + ) -> Result { self.signature_func.compute_signature(self, args, exts) } @@ -486,7 +486,7 @@ mod test { use crate::ops::custom::ExternalOp; use crate::ops::LeafOp; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; - use crate::types::{type_param::TypeParam, FuncTypeVarLen, Signature, TypeArg, TypeBound}; + use crate::types::{type_param::TypeParam, FuncTypeVarLen, FunctionType, TypeArg, TypeBound}; use crate::types::{PolyFuncType, Type}; use crate::Hugr; use crate::{const_extension_ids, Extension}; @@ -518,7 +518,7 @@ mod test { let list_usize = Type::new_extension(list_def.instantiate(vec![TypeArg::Type { ty: USIZE_T }])?); - let mut dfg = DFGBuilder::new(Signature::new_endo(vec![list_usize]))?; + let mut dfg = DFGBuilder::new(FunctionType::new_endo(vec![list_usize]))?; let rev = dfg.add_dataflow_op( LeafOp::from(ExternalOp::Extension( e.instantiate_extension_op(&OP_NAME, vec![TypeArg::Type { ty: USIZE_T }], ®) @@ -570,7 +570,7 @@ mod test { let args = [TypeArg::BoundedNat { n: 3 }, USIZE_T.into()]; assert_eq!( def.compute_signature(&args, &PRELUDE_REGISTRY), - Ok(Signature::new( + Ok(FunctionType::new( vec![USIZE_T; 3], vec![Type::new_tuple(vec![USIZE_T; 3])] )) @@ -583,7 +583,7 @@ mod test { let args = [TypeArg::BoundedNat { n: 3 }, tyvar.clone().into()]; assert_eq!( def.compute_signature(&args, &PRELUDE_REGISTRY), - Ok(Signature::new( + Ok(FunctionType::new( tyvars.clone(), vec![Type::new_tuple(tyvars)] )) @@ -639,7 +639,7 @@ mod test { def.validate_args(&args, &EMPTY_REG, &decls).unwrap(); assert_eq!( def.compute_signature(&args, &EMPTY_REG), - Ok(Signature::new_endo(vec![tv])) + Ok(FunctionType::new_endo(vec![tv])) ); Ok(()) } diff --git a/quantinuum-hugr/src/extension/prelude.rs b/quantinuum-hugr/src/extension/prelude.rs index 21f09c790..ee8b7b576 100644 --- a/quantinuum-hugr/src/extension/prelude.rs +++ b/quantinuum-hugr/src/extension/prelude.rs @@ -238,7 +238,7 @@ impl CustomConst for ConstError { mod test { use crate::{ builder::{DFGBuilder, Dataflow, DataflowHugr}, - types::Signature, + types::FunctionType, }; use super::*; @@ -246,7 +246,7 @@ mod test { #[test] /// Test building a HUGR involving a new_array operation. fn test_new_array() { - let mut b = DFGBuilder::new(Signature::new( + let mut b = DFGBuilder::new(FunctionType::new( vec![QB_T, QB_T], vec![array_type(TypeArg::BoundedNat { n: 2 }, QB_T)], )) @@ -286,7 +286,7 @@ mod test { assert!(error_val.equal_consts(&ConstError::new(2, "my message"))); assert!(!error_val.equal_consts(&ConstError::new(3, "my message"))); - let mut b = DFGBuilder::new(Signature::new_endo(type_row![])).unwrap(); + let mut b = DFGBuilder::new(FunctionType::new_endo(type_row![])).unwrap(); let err = b.add_load_const(error_val); diff --git a/quantinuum-hugr/src/hugr.rs b/quantinuum-hugr/src/hugr.rs index ef7986376..1e597f8d2 100644 --- a/quantinuum-hugr/src/hugr.rs +++ b/quantinuum-hugr/src/hugr.rs @@ -30,7 +30,7 @@ use crate::extension::infer_extensions; use crate::extension::{ExtensionRegistry, ExtensionSet, ExtensionSolution, InferExtensionError}; use crate::ops::custom::resolve_extension_ops; use crate::ops::{OpTag, OpTrait, OpType, DEFAULT_OPTYPE}; -use crate::types::Signature; +use crate::types::FunctionType; use crate::{Direction, Node}; use delegate::delegate; @@ -108,7 +108,7 @@ impl NodeType { } /// Get the function type from the embedded op - pub fn op_signature(&self) -> Option { + pub fn op_signature(&self) -> Option { self.op.dataflow_signature() } diff --git a/quantinuum-hugr/src/hugr/hugrmut.rs b/quantinuum-hugr/src/hugr/hugrmut.rs index 865ea4ea1..a0be5aade 100644 --- a/quantinuum-hugr/src/hugr/hugrmut.rs +++ b/quantinuum-hugr/src/hugr/hugrmut.rs @@ -677,7 +677,7 @@ mod test { extension::PRELUDE_REGISTRY, macros::type_row, ops::{self, dataflow::IOTrait, LeafOp}, - types::{Signature, Type}, + types::{FunctionType, Type}, }; use super::*; @@ -696,7 +696,7 @@ mod test { module, ops::FuncDefn { name: "main".into(), - signature: Signature::new(type_row![NAT], type_row![NAT, NAT]).into(), + signature: FunctionType::new(type_row![NAT], type_row![NAT, NAT]).into(), }, ); diff --git a/quantinuum-hugr/src/hugr/rewrite/consts.rs b/quantinuum-hugr/src/hugr/rewrite/consts.rs index dc01449f9..d48551e94 100644 --- a/quantinuum-hugr/src/hugr/rewrite/consts.rs +++ b/quantinuum-hugr/src/hugr/rewrite/consts.rs @@ -121,14 +121,14 @@ mod test { hugr::HugrMut, ops::{handle::NodeHandle, LeafOp}, type_row, - types::Signature, + types::FunctionType, }; #[test] fn test_const_remove() -> Result<(), Box> { let mut build = ModuleBuilder::new(); let con_node = build.add_constant(ConstUsize::new(2)); - let mut dfg_build = build.define_function("main", Signature::new_endo(type_row![]))?; + let mut dfg_build = build.define_function("main", FunctionType::new_endo(type_row![]))?; let load_1 = dfg_build.load_const(&con_node); let load_2 = dfg_build.load_const(&con_node); let tup = dfg_build.add_dataflow_op( diff --git a/quantinuum-hugr/src/hugr/rewrite/inline_dfg.rs b/quantinuum-hugr/src/hugr/rewrite/inline_dfg.rs index 95b5f886d..e5a6c4062 100644 --- a/quantinuum-hugr/src/hugr/rewrite/inline_dfg.rs +++ b/quantinuum-hugr/src/hugr/rewrite/inline_dfg.rs @@ -143,7 +143,7 @@ mod test { use crate::std_extensions::arithmetic::float_types; use crate::std_extensions::arithmetic::int_ops::{self, IntOpDef}; use crate::std_extensions::arithmetic::int_types::{self, ConstIntU}; - use crate::types::Signature; + use crate::types::FunctionType; use crate::utils::test_quantum_extension; use crate::{type_row, Direction, HugrView, Node, Port}; use crate::{Hugr, Wire}; @@ -175,7 +175,7 @@ mod test { let int_ty = &int_types::INT_TYPES[6]; let mut outer = DFGBuilder::new( - Signature::new(vec![int_ty.clone(); 2], vec![int_ty.clone()]) + FunctionType::new(vec![int_ty.clone(); 2], vec![int_ty.clone()]) .with_extension_delta(delta.clone()), )?; let [a, b] = outer.input_wires_arr(); @@ -199,7 +199,7 @@ mod test { let c1 = nonlocal.then(|| make_const(&mut outer)); let inner = { let mut inner = outer.dfg_builder( - Signature::new_endo(vec![int_ty.clone()]).with_extension_delta(delta), + FunctionType::new_endo(vec![int_ty.clone()]).with_extension_delta(delta), None, [a], )?; @@ -252,7 +252,7 @@ mod test { #[test] fn permutation() -> Result<(), Box> { let mut h = DFGBuilder::new( - Signature::new_endo(type_row![QB_T, QB_T]) + FunctionType::new_endo(type_row![QB_T, QB_T]) .with_extension_delta(test_quantum_extension::EXTENSION_ID), )?; let [p, q] = h.input_wires_arr(); @@ -260,7 +260,11 @@ mod test { .add_dataflow_op(test_quantum_extension::h_gate(), [p])? .outputs_arr(); let swap = { - let swap = h.dfg_builder(Signature::new_endo(type_row![QB_T, QB_T]), None, [p_h, q])?; + let swap = h.dfg_builder( + FunctionType::new_endo(type_row![QB_T, QB_T]), + None, + [p_h, q], + )?; let [a, b] = swap.input_wires_arr(); swap.finish_with_outputs([b, a])? }; @@ -350,14 +354,14 @@ mod test { ]) .unwrap(); let mut outer = DFGBuilder::new( - Signature::new_endo(type_row![QB_T, QB_T]) + FunctionType::new_endo(type_row![QB_T, QB_T]) .with_extension_delta(float_types::EXTENSION_ID), )?; let [a, b] = outer.input_wires_arr(); let h_a = outer.add_dataflow_op(test_quantum_extension::h_gate(), [a])?; let h_b = outer.add_dataflow_op(test_quantum_extension::h_gate(), [b])?; let mut inner = outer.dfg_builder( - Signature::new_endo(type_row![QB_T]).with_extension_delta(float_types::EXTENSION_ID), + FunctionType::new_endo(type_row![QB_T]).with_extension_delta(float_types::EXTENSION_ID), None, h_b.outputs(), )?; diff --git a/quantinuum-hugr/src/hugr/rewrite/outline_cfg.rs b/quantinuum-hugr/src/hugr/rewrite/outline_cfg.rs index 8559adf72..88c1b2bd1 100644 --- a/quantinuum-hugr/src/hugr/rewrite/outline_cfg.rs +++ b/quantinuum-hugr/src/hugr/rewrite/outline_cfg.rs @@ -258,7 +258,7 @@ mod test { use crate::hugr::views::sibling::SiblingMut; use crate::hugr::HugrMut; use crate::ops::handle::{BasicBlockID, CfgID, NodeHandle}; - use crate::types::Signature; + use crate::types::FunctionType; use crate::{type_row, HugrView, Node}; use cool_asserts::assert_matches; use itertools::Itertools; @@ -351,7 +351,7 @@ mod test { let mut fbuild = module_builder .define_function( "main", - Signature::new(type_row![USIZE_T], type_row![USIZE_T]), + FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]), ) .unwrap(); let [i1] = fbuild.input_wires_arr(); diff --git a/quantinuum-hugr/src/hugr/rewrite/replace.rs b/quantinuum-hugr/src/hugr/rewrite/replace.rs index 717c26835..0d7de9923 100644 --- a/quantinuum-hugr/src/hugr/rewrite/replace.rs +++ b/quantinuum-hugr/src/hugr/rewrite/replace.rs @@ -458,7 +458,7 @@ mod test { use crate::ops::handle::{BasicBlockID, ConstID, NodeHandle}; use crate::ops::{self, Case, DataflowBlock, LeafOp, OpTag, OpType, DFG}; use crate::std_extensions::collections; - use crate::types::{Signature, Type, TypeArg, TypeRow}; + use crate::types::{FunctionType, Type, TypeArg, TypeRow}; use crate::{type_row, Direction, Hugr, HugrView, OutgoingPort}; use super::{NewEdgeKind, NewEdgeSpec, ReplaceError, Replacement}; @@ -489,7 +489,7 @@ mod test { let mut cfg = CFGBuilder::new( // One might expect an extension_delta of "collections" here, but push/pop // have an empty delta themselves, pending https://github.com/CQCL/hugr/issues/388 - Signature::new_endo(just_list.clone()), + FunctionType::new_endo(just_list.clone()), )?; let pred_const = cfg.add_constant(ops::Const::unary_unit_sum()); @@ -520,7 +520,7 @@ mod test { // Replacement: one BB with two DFGs inside. // Use Hugr rather than Builder because DFGs must be empty (not even Input/Output). let mut replacement = Hugr::new(NodeType::new_open(ops::CFG { - signature: Signature::new_endo(just_list.clone()), + signature: FunctionType::new_endo(just_list.clone()), })); let r_bb = replacement.add_node_with_parent( replacement.root(), @@ -536,13 +536,16 @@ mod test { let r_df1 = replacement.add_node_with_parent( r_bb, DFG { - signature: Signature::new(vec![listy.clone()], simple_unary_plus(intermed.clone())), + signature: FunctionType::new( + vec![listy.clone()], + simple_unary_plus(intermed.clone()), + ), }, ); let r_df2 = replacement.add_node_with_parent( r_bb, DFG { - signature: Signature::new(intermed, simple_unary_plus(just_list.clone())), + signature: FunctionType::new(intermed, simple_unary_plus(just_list.clone())), }, ); [0, 1] @@ -643,7 +646,7 @@ mod test { #[test] fn test_invalid() -> Result<(), Box> { - let utou = Signature::new_endo(vec![USIZE_T]); + let utou = FunctionType::new_endo(vec![USIZE_T]); let mk_op = |s| { LeafOp::from(ExternalOp::Opaque(OpaqueOp::new( ExtensionId::new("unknown_ext").unwrap(), @@ -653,7 +656,7 @@ mod test { utou.clone(), ))) }; - let mut h = DFGBuilder::new(Signature::new( + let mut h = DFGBuilder::new(FunctionType::new( type_row![USIZE_T, BOOL_T], type_row![USIZE_T], ))?; diff --git a/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs b/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs index 26cc1f5c3..f18bf7387 100644 --- a/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs +++ b/quantinuum-hugr/src/hugr/rewrite/simple_replace.rs @@ -212,7 +212,7 @@ pub(in crate::hugr::rewrite) mod test { use crate::ops::{OpTrait, OpType}; use crate::std_extensions::logic::test::and_op; use crate::type_row; - use crate::types::{Signature, Type}; + use crate::types::{FunctionType, Type}; use crate::utils::test_quantum_extension::{cx_gate, h_gate}; use crate::{IncomingPort, Node}; @@ -234,7 +234,7 @@ pub(in crate::hugr::rewrite) mod test { let _f_id = { let mut func_builder = module_builder.define_function( "main", - Signature::new(type_row![QB, QB, QB], type_row![QB, QB, QB]), + FunctionType::new(type_row![QB, QB, QB], type_row![QB, QB, QB]), )?; let [qb0, qb1, qb2] = func_builder.input_wires_arr(); @@ -242,7 +242,7 @@ pub(in crate::hugr::rewrite) mod test { let q_out = func_builder.add_dataflow_op(h_gate(), vec![qb2])?; let mut inner_builder = func_builder.dfg_builder( - Signature::new(type_row![QB, QB], type_row![QB, QB]), + FunctionType::new(type_row![QB, QB], type_row![QB, QB]), None, [qb0, qb1], )?; @@ -275,7 +275,7 @@ pub(in crate::hugr::rewrite) mod test { /// └───┘└───┘ fn make_dfg_hugr() -> Result { let mut dfg_builder = - DFGBuilder::new(Signature::new(type_row![QB, QB], type_row![QB, QB]))?; + DFGBuilder::new(FunctionType::new(type_row![QB, QB], type_row![QB, QB]))?; let [wire0, wire1] = dfg_builder.input_wires_arr(); let wire2 = dfg_builder.add_dataflow_op(h_gate(), vec![wire0])?; let wire3 = dfg_builder.add_dataflow_op(h_gate(), vec![wire1])?; @@ -296,7 +296,7 @@ pub(in crate::hugr::rewrite) mod test { /// └───┘ fn make_dfg_hugr2() -> Result { let mut dfg_builder = - DFGBuilder::new(Signature::new(type_row![QB, QB], type_row![QB, QB]))?; + DFGBuilder::new(FunctionType::new(type_row![QB, QB], type_row![QB, QB]))?; let [wire0, wire1] = dfg_builder.input_wires_arr(); let wire2 = dfg_builder.add_dataflow_op(h_gate(), vec![wire1])?; let wire2out = wire2.outputs().exactly_one().unwrap(); @@ -466,7 +466,7 @@ pub(in crate::hugr::rewrite) mod test { #[test] fn test_replace_cx_cross() { let q_row: Vec = vec![QB, QB]; - let mut builder = DFGBuilder::new(Signature::new(q_row.clone(), q_row)).unwrap(); + let mut builder = DFGBuilder::new(FunctionType::new(q_row.clone(), q_row)).unwrap(); let mut circ = builder.as_circuit(builder.input_wires()); circ.append(cx_gate(), [0, 1]).unwrap(); circ.append(cx_gate(), [1, 0]).unwrap(); @@ -525,7 +525,7 @@ pub(in crate::hugr::rewrite) mod test { let two_bit = type_row![BOOL_T, BOOL_T]; let mut builder = - DFGBuilder::new(Signature::new(one_bit.clone(), one_bit.clone())).unwrap(); + DFGBuilder::new(FunctionType::new(one_bit.clone(), one_bit.clone())).unwrap(); let inw = builder.input_wires().exactly_one().unwrap(); let outw = builder .add_dataflow_op(and_op(), [inw, inw]) @@ -534,7 +534,7 @@ pub(in crate::hugr::rewrite) mod test { let [input, _] = builder.io(); let mut h = builder.finish_hugr_with_outputs(outw, &EMPTY_REG).unwrap(); - let mut builder = DFGBuilder::new(Signature::new(two_bit, one_bit)).unwrap(); + let mut builder = DFGBuilder::new(FunctionType::new(two_bit, one_bit)).unwrap(); let inw = builder.input_wires(); let outw = builder.add_dataflow_op(and_op(), inw).unwrap().outputs(); let [repl_input, repl_output] = builder.io(); diff --git a/quantinuum-hugr/src/hugr/serialize.rs b/quantinuum-hugr/src/hugr/serialize.rs index d87d9e27f..d3e3d13a2 100644 --- a/quantinuum-hugr/src/hugr/serialize.rs +++ b/quantinuum-hugr/src/hugr/serialize.rs @@ -267,7 +267,7 @@ pub mod test { use crate::std_extensions::arithmetic::float_ops::FLOAT_OPS_REGISTRY; use crate::std_extensions::arithmetic::float_types::{ConstF64, FLOAT64_TYPE}; use crate::std_extensions::logic::NotOp; - use crate::types::{Signature, Type}; + use crate::types::{FunctionType, Type}; use crate::{type_row, OutgoingPort}; use itertools::Itertools; use jsonschema::{Draft, JSONSchema}; @@ -382,7 +382,7 @@ pub mod test { let outputs = g.num_outputs(node); match (inputs == 0, outputs == 0) { (false, false) => DFG { - signature: Signature::new(vec![NAT; inputs - 1], vec![NAT; outputs - 1]), + signature: FunctionType::new(vec![NAT; inputs - 1], vec![NAT; outputs - 1]), } .into(), (true, false) => Input::new(vec![NAT; outputs - 1]).into(), @@ -436,7 +436,7 @@ pub mod test { let t_row = vec![Type::new_sum([type_row![NAT], type_row![QB]])]; let mut f_build = module_builder - .define_function("main", Signature::new(t_row.clone(), t_row)) + .define_function("main", FunctionType::new(t_row.clone(), t_row)) .unwrap(); let outputs = f_build @@ -465,7 +465,7 @@ pub mod test { #[test] fn dfg_roundtrip() -> Result<(), Box> { let tp: Vec = vec![BOOL_T; 2]; - let mut dfg = DFGBuilder::new(Signature::new(tp.clone(), tp))?; + let mut dfg = DFGBuilder::new(FunctionType::new(tp.clone(), tp))?; let mut params: [_; 2] = dfg.input_wires_arr(); for p in params.iter_mut() { *p = dfg @@ -482,7 +482,7 @@ pub mod test { #[test] fn opaque_ops() -> Result<(), Box> { let tp: Vec = vec![BOOL_T; 1]; - let mut dfg = DFGBuilder::new(Signature::new_endo(tp))?; + let mut dfg = DFGBuilder::new(FunctionType::new_endo(tp))?; let [wire] = dfg.input_wires_arr(); // Add an extension operation @@ -504,7 +504,7 @@ pub mod test { #[test] fn hierarchy_order() -> Result<(), Box> { - let mut hugr = closed_dfg_root_hugr(Signature::new(vec![QB], vec![QB])); + let mut hugr = closed_dfg_root_hugr(FunctionType::new(vec![QB], vec![QB])); let [old_in, out] = hugr.get_io(hugr.root()).unwrap(); hugr.connect(old_in, 0, out, 0); @@ -527,7 +527,7 @@ pub mod test { // Miri doesn't run the extension registration required by `typetag` for registering `CustomConst`s. // https://github.com/rust-lang/miri/issues/450 fn constants_roundtrip() -> Result<(), Box> { - let mut builder = DFGBuilder::new(Signature::new(vec![], vec![FLOAT64_TYPE])).unwrap(); + let mut builder = DFGBuilder::new(FunctionType::new(vec![], vec![FLOAT64_TYPE])).unwrap(); let w = builder.add_load_const(ConstF64::new(0.5)); let hugr = builder.finish_hugr_with_outputs([w], &FLOAT_OPS_REGISTRY)?; diff --git a/quantinuum-hugr/src/hugr/validate/test.rs b/quantinuum-hugr/src/hugr/validate/test.rs index b82ed594f..3861fa140 100644 --- a/quantinuum-hugr/src/hugr/validate/test.rs +++ b/quantinuum-hugr/src/hugr/validate/test.rs @@ -17,7 +17,7 @@ use crate::std_extensions::logic::{self, NotOp}; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; use crate::types::type_row::RowVarOrType; use crate::types::{ - CustomType, FuncTypeVarLen, PolyFixedFunc, Signature, Type, TypeBound, TypeRow, + CustomType, FuncTypeVarLen, FunctionType, PolyFixedFunc, Type, TypeBound, TypeRow, }; use crate::{type_row, Direction, IncomingPort, Node}; @@ -29,7 +29,7 @@ const NAT: Type = crate::extension::prelude::USIZE_T; fn make_simple_hugr(copies: usize) -> (Hugr, Node) { let def_op: OpType = ops::FuncDefn { name: "main".into(), - signature: Signature::new(type_row![BOOL_T], vec![BOOL_T; copies]).into(), + signature: FunctionType::new(type_row![BOOL_T], vec![BOOL_T; copies]).into(), } .into(); @@ -62,7 +62,7 @@ fn add_df_children(b: &mut Hugr, parent: Node, copies: usize) -> (Node, Node, No fn invalid_root() { let declare_op: OpType = ops::FuncDecl { name: "main".into(), - signature: Signature::default().into(), + signature: FunctionType::default().into(), } .into(); @@ -103,7 +103,7 @@ fn leaf_root() { #[test] fn dfg_root() { let dfg_op: OpType = ops::DFG { - signature: Signature::new_endo(type_row![BOOL_T]), + signature: FunctionType::new_endo(type_row![BOOL_T]), } .into(); @@ -132,7 +132,7 @@ fn children_restrictions() { .unwrap(); // Add a definition without children - let def_sig = Signature::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]); + let def_sig = FunctionType::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]); let new_def = b.add_node_with_parent( root, ops::FuncDefn { @@ -215,14 +215,17 @@ fn df_children_restrictions() { #[test] fn test_ext_edge() { - let mut h = closed_dfg_root_hugr(Signature::new(type_row![BOOL_T, BOOL_T], type_row![BOOL_T])); + let mut h = closed_dfg_root_hugr(FunctionType::new( + type_row![BOOL_T, BOOL_T], + type_row![BOOL_T], + )); let [input, output] = h.get_io(h.root()).unwrap(); // Nested DFG BOOL_T -> BOOL_T let sub_dfg = h.add_node_with_parent( h.root(), ops::DFG { - signature: Signature::new_endo(type_row![BOOL_T]), + signature: FunctionType::new_endo(type_row![BOOL_T]), }, ); // this Xor has its 2nd input unconnected @@ -257,7 +260,7 @@ fn test_ext_edge() { #[test] fn test_local_const() { - let mut h = closed_dfg_root_hugr(Signature::new(type_row![BOOL_T], type_row![BOOL_T])); + let mut h = closed_dfg_root_hugr(FunctionType::new(type_row![BOOL_T], type_row![BOOL_T])); let [input, output] = h.get_io(h.root()).unwrap(); let and = h.add_node_with_parent(h.root(), and_op()); h.connect(input, 0, and, 0); @@ -288,7 +291,10 @@ fn test_local_const() { #[test] fn dfg_with_cycles() { - let mut h = closed_dfg_root_hugr(Signature::new(type_row![BOOL_T, BOOL_T], type_row![BOOL_T])); + let mut h = closed_dfg_root_hugr(FunctionType::new( + type_row![BOOL_T, BOOL_T], + type_row![BOOL_T], + )); let [input, output] = h.get_io(h.root()).unwrap(); let or = h.add_node_with_parent(h.root(), or_op()); let not1 = h.add_node_with_parent(h.root(), NotOp); @@ -310,7 +316,7 @@ fn identity_hugr_with_type(t: Type) -> (Hugr, Node) { b.root(), ops::FuncDefn { name: "main".into(), - signature: Signature::new(row.clone(), row.clone()).into(), + signature: FunctionType::new(row.clone(), row.clone()).into(), }, ); @@ -431,7 +437,7 @@ fn typevars_declared() -> Result<(), Box> { "myfunc", PolyFixedFunc::new( [TypeBound::Any.into()], - Signature::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; let [w] = f.input_wires_arr(); @@ -441,7 +447,7 @@ fn typevars_declared() -> Result<(), Box> { "myfunc", PolyFixedFunc::new( [TypeBound::Any.into()], - Signature::new_endo(vec![Type::new_var_use(1, TypeBound::Any)]), + FunctionType::new_endo(vec![Type::new_var_use(1, TypeBound::Any)]), ), )?; let [w] = f.input_wires_arr(); @@ -451,7 +457,7 @@ fn typevars_declared() -> Result<(), Box> { "myfunc", PolyFixedFunc::new( [TypeBound::Any.into()], - Signature::new_endo(vec![Type::new_var_use(1, TypeBound::Copyable)]), + FunctionType::new_endo(vec![Type::new_var_use(1, TypeBound::Copyable)]), ), )?; let [w] = f.input_wires_arr(); @@ -469,12 +475,12 @@ fn nested_typevars() -> Result<(), Box> { "outer", PolyFixedFunc::new( [OUTER_BOUND.into()], - Signature::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; let inner = outer.define_function( "inner", - PolyFixedFunc::new([INNER_BOUND.into()], Signature::new_endo(vec![t])), + PolyFixedFunc::new([INNER_BOUND.into()], FunctionType::new_endo(vec![t])), )?; let [w] = inner.input_wires_arr(); inner.finish_with_outputs([w])?; @@ -515,7 +521,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { "myfunc", PolyFixedFunc::new( [BOUND], - Signature::new(type_row![], vec![list_of_var.clone()]) + FunctionType::new(type_row![], vec![list_of_var.clone()]) .with_extension_delta(collections::EXTENSION_NAME), ), )?; @@ -548,7 +554,7 @@ fn inner_row_variables() -> Result<(), Box> { [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Any }), }], - Signature::new_endo(vec![inner_ft.clone()]), + FunctionType::new_endo(vec![inner_ft.clone()]), ), )?; // All the wires here are carrying higher-order Function values @@ -567,7 +573,7 @@ fn no_outer_row_variables() -> Result<(), Box> { [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Any }), }], - Signature::new_endo(vec![tv]), + FunctionType::new_endo(vec![tv]), ), )?; // Input and Output nodes have a Port whose type is List(Type(Any)) @@ -592,10 +598,10 @@ fn test_polymorphic_call() -> Result<(), Box> { "id", PolyFixedFunc::new( vec![TypeBound::Any.into()], - Signature::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), + FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; - let mut f = m.define_function("main", Signature::new_endo(vec![USIZE_T]))?; + let mut f = m.define_function("main", FunctionType::new_endo(vec![USIZE_T]))?; let c = f.call(&id, &[USIZE_T.into()], f.input_wires(), &PRELUDE_REGISTRY)?; f.finish_with_outputs(c.outputs())?; let _ = m.finish_prelude_hugr()?; diff --git a/quantinuum-hugr/src/hugr/views.rs b/quantinuum-hugr/src/hugr/views.rs index bad59d3c6..ee58cf850 100644 --- a/quantinuum-hugr/src/hugr/views.rs +++ b/quantinuum-hugr/src/hugr/views.rs @@ -29,7 +29,7 @@ use crate::ops::handle::NodeHandle; use crate::ops::{OpParent, OpTag, OpTrait, OpType}; use crate::types::Type; -use crate::types::{EdgeKind, PolyFixedFunc, Signature}; +use crate::types::{EdgeKind, FunctionType, PolyFixedFunc}; use crate::{Direction, IncomingPort, Node, OutgoingPort, Port}; use itertools::Either; @@ -336,7 +336,7 @@ pub trait HugrView: sealed::HugrInternals { /// /// In contrast to [`get_function_type`][HugrView::get_function_type], this /// method always return a concrete [`Signature`]. - fn get_df_function_type(&self) -> Option { + fn get_df_function_type(&self) -> Option { let op = self.get_optype(self.root()); op.inner_function_type() } @@ -435,7 +435,7 @@ pub trait HugrView: sealed::HugrInternals { /// Get the "signature" (incoming and outgoing types) of a node, non-Value /// kind ports will be missing. - fn signature(&self, node: Node) -> Option { + fn signature(&self, node: Node) -> Option { self.get_optype(node).dataflow_signature() } diff --git a/quantinuum-hugr/src/hugr/views/descendants.rs b/quantinuum-hugr/src/hugr/views/descendants.rs index 6aa0b231e..58831c325 100644 --- a/quantinuum-hugr/src/hugr/views/descendants.rs +++ b/quantinuum-hugr/src/hugr/views/descendants.rs @@ -203,7 +203,7 @@ pub(super) mod test { builder::{Container, Dataflow, DataflowSubContainer, HugrBuilder, ModuleBuilder}, ops::handle::NodeHandle, type_row, - types::{Signature, Type}, + types::{FunctionType, Type}, utils::test_quantum_extension::h_gate, }; @@ -222,7 +222,7 @@ pub(super) mod test { let (f_id, inner_id) = { let mut func_builder = module_builder.define_function( "main", - Signature::new(type_row![NAT, QB], type_row![NAT, QB]), + FunctionType::new(type_row![NAT, QB], type_row![NAT, QB]), )?; let [int, qb] = func_builder.input_wires_arr(); @@ -231,7 +231,7 @@ pub(super) mod test { let inner_id = { let inner_builder = func_builder.dfg_builder( - Signature::new(type_row![NAT], type_row![NAT]), + FunctionType::new(type_row![NAT], type_row![NAT]), None, [int], )?; @@ -261,12 +261,12 @@ pub(super) mod test { assert_eq!( region.get_function_type(), - Some(Signature::new_endo(type_row![NAT, QB]).into()) + 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(Signature::new(type_row![NAT], type_row![NAT]).into()) + Some(FunctionType::new(type_row![NAT], type_row![NAT]).into()) ); Ok(()) diff --git a/quantinuum-hugr/src/hugr/views/root_checked.rs b/quantinuum-hugr/src/hugr/views/root_checked.rs index 10832466b..b21ac2abb 100644 --- a/quantinuum-hugr/src/hugr/views/root_checked.rs +++ b/quantinuum-hugr/src/hugr/views/root_checked.rs @@ -75,13 +75,13 @@ mod test { use crate::hugr::{HugrError, HugrMut, NodeType}; use crate::ops::handle::{BasicBlockID, CfgID, DataflowParentID, DfgID}; use crate::ops::{DataflowBlock, LeafOp, OpTag}; - use crate::types::Signature; + use crate::types::FunctionType; use crate::{ops, type_row, Hugr, HugrView}; #[test] fn root_checked() { let root_type = NodeType::new_pure(ops::DFG { - signature: Signature::new(vec![], vec![]), + signature: FunctionType::new(vec![], vec![]), }); let mut h = Hugr::new(root_type.clone()); let cfg_v = RootChecked::<&Hugr, CfgID>::try_new(&h); diff --git a/quantinuum-hugr/src/hugr/views/sibling.rs b/quantinuum-hugr/src/hugr/views/sibling.rs index 8f482e7b4..56068ecb1 100644 --- a/quantinuum-hugr/src/hugr/views/sibling.rs +++ b/quantinuum-hugr/src/hugr/views/sibling.rs @@ -381,7 +381,7 @@ mod test { use crate::ops::handle::{CfgID, DataflowParentID, DfgID, FuncID}; use crate::ops::{dataflow::IOTrait, Input, OpTag, Output}; use crate::type_row; - use crate::types::{Signature, Type}; + use crate::types::{FunctionType, Type}; use super::super::descendants::test::make_module_hgr; use super::*; @@ -405,7 +405,7 @@ mod test { #[test] fn nested_flat() -> Result<(), Box> { let mut module_builder = ModuleBuilder::new(); - let fty = Signature::new(type_row![NAT], type_row![NAT]); + let fty = FunctionType::new(type_row![NAT], type_row![NAT]); let mut fbuild = module_builder.define_function("main", fty.clone())?; let dfg = fbuild.dfg_builder(fty, None, fbuild.input_wires())?; let ins = dfg.input_wires(); diff --git a/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs b/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs index 7d6fc7e20..9741b08c7 100644 --- a/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs +++ b/quantinuum-hugr/src/hugr/views/sibling_subgraph.rs @@ -22,7 +22,7 @@ use crate::hugr::{HugrMut, HugrView, RootTagged}; use crate::ops::dataflow::DataflowOpTrait; use crate::ops::handle::{ContainerHandle, DataflowOpID}; use crate::ops::{OpTag, OpTrait}; -use crate::types::{Signature, Type}; +use crate::types::{FunctionType, Type}; use crate::{Hugr, IncomingPort, Node, OutgoingPort, Port, SimpleReplacement}; /// A non-empty convex subgraph of a HUGR sibling graph. @@ -289,7 +289,7 @@ impl SiblingSubgraph { } /// The signature of the subgraph. - pub fn signature(&self, hugr: &impl HugrView) -> Signature { + pub fn signature(&self, hugr: &impl HugrView) -> FunctionType { let input = self .inputs .iter() @@ -307,7 +307,7 @@ impl SiblingSubgraph { sig.port_type(p).cloned().expect("must be dataflow edge") }) .collect_vec(); - Signature::new(input, output) + FunctionType::new(input, output) } /// The parent of the sibling subgraph. @@ -731,7 +731,7 @@ mod tests { let mut mod_builder = ModuleBuilder::new(); let func = mod_builder.declare( "test", - Signature::new_endo(type_row![QB_T, QB_T, QB_T]).into(), + FunctionType::new_endo(type_row![QB_T, QB_T, QB_T]).into(), )?; let func_id = { let mut dfg = mod_builder.define_declaration(&func)?; @@ -747,7 +747,7 @@ mod tests { fn build_3not_hugr() -> Result<(Hugr, Node), BuildError> { let mut mod_builder = ModuleBuilder::new(); - let func = mod_builder.declare("test", Signature::new_endo(type_row![BOOL_T]).into())?; + let func = mod_builder.declare("test", FunctionType::new_endo(type_row![BOOL_T]).into())?; let func_id = { let mut dfg = mod_builder.define_declaration(&func)?; let outs1 = dfg.add_dataflow_op(NotOp, dfg.input_wires())?; @@ -766,7 +766,7 @@ mod tests { let mut mod_builder = ModuleBuilder::new(); let func = mod_builder.declare( "test", - Signature::new(type_row![BOOL_T], type_row![BOOL_T]).into(), + FunctionType::new(type_row![BOOL_T], type_row![BOOL_T]).into(), )?; let func_id = { let mut dfg = mod_builder.define_declaration(&func)?; @@ -805,7 +805,7 @@ mod tests { let sub = SiblingSubgraph::try_new_dataflow_subgraph(&func)?; let empty_dfg = { - let builder = DFGBuilder::new(Signature::new_endo(type_row![QB_T, QB_T])).unwrap(); + let builder = DFGBuilder::new(FunctionType::new_endo(type_row![QB_T, QB_T])).unwrap(); let inputs = builder.input_wires(); builder.finish_prelude_hugr_with_outputs(inputs).unwrap() }; @@ -830,7 +830,7 @@ mod tests { // the first two qubits. assert_eq!( sub.signature(&func), - Signature::new_endo(type_row![QB_T, QB_T]) + FunctionType::new_endo(type_row![QB_T, QB_T]) ); Ok(()) } @@ -842,7 +842,7 @@ mod tests { let sub = SiblingSubgraph::from_sibling_graph(&func)?; let empty_dfg = { - let builder = DFGBuilder::new(Signature::new_endo(type_row![QB_T])).unwrap(); + let builder = DFGBuilder::new(FunctionType::new_endo(type_row![QB_T])).unwrap(); let inputs = builder.input_wires(); builder.finish_prelude_hugr_with_outputs(inputs).unwrap() }; @@ -981,7 +981,7 @@ mod tests { let two_bit = type_row![BOOL_T, BOOL_T]; let mut builder = - DFGBuilder::new(Signature::new(one_bit.clone(), two_bit.clone())).unwrap(); + DFGBuilder::new(FunctionType::new(one_bit.clone(), two_bit.clone())).unwrap(); let inw = builder.input_wires().exactly_one().unwrap(); let outw1 = builder.add_dataflow_op(NotOp, [inw]).unwrap().out_wire(0); let outw2 = builder diff --git a/quantinuum-hugr/src/hugr/views/tests.rs b/quantinuum-hugr/src/hugr/views/tests.rs index 4901f10cc..dfa4b9712 100644 --- a/quantinuum-hugr/src/hugr/views/tests.rs +++ b/quantinuum-hugr/src/hugr/views/tests.rs @@ -6,15 +6,18 @@ use crate::{ extension::prelude::QB_T, ops::handle::{DataflowOpID, NodeHandle}, type_row, - types::Signature, + types::FunctionType, utils::test_quantum_extension::cx_gate, Hugr, HugrView, }; #[fixture] fn sample_hugr() -> (Hugr, BuildHandle, BuildHandle) { - let mut dfg = - DFGBuilder::new(Signature::new(type_row![QB_T, QB_T], type_row![QB_T, QB_T])).unwrap(); + let mut dfg = DFGBuilder::new(FunctionType::new( + type_row![QB_T, QB_T], + type_row![QB_T, QB_T], + )) + .unwrap(); let [q1, q2] = dfg.input_wires_arr(); @@ -119,7 +122,7 @@ fn value_types() { use crate::utils::test_quantum_extension::h_gate; use itertools::Itertools; - let mut dfg = DFGBuilder::new(Signature::new( + let mut dfg = DFGBuilder::new(FunctionType::new( type_row![QB_T, BOOL_T], type_row![BOOL_T, QB_T], )) @@ -147,7 +150,7 @@ fn static_targets() { use crate::extension::prelude::{ConstUsize, PRELUDE_ID, USIZE_T}; use itertools::Itertools; let mut dfg = DFGBuilder::new( - Signature::new(type_row![], type_row![USIZE_T]).with_extension_delta(PRELUDE_ID), + FunctionType::new(type_row![], type_row![USIZE_T]).with_extension_delta(PRELUDE_ID), ) .unwrap(); @@ -173,12 +176,12 @@ fn test_dataflow_ports_only() { use crate::std_extensions::logic::NotOp; use itertools::Itertools; - let mut dfg = DFGBuilder::new(Signature::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap(); + let mut dfg = DFGBuilder::new(FunctionType::new(type_row![BOOL_T], type_row![BOOL_T])).unwrap(); let local_and = { let local_and = dfg .define_function( "and", - Signature::new(type_row![BOOL_T; 2], type_row![BOOL_T]), + FunctionType::new(type_row![BOOL_T; 2], type_row![BOOL_T]), ) .unwrap(); let first_input = local_and.input().out_wire(0); diff --git a/quantinuum-hugr/src/ops.rs b/quantinuum-hugr/src/ops.rs index 05e222341..7145b35e1 100644 --- a/quantinuum-hugr/src/ops.rs +++ b/quantinuum-hugr/src/ops.rs @@ -10,7 +10,7 @@ pub mod module; pub mod tag; pub mod validate; use crate::extension::ExtensionSet; -use crate::types::{EdgeKind, Signature}; +use crate::types::{EdgeKind, FunctionType}; use crate::{Direction, OutgoingPort, Port}; use crate::{IncomingPort, PortIndex}; use paste::paste; @@ -319,7 +319,7 @@ pub trait OpTrait { /// The signature of the operation. /// /// Only dataflow operations have a signature, otherwise returns None. - fn dataflow_signature(&self) -> Option { + fn dataflow_signature(&self) -> Option { None } @@ -382,13 +382,13 @@ pub trait OpParent { /// sibling graph. /// /// Non-container ops like `FuncDecl` return `None` even though they represent a function. - fn inner_function_type(&self) -> Option { + fn inner_function_type(&self) -> Option { None } } impl OpParent for T { - fn inner_function_type(&self) -> Option { + fn inner_function_type(&self) -> Option { Some(DataflowParent::inner_signature(self)) } } diff --git a/quantinuum-hugr/src/ops/constant.rs b/quantinuum-hugr/src/ops/constant.rs index 964543d5e..239e8e8fb 100644 --- a/quantinuum-hugr/src/ops/constant.rs +++ b/quantinuum-hugr/src/ops/constant.rs @@ -285,7 +285,7 @@ where mod test { use super::Const; use crate::builder::test::simple_dfg_hugr; - use crate::types::Signature; + use crate::types::FunctionType; use crate::{ builder::{BuildError, DFGBuilder, Dataflow, DataflowHugr}, extension::{ @@ -344,7 +344,7 @@ mod test { let pred_rows = vec![type_row![USIZE_T, FLOAT64_TYPE], Type::EMPTY_TYPEROW]; let pred_ty = SumType::new(pred_rows.clone()); - let mut b = DFGBuilder::new(Signature::new( + let mut b = DFGBuilder::new(FunctionType::new( type_row![], TypeRow::from(vec![pred_ty.clone().into()]), ))?; @@ -359,7 +359,7 @@ mod test { let w = b.load_const(&c); b.finish_hugr_with_outputs([w], &test_registry()).unwrap(); - let mut b = DFGBuilder::new(Signature::new( + let mut b = DFGBuilder::new(FunctionType::new( type_row![], TypeRow::from(vec![pred_ty.clone().into()]), ))?; diff --git a/quantinuum-hugr/src/ops/controlflow.rs b/quantinuum-hugr/src/ops/controlflow.rs index 5d9e27f5d..41d597e60 100644 --- a/quantinuum-hugr/src/ops/controlflow.rs +++ b/quantinuum-hugr/src/ops/controlflow.rs @@ -3,7 +3,7 @@ use smol_str::SmolStr; use crate::extension::ExtensionSet; -use crate::types::{EdgeKind, Signature, Type, TypeRow}; +use crate::types::{EdgeKind, FunctionType, Type, TypeRow}; use crate::Direction; use super::dataflow::{DataflowOpTrait, DataflowParent}; @@ -30,10 +30,10 @@ impl DataflowOpTrait for TailLoop { "A tail-controlled loop" } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { let [inputs, outputs] = [&self.just_inputs, &self.just_outputs].map(|row| row.extend(self.rest.iter())); - Signature::new(inputs, outputs) + FunctionType::new(inputs, outputs) } } @@ -73,12 +73,12 @@ impl DataflowOpTrait for Conditional { "HUGR conditional operation" } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { let mut inputs = self.other_inputs.clone(); inputs .to_mut() .insert(0, Type::new_sum(self.sum_rows.clone())); - Signature::new(inputs, self.outputs.clone()) + FunctionType::new(inputs, self.outputs.clone()) .with_extension_delta(self.extension_delta.clone()) } } @@ -94,7 +94,7 @@ impl Conditional { #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[allow(missing_docs)] pub struct CFG { - pub signature: Signature, + pub signature: FunctionType, } impl_op_name!(CFG); @@ -106,7 +106,7 @@ impl DataflowOpTrait for CFG { "A dataflow node defined by a child CFG" } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { self.signature.clone() } } @@ -150,12 +150,12 @@ impl StaticTag for ExitBlock { } impl DataflowParent for DataflowBlock { - fn inner_signature(&self) -> Signature { + fn inner_signature(&self) -> FunctionType { // The node outputs a Sum before the data outputs of the block node let sum_type = Type::new_sum(self.sum_rows.clone()); let mut node_outputs = vec![sum_type]; node_outputs.extend_from_slice(&self.other_outputs); - Signature::new(self.inputs.clone(), TypeRow::from(node_outputs)) + FunctionType::new(self.inputs.clone(), TypeRow::from(node_outputs)) } } @@ -246,7 +246,7 @@ impl BasicBlock for ExitBlock { /// Case ops - nodes valid inside Conditional nodes. pub struct Case { /// The signature of the contained dataflow graph. - pub signature: Signature, + pub signature: FunctionType, } impl_op_name!(Case); @@ -256,7 +256,7 @@ impl StaticTag for Case { } impl DataflowParent for Case { - fn inner_signature(&self) -> Signature { + fn inner_signature(&self) -> FunctionType { self.signature.clone() } } diff --git a/quantinuum-hugr/src/ops/custom.rs b/quantinuum-hugr/src/ops/custom.rs index aa11e41cb..d4e4c88a6 100644 --- a/quantinuum-hugr/src/ops/custom.rs +++ b/quantinuum-hugr/src/ops/custom.rs @@ -7,7 +7,7 @@ use thiserror::Error; use crate::extension::{ConstFoldResult, ExtensionId, ExtensionRegistry, OpDef, SignatureError}; use crate::hugr::hugrmut::sealed::HugrMutInternals; use crate::hugr::{HugrView, NodeType}; -use crate::types::{type_param::TypeArg, Signature}; +use crate::types::{type_param::TypeArg, FunctionType}; use crate::{ops, Hugr, IncomingPort, Node}; use super::dataflow::DataflowOpTrait; @@ -93,7 +93,7 @@ impl DataflowOpTrait for ExternalOp { } } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { match self { Self::Opaque(op) => op.signature.clone(), Self::Extension(ext_op) => ext_op.signature(), @@ -109,7 +109,7 @@ impl DataflowOpTrait for ExternalOp { pub struct ExtensionOp { def: Arc, args: Vec, - signature: Signature, // Cache + signature: FunctionType, // Cache } impl ExtensionOp { @@ -187,7 +187,7 @@ impl DataflowOpTrait for ExtensionOp { self.def().description() } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { self.signature.clone() } } @@ -201,7 +201,7 @@ pub struct OpaqueOp { op_name: SmolStr, description: String, // cache in advance so description() can return &str args: Vec, - signature: Signature, + signature: FunctionType, } fn qualify_name(res_id: &ExtensionId, op_name: &SmolStr) -> SmolStr { @@ -215,7 +215,7 @@ impl OpaqueOp { op_name: impl Into, description: String, args: impl Into>, - signature: Signature, + signature: FunctionType, ) -> Self { Self { extension, @@ -264,7 +264,7 @@ impl DataflowOpTrait for OpaqueOp { &self.description } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { self.signature.clone() } } @@ -346,8 +346,8 @@ pub enum CustomOpError { SignatureMismatch { extension: ExtensionId, op: SmolStr, - stored: Signature, - computed: Signature, + stored: FunctionType, + computed: FunctionType, }, } @@ -360,7 +360,7 @@ mod test { #[test] fn new_opaque_op() { - let sig = Signature::new_endo(vec![QB_T]); + let sig = FunctionType::new_endo(vec![QB_T]); let op = OpaqueOp::new( "res".try_into().unwrap(), "op", diff --git a/quantinuum-hugr/src/ops/dataflow.rs b/quantinuum-hugr/src/ops/dataflow.rs index 3cb36e2d3..d886a8720 100644 --- a/quantinuum-hugr/src/ops/dataflow.rs +++ b/quantinuum-hugr/src/ops/dataflow.rs @@ -4,13 +4,13 @@ use super::{impl_op_name, OpTag, OpTrait}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::ops::StaticTag; -use crate::types::{EdgeKind, PolyFixedFunc, Signature, Type, TypeArg, TypeRow}; +use crate::types::{EdgeKind, FunctionType, PolyFixedFunc, Type, TypeArg, TypeRow}; use crate::IncomingPort; pub(crate) trait DataflowOpTrait { const TAG: OpTag; fn description(&self) -> &str; - fn signature(&self) -> Signature; + fn signature(&self) -> FunctionType; /// The edge kind for the non-dataflow or constant inputs of the operation, /// not described by the signature. @@ -94,8 +94,8 @@ impl DataflowOpTrait for Input { None } - fn signature(&self) -> Signature { - Signature::new(TypeRow::new(), self.types.clone()) + fn signature(&self) -> FunctionType { + FunctionType::new(TypeRow::new(), self.types.clone()) } } impl DataflowOpTrait for Output { @@ -107,8 +107,8 @@ impl DataflowOpTrait for Output { // Note: We know what the input extensions should be, so we *could* give an // instantiated Signature instead - fn signature(&self) -> Signature { - Signature::new(self.types.clone(), TypeRow::new()) + fn signature(&self) -> FunctionType { + FunctionType::new(self.types.clone(), TypeRow::new()) } fn other_output(&self) -> Option { @@ -123,7 +123,7 @@ impl OpTrait for T { fn tag(&self) -> OpTag { T::TAG } - fn dataflow_signature(&self) -> Option { + fn dataflow_signature(&self) -> Option { Some(DataflowOpTrait::signature(self)) } fn extension_delta(&self) -> ExtensionSet { @@ -155,7 +155,7 @@ pub struct Call { /// Signature of function being called func_sig: PolyFixedFunc, type_args: Vec, - instantiation: Signature, // Cache, so we can fail in try_new() not in signature() + instantiation: FunctionType, // Cache, so we can fail in try_new() not in signature() } impl_op_name!(Call); @@ -166,7 +166,7 @@ impl DataflowOpTrait for Call { "Call a function directly" } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { self.instantiation.clone() } @@ -231,7 +231,7 @@ impl Call { #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct CallIndirect { /// Signature of function being called - pub signature: Signature, + pub signature: FunctionType, } impl_op_name!(CallIndirect); @@ -242,7 +242,7 @@ impl DataflowOpTrait for CallIndirect { "Call a function indirectly" } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { let mut s = self.signature.clone(); s.input.to_mut().insert( 0, @@ -266,8 +266,8 @@ impl DataflowOpTrait for LoadConstant { "Load a static constant in to the local dataflow graph" } - fn signature(&self) -> Signature { - Signature::new(TypeRow::new(), vec![self.datatype.clone()]) + fn signature(&self) -> FunctionType { + FunctionType::new(TypeRow::new(), vec![self.datatype.clone()]) } fn static_input(&self) -> Option { @@ -305,20 +305,20 @@ impl LoadConstant { /// Operations that is the parent of a dataflow graph. pub trait DataflowParent { /// Signature of the inner dataflow graph. - fn inner_signature(&self) -> Signature; + fn inner_signature(&self) -> FunctionType; } /// A simply nested dataflow graph. #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct DFG { /// Signature of DFG node - pub signature: Signature, + pub signature: FunctionType, } impl_op_name!(DFG); impl DataflowParent for DFG { - fn inner_signature(&self) -> Signature { + fn inner_signature(&self) -> FunctionType { self.signature.clone() } } @@ -330,7 +330,7 @@ impl DataflowOpTrait for DFG { "A simply nested dataflow graph" } - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { self.inner_signature() } } diff --git a/quantinuum-hugr/src/ops/leaf.rs b/quantinuum-hugr/src/ops/leaf.rs index b883511fb..6d32495ef 100644 --- a/quantinuum-hugr/src/ops/leaf.rs +++ b/quantinuum-hugr/src/ops/leaf.rs @@ -8,7 +8,7 @@ use super::{OpName, OpTag}; use crate::extension::{ExtensionId, ExtensionRegistry, ExtensionSet, SignatureError}; use crate::types::type_param::TypeArg; -use crate::types::{EdgeKind, PolyFuncType, Signature, Type, TypeRow}; +use crate::types::{EdgeKind, FunctionType, PolyFuncType, Type, TypeRow}; /// Dataflow operations with no children. #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] @@ -175,29 +175,29 @@ impl DataflowOpTrait for LeafOp { } /// The signature of the operation. - fn signature(&self) -> Signature { + fn signature(&self) -> FunctionType { // Static signatures. The `TypeRow`s in the `FuncTypeVarLen` use a // copy-on-write strategy, so we can avoid unnecessary allocations. match self { - LeafOp::Noop { ty: typ } => Signature::new(vec![typ.clone()], vec![typ.clone()]), + LeafOp::Noop { ty: typ } => FunctionType::new(vec![typ.clone()], vec![typ.clone()]), LeafOp::CustomOp(ext) => ext.signature(), LeafOp::MakeTuple { tys: types } => { - Signature::new(types.clone(), vec![Type::new_tuple(types.clone())]) + FunctionType::new(types.clone(), vec![Type::new_tuple(types.clone())]) } LeafOp::UnpackTuple { tys: types } => { - Signature::new(vec![Type::new_tuple(types.clone())], types.clone()) + FunctionType::new(vec![Type::new_tuple(types.clone())], types.clone()) } - LeafOp::Tag { tag, variants } => Signature::new( + LeafOp::Tag { tag, variants } => FunctionType::new( variants.get(*tag).expect("Not a valid tag").clone(), vec![Type::new_sum(variants.clone())], ), LeafOp::Lift { type_row, new_extension, - } => Signature::new(type_row.clone(), type_row.clone()) + } => FunctionType::new(type_row.clone(), type_row.clone()) .with_extension_delta(ExtensionSet::singleton(new_extension)), - LeafOp::TypeApply { ta } => Signature::new( + LeafOp::TypeApply { ta } => FunctionType::new( vec![Type::new_function(ta.input.clone())], vec![Type::new_function(ta.output.clone())], ), @@ -223,7 +223,7 @@ mod test { use crate::ops::handle::NodeHandle; use crate::std_extensions::collections::EXTENSION; use crate::types::test::nested_func; - use crate::types::{Signature, Type, TypeArg}; + use crate::types::{FunctionType, Type, TypeArg}; use super::{LeafOp, TypeApplication}; @@ -234,7 +234,7 @@ mod test { let reg = ExtensionRegistry::try_new([PRELUDE.to_owned(), EXTENSION.to_owned()]).unwrap(); let pf_in = nested_func(); let pf_out = pf_in.instantiate(&[USIZE_TA], ®)?; - let mut dfg = DFGBuilder::new(Signature::new( + let mut dfg = DFGBuilder::new(FunctionType::new( vec![Type::new_function(pf_in.clone())], vec![Type::new_function(pf_out)], ))?; @@ -254,7 +254,7 @@ mod test { let pf = nested_func(); let pf_usz = pf.instantiate_poly(&[USIZE_TA], ®)?; let pf_bool = pf.instantiate_poly(&[TypeArg::Type { ty: BOOL_T }], ®)?; - let mut dfg = DFGBuilder::new(Signature::new( + let mut dfg = DFGBuilder::new(FunctionType::new( vec![Type::new_function(pf.clone())], vec![Type::new_function(pf_usz.clone())], ))?; diff --git a/quantinuum-hugr/src/ops/module.rs b/quantinuum-hugr/src/ops/module.rs index 742518b18..a5ebc40cc 100644 --- a/quantinuum-hugr/src/ops/module.rs +++ b/quantinuum-hugr/src/ops/module.rs @@ -2,7 +2,7 @@ use smol_str::SmolStr; -use crate::types::{EdgeKind, PolyFixedFunc, Signature}; +use crate::types::{EdgeKind, FunctionType, PolyFixedFunc}; use crate::types::{Type, TypeBound}; use super::dataflow::DataflowParent; @@ -46,7 +46,7 @@ impl StaticTag for FuncDefn { } impl DataflowParent for FuncDefn { - fn inner_signature(&self) -> Signature { + fn inner_signature(&self) -> FunctionType { self.signature.body().clone() } } diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs index 4c2098004..8d7e4a896 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs @@ -333,7 +333,7 @@ impl IntOpDef { mod test { use crate::{ ops::dataflow::DataflowOpTrait, std_extensions::arithmetic::int_types::int_type, - types::Signature, + types::FunctionType, }; use super::*; @@ -359,7 +359,7 @@ mod test { .to_extension_op() .unwrap() .signature(), - Signature::new(vec![int_type(ta(3))], vec![int_type(ta(4))],) + FunctionType::new(vec![int_type(ta(3))], vec![int_type(ta(4))],) ); assert_eq!( IntOpDef::iwiden_s @@ -367,7 +367,7 @@ mod test { .to_extension_op() .unwrap() .signature(), - Signature::new(vec![int_type(ta(3))], vec![int_type(ta(3))],) + FunctionType::new(vec![int_type(ta(3))], vec![int_type(ta(3))],) ); assert_eq!( IntOpDef::inarrow_s @@ -375,7 +375,7 @@ mod test { .to_extension_op() .unwrap() .signature(), - Signature::new( + FunctionType::new( vec![int_type(ta(3))], vec![sum_with_error(int_type(ta(3))).into()], ) @@ -394,7 +394,7 @@ mod test { .to_extension_op() .unwrap() .signature(), - Signature::new( + FunctionType::new( vec![int_type(ta(2))], vec![sum_with_error(int_type(ta(1))).into()], ) diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index cfd4ae651..a63aca1c0 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -13,7 +13,7 @@ use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; pub use poly_func::{PolyFixedFunc, PolyFuncType}; -pub use signature::{FuncTypeVarLen, Signature}; +pub use signature::{FuncTypeVarLen, FunctionType}; use smol_str::SmolStr; pub use type_param::TypeArg; pub use type_row::TypeRow; diff --git a/quantinuum-hugr/src/types/signature.rs b/quantinuum-hugr/src/types/signature.rs index 0bfbeb922..933e82e2d 100644 --- a/quantinuum-hugr/src/types/signature.rs +++ b/quantinuum-hugr/src/types/signature.rs @@ -86,7 +86,7 @@ impl TypeRowElem for RowVarOrType { } /// The type of a node. Fixed/known arity of inputs + outputs. -pub type Signature = FuncTypeBase; +pub type FunctionType = FuncTypeBase; impl TypeRowElem for Type { fn validate( @@ -164,7 +164,7 @@ where } } -impl Signature { +impl FunctionType { /// The number of wires in the signature. #[inline(always)] pub fn is_empty(&self) -> bool { @@ -284,8 +284,8 @@ impl Signature { } } -impl From for FuncTypeVarLen { - fn from(sig: Signature) -> Self { +impl From for FuncTypeVarLen { + fn from(sig: FunctionType) -> Self { Self { input: sig.input.into(), output: sig.output.into(), @@ -294,7 +294,7 @@ impl From for FuncTypeVarLen { } } -impl TryFrom for Signature { +impl TryFrom for FunctionType { type Error = (usize, TypeBound); fn try_from(funty: FuncTypeVarLen) -> Result { @@ -329,7 +329,7 @@ mod test { use super::*; #[test] fn test_function_type() { - let mut f_type = Signature::new(type_row![Type::UNIT], type_row![Type::UNIT]); + let mut f_type = FunctionType::new(type_row![Type::UNIT], type_row![Type::UNIT]); assert_eq!(f_type.input_count(), 1); assert_eq!(f_type.output_count(), 1); From 57a71b0ee15366f1797435330a9b5d8b2ea173e9 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 2 Apr 2024 09:29:35 +0100 Subject: [PATCH 46/57] Rename: PolyFuncType -> PolyFuncVarLen; doc --- quantinuum-hugr/src/extension.rs | 6 ++-- .../src/extension/declarative/signature.rs | 4 +-- quantinuum-hugr/src/extension/op_def.rs | 33 ++++++++++--------- quantinuum-hugr/src/extension/prelude.rs | 6 ++-- quantinuum-hugr/src/ops/leaf.rs | 12 +++---- .../std_extensions/arithmetic/conversions.rs | 6 ++-- .../src/std_extensions/arithmetic/int_ops.rs | 10 +++--- .../src/std_extensions/collections.rs | 6 ++-- quantinuum-hugr/src/std_extensions/logic.rs | 2 +- quantinuum-hugr/src/types.rs | 6 ++-- quantinuum-hugr/src/types/poly_func.rs | 15 +++++---- quantinuum-hugr/src/types/serialize.rs | 4 +-- quantinuum-hugr/src/utils.rs | 6 ++-- 13 files changed, 60 insertions(+), 56 deletions(-) diff --git a/quantinuum-hugr/src/extension.rs b/quantinuum-hugr/src/extension.rs index d16a11b8b..8f05a501d 100644 --- a/quantinuum-hugr/src/extension.rs +++ b/quantinuum-hugr/src/extension.rs @@ -18,7 +18,7 @@ use crate::ops::custom::{ExtensionOp, OpaqueOp}; use crate::types::type_param::{check_type_args, TypeArgError}; use crate::types::type_param::{TypeArg, TypeParam}; use crate::types::{ - check_typevar_decl, CustomType, PolyFuncType, Substitution, TypeBound, TypeName, + check_typevar_decl, CustomType, PolyFuncVarLen, Substitution, TypeBound, TypeName, }; #[allow(dead_code)] @@ -175,8 +175,8 @@ pub enum SignatureError { /// [LeafOp::TypeApply]: crate::ops::LeafOp::TypeApply #[error("Incorrect result of type application - cached {cached} but expected {expected}")] TypeApplyIncorrectCache { - cached: PolyFuncType, - expected: PolyFuncType, + cached: PolyFuncVarLen, + expected: PolyFuncVarLen, }, } diff --git a/quantinuum-hugr/src/extension/declarative/signature.rs b/quantinuum-hugr/src/extension/declarative/signature.rs index d490de6bd..6fa98c96d 100644 --- a/quantinuum-hugr/src/extension/declarative/signature.rs +++ b/quantinuum-hugr/src/extension/declarative/signature.rs @@ -15,7 +15,7 @@ use crate::extension::prelude::PRELUDE_ID; use crate::extension::{CustomValidator, ExtensionSet, SignatureFunc, TypeDef, TypeParametrised}; use crate::types::type_param::TypeParam; use crate::types::type_row::TypeRowVarLen; -use crate::types::{CustomType, FuncTypeVarLen, PolyFuncType, Type}; +use crate::types::{CustomType, FuncTypeVarLen, PolyFuncVarLen, Type}; use crate::Extension; use super::{DeclarationContext, ExtensionDeclarationError}; @@ -57,7 +57,7 @@ impl SignatureDeclaration { extension_reqs: self.extensions.clone(), }; - let poly_func = PolyFuncType::new(op_params, body); + let poly_func = PolyFuncVarLen::new(op_params, body); Ok(SignatureFunc::TypeScheme(CustomValidator::from_polyfunc( poly_func, ))) diff --git a/quantinuum-hugr/src/extension/op_def.rs b/quantinuum-hugr/src/extension/op_def.rs index d901c6c7e..87fb02a03 100644 --- a/quantinuum-hugr/src/extension/op_def.rs +++ b/quantinuum-hugr/src/extension/op_def.rs @@ -12,7 +12,7 @@ use super::{ }; use crate::types::type_param::{check_type_args, TypeArg, TypeParam}; -use crate::types::{FuncTypeVarLen, FunctionType, PolyFuncType}; +use crate::types::{FuncTypeVarLen, FunctionType, PolyFuncVarLen}; use crate::Hugr; /// Trait necessary for binary computations of OpDef signature @@ -25,7 +25,7 @@ pub trait CustomSignatureFunc: Send + Sync { arg_values: &[TypeArg], def: &'o OpDef, extension_registry: &ExtensionRegistry, - ) -> Result; + ) -> Result; /// The declared type parameters which for which closed values /// (closed == without any free variables) /// which must be provided in order for signature to be computed. @@ -36,7 +36,7 @@ pub trait CustomSignatureFunc: Send + Sync { pub trait SignatureFromArgs: Send + Sync { /// Compute signature of node given /// values for the type parameters. - fn compute_signature(&self, arg_values: &[TypeArg]) -> Result; + fn compute_signature(&self, arg_values: &[TypeArg]) -> Result; /// The declared type parameters which require values in order for signature to /// be computed. fn static_params(&self) -> &[TypeParam]; @@ -49,7 +49,7 @@ impl CustomSignatureFunc for T { arg_values: &[TypeArg], _def: &'o OpDef, _extension_registry: &ExtensionRegistry, - ) -> Result { + ) -> Result { SignatureFromArgs::compute_signature(self, arg_values) } @@ -122,14 +122,14 @@ pub trait CustomLowerFunc: Send + Sync { #[derive(serde::Deserialize, serde::Serialize)] pub struct CustomValidator { #[serde(flatten)] - poly_func: PolyFuncType, + poly_func: PolyFuncVarLen, #[serde(skip)] validate: Box, } impl CustomValidator { /// Encode a signature using a `PolyFuncType` - pub fn from_polyfunc(poly_func: impl Into) -> Self { + pub fn from_polyfunc(poly_func: impl Into) -> Self { Self { poly_func: poly_func.into(), validate: Default::default(), @@ -139,7 +139,7 @@ impl CustomValidator { /// Encode a signature using a `PolyFuncType`, with a custom function for /// validating type arguments before returning the signature. pub fn new_with_validator( - poly_func: impl Into, + poly_func: impl Into, validate: impl ValidateTypeArgs + 'static, ) -> Self { Self { @@ -188,8 +188,8 @@ impl From for SignatureFunc { } } -impl From for SignatureFunc { - fn from(v: PolyFuncType) -> Self { +impl From for SignatureFunc { + fn from(v: PolyFuncVarLen) -> Self { Self::TypeScheme(CustomValidator::from_polyfunc(v)) } } @@ -232,7 +232,7 @@ impl SignatureFunc { args: &[TypeArg], exts: &ExtensionRegistry, ) -> Result { - let temp: PolyFuncType; + let temp: PolyFuncVarLen; let (pf, args) = match &self { SignatureFunc::TypeScheme(custom) => { custom.validate.validate(args, def, exts)?; @@ -331,7 +331,7 @@ impl OpDef { exts: &ExtensionRegistry, var_decls: &[TypeParam], ) -> Result<(), SignatureError> { - let temp: PolyFuncType; // to keep alive + let temp: PolyFuncVarLen; // to keep alive let (pf, args) = match &self.signature_func { SignatureFunc::TypeScheme(ts) => (&ts.poly_func, args), SignatureFunc::CustomFunc(custom) => { @@ -487,7 +487,7 @@ mod test { use crate::ops::LeafOp; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; use crate::types::{type_param::TypeParam, FuncTypeVarLen, FunctionType, TypeArg, TypeBound}; - use crate::types::{PolyFuncType, Type}; + use crate::types::{PolyFuncVarLen, Type}; use crate::Hugr; use crate::{const_extension_ids, Extension}; @@ -503,7 +503,8 @@ mod test { let list_of_var = Type::new_extension(list_def.instantiate(vec![TypeArg::new_var_use(0, TP)])?); const OP_NAME: SmolStr = SmolStr::new_inline("Reverse"); - let type_scheme = PolyFuncType::new(vec![TP], FuncTypeVarLen::new_endo(vec![list_of_var])); + let type_scheme = + PolyFuncVarLen::new(vec![TP], FuncTypeVarLen::new_endo(vec![list_of_var])); let def = e.add_op(OP_NAME, "desc".into(), type_scheme)?; def.add_lower_func(LowerFunc::FixedHugr(ExtensionSet::new(), Hugr::default())); @@ -542,7 +543,7 @@ mod test { fn compute_signature( &self, arg_values: &[TypeArg], - ) -> Result { + ) -> Result { const TP: TypeParam = TypeParam::Type { b: TypeBound::Any }; let [TypeArg::BoundedNat { n }] = arg_values else { return Err(SignatureError::InvalidTypeArgs); @@ -551,7 +552,7 @@ mod test { let tvs: Vec = (0..n) .map(|_| Type::new_var_use(0, TypeBound::Any)) .collect(); - Ok(PolyFuncType::new( + Ok(PolyFuncVarLen::new( vec![TP.to_owned()], FuncTypeVarLen::new(tvs.clone(), vec![Type::new_tuple(tvs)]), )) @@ -628,7 +629,7 @@ mod test { let def = e.add_op( "SimpleOp".into(), "".into(), - PolyFuncType::new( + PolyFuncVarLen::new( vec![TypeBound::Any.into()], FuncTypeVarLen::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), diff --git a/quantinuum-hugr/src/extension/prelude.rs b/quantinuum-hugr/src/extension/prelude.rs index ee8b7b576..3c85e4fde 100644 --- a/quantinuum-hugr/src/extension/prelude.rs +++ b/quantinuum-hugr/src/extension/prelude.rs @@ -11,7 +11,7 @@ use crate::{ type_row, types::{ type_param::{TypeArg, TypeParam}, - CustomType, FuncTypeVarLen, PolyFuncType, Type, TypeBound, + CustomType, FuncTypeVarLen, PolyFuncVarLen, Type, TypeBound, }, Extension, }; @@ -21,7 +21,7 @@ struct ArrayOpCustom; const MAX: &[TypeParam; 1] = &[TypeParam::max_nat()]; impl SignatureFromArgs for ArrayOpCustom { - fn compute_signature(&self, arg_values: &[TypeArg]) -> Result { + fn compute_signature(&self, arg_values: &[TypeArg]) -> Result { let [TypeArg::BoundedNat { n }] = *arg_values else { return Err(SignatureError::InvalidTypeArgs); }; @@ -30,7 +30,7 @@ impl SignatureFromArgs for ArrayOpCustom { let var_arg_row = vec![elem_ty_var.clone(); n as usize]; let other_row = vec![array_type(TypeArg::BoundedNat { n }, elem_ty_var.clone())]; - Ok(PolyFuncType::new( + Ok(PolyFuncVarLen::new( vec![TypeBound::Any.into()], FuncTypeVarLen::new(var_arg_row, other_row), )) diff --git a/quantinuum-hugr/src/ops/leaf.rs b/quantinuum-hugr/src/ops/leaf.rs index 6d32495ef..3025a2c38 100644 --- a/quantinuum-hugr/src/ops/leaf.rs +++ b/quantinuum-hugr/src/ops/leaf.rs @@ -8,7 +8,7 @@ use super::{OpName, OpTag}; use crate::extension::{ExtensionId, ExtensionRegistry, ExtensionSet, SignatureError}; use crate::types::type_param::TypeArg; -use crate::types::{EdgeKind, FunctionType, PolyFuncType, Type, TypeRow}; +use crate::types::{EdgeKind, FunctionType, PolyFuncVarLen, Type, TypeRow}; /// Dataflow operations with no children. #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] @@ -76,9 +76,9 @@ impl LeafOp { /// and the result (a less-, but still potentially-, polymorphic type). #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct TypeApplication { - input: PolyFuncType, + input: PolyFuncVarLen, args: Vec, - output: PolyFuncType, // cached + output: PolyFuncVarLen, // cached } impl TypeApplication { @@ -87,7 +87,7 @@ impl TypeApplication { /// /// [TypeParam]: crate::types::type_param::TypeParam pub fn try_new( - input: PolyFuncType, + input: PolyFuncVarLen, args: impl Into>, extension_registry: &ExtensionRegistry, ) -> Result { @@ -118,7 +118,7 @@ impl TypeApplication { } /// Returns the type of the input function. - pub fn input(&self) -> &PolyFuncType { + pub fn input(&self) -> &PolyFuncVarLen { &self.input } @@ -128,7 +128,7 @@ impl TypeApplication { } /// Returns the type of the output function. - pub fn output(&self) -> &PolyFuncType { + pub fn output(&self) -> &PolyFuncVarLen { &self.output } } diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs b/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs index 5506a31a4..dac221343 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/conversions.rs @@ -12,7 +12,7 @@ use crate::{ }, ops::{custom::ExtensionOp, OpName}, type_row, - types::{type_row::RowVarOrType, FuncTypeVarLen, PolyFuncType, TypeArg}, + types::{type_row::RowVarOrType, FuncTypeVarLen, PolyFuncVarLen, TypeArg}, Extension, }; @@ -41,7 +41,7 @@ impl MakeOpDef for ConvertOpDef { fn signature(&self) -> SignatureFunc { use ConvertOpDef::*; match self { - trunc_s | trunc_u => PolyFuncType::new( + trunc_s | trunc_u => PolyFuncVarLen::new( vec![LOG_WIDTH_TYPE_PARAM], FuncTypeVarLen::new( type_row![FLOAT64_TYPE], @@ -49,7 +49,7 @@ impl MakeOpDef for ConvertOpDef { ), ), - convert_s | convert_u => PolyFuncType::new( + convert_s | convert_u => PolyFuncVarLen::new( vec![LOG_WIDTH_TYPE_PARAM], FuncTypeVarLen::new(vec![int_tv(0)], type_row![FLOAT64_TYPE]), ), diff --git a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs index 8d7e4a896..cc004bf5b 100644 --- a/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs +++ b/quantinuum-hugr/src/std_extensions/arithmetic/int_ops.rs @@ -9,7 +9,7 @@ use crate::extension::{ use crate::ops::custom::ExtensionOp; use crate::ops::OpName; use crate::type_row; -use crate::types::{FuncTypeVarLen, PolyFuncType}; +use crate::types::{FuncTypeVarLen, PolyFuncVarLen}; use crate::utils::collect_array; use crate::{ @@ -221,20 +221,20 @@ fn int_polytype( n_vars: usize, input: impl Into, output: impl Into, -) -> PolyFuncType { - PolyFuncType::new( +) -> PolyFuncVarLen { + PolyFuncVarLen::new( vec![LOG_WIDTH_TYPE_PARAM; n_vars], FuncTypeVarLen::new(input.into(), output.into()), ) } -fn ibinop_sig() -> PolyFuncType { +fn ibinop_sig() -> PolyFuncVarLen { let int_type_var = int_tv(0); int_polytype(1, vec![int_type_var.clone(); 2], vec![int_type_var]) } -fn iunop_sig() -> PolyFuncType { +fn iunop_sig() -> PolyFuncVarLen { let int_type_var = int_tv(0); int_polytype(1, vec![int_type_var.clone()], vec![int_type_var]) } diff --git a/quantinuum-hugr/src/std_extensions/collections.rs b/quantinuum-hugr/src/std_extensions/collections.rs index 35b1613a2..a56e53707 100644 --- a/quantinuum-hugr/src/std_extensions/collections.rs +++ b/quantinuum-hugr/src/std_extensions/collections.rs @@ -17,7 +17,7 @@ use crate::{ ops::{self, custom::ExtensionOp, OpName}, types::{ type_param::{TypeArg, TypeParam}, - CustomCheckFailure, CustomType, FuncTypeVarLen, PolyFuncType, Type, TypeBound, + CustomCheckFailure, CustomType, FuncTypeVarLen, PolyFuncVarLen, Type, TypeBound, }, Extension, }; @@ -154,7 +154,7 @@ fn extension() -> Extension { .add_op( POP_NAME, "Pop from back of list".into(), - PolyFuncType::new( + PolyFuncVarLen::new( vec![TP], FuncTypeVarLen::new(vec![l.clone()], vec![l.clone(), e.clone()]), ), @@ -165,7 +165,7 @@ fn extension() -> Extension { .add_op( PUSH_NAME, "Push to back of list".into(), - PolyFuncType::new(vec![TP], FuncTypeVarLen::new(vec![l.clone(), e], vec![l])), + PolyFuncVarLen::new(vec![TP], FuncTypeVarLen::new(vec![l.clone(), e], vec![l])), ) .unwrap() .set_constant_folder(PushFold); diff --git a/quantinuum-hugr/src/std_extensions/logic.rs b/quantinuum-hugr/src/std_extensions/logic.rs index 841bb9e94..7334caa4c 100644 --- a/quantinuum-hugr/src/std_extensions/logic.rs +++ b/quantinuum-hugr/src/std_extensions/logic.rs @@ -129,7 +129,7 @@ fn logic_op_sig() -> impl SignatureFromArgs { fn compute_signature( &self, arg_values: &[TypeArg], - ) -> Result { + ) -> Result { // get the number of input booleans. let [TypeArg::BoundedNat { n }] = *arg_values else { return Err(SignatureError::InvalidTypeArgs); diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index a63aca1c0..372313556 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -12,7 +12,7 @@ pub use crate::ops::constant::{ConstTypeError, CustomCheckFailure}; use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; -pub use poly_func::{PolyFixedFunc, PolyFuncType}; +pub use poly_func::{PolyFixedFunc, PolyFuncVarLen}; pub use signature::{FuncTypeVarLen, FunctionType}; use smol_str::SmolStr; pub use type_param::TypeArg; @@ -187,7 +187,7 @@ pub enum TypeEnum { Alias(AliasDecl), #[allow(missing_docs)] #[display(fmt = "Function({})", "_0")] - Function(Box), + Function(Box), /// DeBruijn index, and cache of TypeBound of [TypeParam::Type] (checked in validation) #[allow(missing_docs)] #[display(fmt = "Variable({})", _0)] @@ -260,7 +260,7 @@ impl Type { const EMPTY_VL_TYPEROW_REF: &'static TypeRowVarLen = &Self::EMPTY_VL_TYPEROW; /// Initialize a new function type. - pub fn new_function(fun_ty: impl Into) -> Self { + pub fn new_function(fun_ty: impl Into) -> Self { Self::new(TypeEnum::Function(Box::new(fun_ty.into()))) } diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index 61f817f5c..f9980916d 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -42,7 +42,10 @@ where /// Template for the function. May contain variables up to length of [Self::params] body: FuncTypeBase, } -pub type PolyFuncType = PolyFuncBase; + +/// Type of a function polymorphic over some variables, +/// which may include row variables. +pub type PolyFuncVarLen = PolyFuncBase; pub type PolyFixedFunc = PolyFuncBase; impl From> for PolyFuncBase @@ -57,7 +60,7 @@ where } } -impl From for PolyFuncType { +impl From for PolyFuncVarLen { fn from(value: PolyFixedFunc) -> Self { Self { params: value.params, @@ -273,7 +276,7 @@ pub(crate) mod test { use crate::types::signature::FuncTypeBase; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; use crate::types::type_row::RowVarOrType; - use crate::types::{CustomType, FuncTypeVarLen, PolyFuncType, Type, TypeBound}; + use crate::types::{CustomType, FuncTypeVarLen, PolyFuncVarLen, Type, TypeBound}; use crate::Extension; use super::{PolyFuncBase, TypeRowElem}; @@ -501,8 +504,8 @@ pub(crate) mod test { Ok(()) } - fn new_pf1(param: TypeParam, input: Type, output: Type) -> PolyFuncType { - PolyFuncType { + fn new_pf1(param: TypeParam, input: Type, output: Type) -> PolyFuncVarLen { + PolyFuncVarLen { params: vec![param], body: FuncTypeVarLen::new(vec![input], vec![output]), } @@ -564,7 +567,7 @@ pub(crate) mod test { } // forall A. A -> (forall C. C -> List(Tuple(C, A)) - pub(crate) fn nested_func() -> PolyFuncType { + pub(crate) fn nested_func() -> PolyFuncVarLen { PolyFuncBase::new_validated( vec![TypeBound::Any.into()], FuncTypeVarLen::new( diff --git a/quantinuum-hugr/src/types/serialize.rs b/quantinuum-hugr/src/types/serialize.rs index f5de34fe6..31eef3352 100644 --- a/quantinuum-hugr/src/types/serialize.rs +++ b/quantinuum-hugr/src/types/serialize.rs @@ -1,5 +1,5 @@ use super::type_row::RowVarOrType; -use super::{PolyFuncType, SumType, Type, TypeArg, TypeBound, TypeEnum}; +use super::{PolyFuncVarLen, SumType, Type, TypeArg, TypeBound, TypeEnum}; use super::custom::CustomType; @@ -11,7 +11,7 @@ use crate::ops::AliasDecl; pub(super) enum SerSimpleType { Q, I, - G(Box), + G(Box), Sum(SumType), Array { inner: Box, len: u64 }, Opaque(CustomType), diff --git a/quantinuum-hugr/src/utils.rs b/quantinuum-hugr/src/utils.rs index 1e7c1d278..8d18c357d 100644 --- a/quantinuum-hugr/src/utils.rs +++ b/quantinuum-hugr/src/utils.rs @@ -108,17 +108,17 @@ pub(crate) mod test_quantum_extension { ops::LeafOp, std_extensions::arithmetic::float_types, type_row, - types::{FuncTypeVarLen, PolyFuncType}, + types::{FuncTypeVarLen, PolyFuncVarLen}, Extension, }; use lazy_static::lazy_static; - fn one_qb_func() -> PolyFuncType { + fn one_qb_func() -> PolyFuncVarLen { FuncTypeVarLen::new_endo(type_row![QB_T]).into() } - fn two_qb_func() -> PolyFuncType { + fn two_qb_func() -> PolyFuncVarLen { FuncTypeVarLen::new_endo(type_row![QB_T, QB_T]).into() } /// The extension identifier. From c36780ee3c21bba52ff996ac8e8d6296f358f7da Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Tue, 2 Apr 2024 09:31:25 +0100 Subject: [PATCH 47/57] Rename: PolyFixedFunc -> PolyFuncType (consistent, but seems misleading); doc --- quantinuum-hugr/src/builder.rs | 4 ++-- quantinuum-hugr/src/builder/build_traits.rs | 4 ++-- quantinuum-hugr/src/builder/dataflow.rs | 4 ++-- quantinuum-hugr/src/builder/module.rs | 4 ++-- quantinuum-hugr/src/hugr/validate/test.rs | 20 ++++++++++---------- quantinuum-hugr/src/hugr/views.rs | 6 +++--- quantinuum-hugr/src/ops/dataflow.rs | 10 +++++----- quantinuum-hugr/src/ops/module.rs | 6 +++--- quantinuum-hugr/src/types.rs | 2 +- quantinuum-hugr/src/types/poly_func.rs | 8 +++++--- 10 files changed, 35 insertions(+), 33 deletions(-) diff --git a/quantinuum-hugr/src/builder.rs b/quantinuum-hugr/src/builder.rs index e7e9ffe14..79ecc5a2b 100644 --- a/quantinuum-hugr/src/builder.rs +++ b/quantinuum-hugr/src/builder.rs @@ -223,7 +223,7 @@ pub(crate) mod test { use crate::hugr::{views::HugrView, HugrMut, NodeType}; use crate::ops; - use crate::types::{FunctionType, PolyFixedFunc, Type}; + use crate::types::{FunctionType, PolyFuncType, Type}; use crate::{type_row, Hugr}; use super::handle::BuildHandle; @@ -246,7 +246,7 @@ pub(crate) mod test { } pub(super) fn build_main( - signature: PolyFixedFunc, + signature: PolyFuncType, f: impl FnOnce(FunctionBuilder<&mut Hugr>) -> Result>, BuildError>, ) -> Result { let mut module_builder = ModuleBuilder::new(); diff --git a/quantinuum-hugr/src/builder/build_traits.rs b/quantinuum-hugr/src/builder/build_traits.rs index 7bcb592e0..eb3dd4b51 100644 --- a/quantinuum-hugr/src/builder/build_traits.rs +++ b/quantinuum-hugr/src/builder/build_traits.rs @@ -20,7 +20,7 @@ use crate::{ }; use crate::extension::{ExtensionRegistry, ExtensionSet, PRELUDE_REGISTRY}; -use crate::types::{FunctionType, PolyFixedFunc, Type, TypeArg, TypeRow}; +use crate::types::{FunctionType, PolyFuncType, Type, TypeArg, TypeRow}; use itertools::Itertools; @@ -85,7 +85,7 @@ pub trait Container { fn define_function( &mut self, name: impl Into, - signature: impl Into, + signature: impl Into, ) -> Result, BuildError> { let signature = signature.into(); let body = signature.body().clone(); diff --git a/quantinuum-hugr/src/builder/dataflow.rs b/quantinuum-hugr/src/builder/dataflow.rs index 18e47b320..762375fb4 100644 --- a/quantinuum-hugr/src/builder/dataflow.rs +++ b/quantinuum-hugr/src/builder/dataflow.rs @@ -7,7 +7,7 @@ use std::marker::PhantomData; use crate::hugr::{HugrView, NodeType, ValidationError}; use crate::ops; -use crate::types::{FunctionType, PolyFixedFunc}; +use crate::types::{FunctionType, PolyFuncType}; use crate::extension::{ExtensionRegistry, ExtensionSet}; use crate::Node; @@ -147,7 +147,7 @@ impl FunctionBuilder { /// # Errors /// /// Error in adding DFG child nodes. - pub fn new(name: impl Into, signature: PolyFixedFunc) -> Result { + pub fn new(name: impl Into, signature: PolyFuncType) -> Result { let body = signature.body().clone(); let op = ops::FuncDefn { signature, diff --git a/quantinuum-hugr/src/builder/module.rs b/quantinuum-hugr/src/builder/module.rs index 058ef7e5b..3ea607737 100644 --- a/quantinuum-hugr/src/builder/module.rs +++ b/quantinuum-hugr/src/builder/module.rs @@ -8,7 +8,7 @@ use crate::{ extension::ExtensionRegistry, hugr::{hugrmut::sealed::HugrMutInternals, views::HugrView, ValidationError}, ops, - types::{PolyFixedFunc, Type, TypeBound}, + types::{PolyFuncType, Type, TypeBound}, }; use crate::ops::handle::{AliasID, FuncID, NodeHandle}; @@ -105,7 +105,7 @@ impl + AsRef> ModuleBuilder { pub fn declare( &mut self, name: impl Into, - signature: PolyFixedFunc, + signature: PolyFuncType, ) -> Result, BuildError> { // TODO add param names to metadata let declare_n = self.add_child_node(NodeType::new_pure(ops::FuncDecl { diff --git a/quantinuum-hugr/src/hugr/validate/test.rs b/quantinuum-hugr/src/hugr/validate/test.rs index 3861fa140..3aea28426 100644 --- a/quantinuum-hugr/src/hugr/validate/test.rs +++ b/quantinuum-hugr/src/hugr/validate/test.rs @@ -17,7 +17,7 @@ use crate::std_extensions::logic::{self, NotOp}; use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; use crate::types::type_row::RowVarOrType; use crate::types::{ - CustomType, FuncTypeVarLen, FunctionType, PolyFixedFunc, Type, TypeBound, TypeRow, + CustomType, FuncTypeVarLen, FunctionType, PolyFuncType, Type, TypeBound, TypeRow, }; use crate::{type_row, Direction, IncomingPort, Node}; @@ -435,7 +435,7 @@ fn typevars_declared() -> Result<(), Box> { // Base case let f = FunctionBuilder::new( "myfunc", - PolyFixedFunc::new( + PolyFuncType::new( [TypeBound::Any.into()], FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), @@ -445,7 +445,7 @@ fn typevars_declared() -> Result<(), Box> { // Type refers to undeclared variable let f = FunctionBuilder::new( "myfunc", - PolyFixedFunc::new( + PolyFuncType::new( [TypeBound::Any.into()], FunctionType::new_endo(vec![Type::new_var_use(1, TypeBound::Any)]), ), @@ -455,7 +455,7 @@ fn typevars_declared() -> Result<(), Box> { // Variable declaration incorrectly copied to use site let f = FunctionBuilder::new( "myfunc", - PolyFixedFunc::new( + PolyFuncType::new( [TypeBound::Any.into()], FunctionType::new_endo(vec![Type::new_var_use(1, TypeBound::Copyable)]), ), @@ -473,14 +473,14 @@ fn nested_typevars() -> Result<(), Box> { fn build(t: Type) -> Result { let mut outer = FunctionBuilder::new( "outer", - PolyFixedFunc::new( + PolyFuncType::new( [OUTER_BOUND.into()], FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), )?; let inner = outer.define_function( "inner", - PolyFixedFunc::new([INNER_BOUND.into()], FunctionType::new_endo(vec![t])), + PolyFuncType::new([INNER_BOUND.into()], FunctionType::new_endo(vec![t])), )?; let [w] = inner.input_wires_arr(); inner.finish_with_outputs([w])?; @@ -519,7 +519,7 @@ fn no_polymorphic_consts() -> Result<(), Box> { let reg = ExtensionRegistry::try_new([collections::EXTENSION.to_owned()]).unwrap(); let mut def = FunctionBuilder::new( "myfunc", - PolyFixedFunc::new( + PolyFuncType::new( [BOUND], FunctionType::new(type_row![], vec![list_of_var.clone()]) .with_extension_delta(collections::EXTENSION_NAME), @@ -550,7 +550,7 @@ fn inner_row_variables() -> Result<(), Box> { let inner_ft = Type::new_function(FuncTypeVarLen::new_endo(vec![tv])); let mut fb = FunctionBuilder::new( "id", - PolyFixedFunc::new( + PolyFuncType::new( [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Any }), }], @@ -569,7 +569,7 @@ fn no_outer_row_variables() -> Result<(), Box> { let tv = Type::new_var_use(0, TypeBound::Any); let fb = FunctionBuilder::new( "impossible_id_of_unknown_arity", - PolyFixedFunc::new( + PolyFuncType::new( [TypeParam::List { param: Box::new(TypeParam::Type { b: TypeBound::Any }), }], @@ -596,7 +596,7 @@ fn test_polymorphic_call() -> Result<(), Box> { let mut m = ModuleBuilder::new(); let id = m.declare( "id", - PolyFixedFunc::new( + PolyFuncType::new( vec![TypeBound::Any.into()], FunctionType::new_endo(vec![Type::new_var_use(0, TypeBound::Any)]), ), diff --git a/quantinuum-hugr/src/hugr/views.rs b/quantinuum-hugr/src/hugr/views.rs index ee58cf850..1940128ef 100644 --- a/quantinuum-hugr/src/hugr/views.rs +++ b/quantinuum-hugr/src/hugr/views.rs @@ -29,7 +29,7 @@ use crate::ops::handle::NodeHandle; use crate::ops::{OpParent, OpTag, OpTrait, OpType}; use crate::types::Type; -use crate::types::{EdgeKind, FunctionType, PolyFixedFunc}; +use crate::types::{EdgeKind, FunctionType, PolyFuncType}; use crate::{Direction, IncomingPort, Node, OutgoingPort, Port}; use itertools::Either; @@ -351,12 +351,12 @@ pub trait HugrView: sealed::HugrInternals { /// operation, report the signature of the inner dataflow sibling graph. /// /// Otherwise, returns `None`. - fn get_function_type(&self) -> Option { + 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(PolyFixedFunc::from), + _ => op.inner_function_type().map(PolyFuncType::from), } } diff --git a/quantinuum-hugr/src/ops/dataflow.rs b/quantinuum-hugr/src/ops/dataflow.rs index d886a8720..d4304ab9e 100644 --- a/quantinuum-hugr/src/ops/dataflow.rs +++ b/quantinuum-hugr/src/ops/dataflow.rs @@ -4,7 +4,7 @@ use super::{impl_op_name, OpTag, OpTrait}; use crate::extension::{ExtensionRegistry, ExtensionSet, SignatureError}; use crate::ops::StaticTag; -use crate::types::{EdgeKind, FunctionType, PolyFixedFunc, Type, TypeArg, TypeRow}; +use crate::types::{EdgeKind, FunctionType, PolyFuncType, Type, TypeArg, TypeRow}; use crate::IncomingPort; pub(crate) trait DataflowOpTrait { @@ -153,7 +153,7 @@ impl StaticTag for T { #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct Call { /// Signature of function being called - func_sig: PolyFixedFunc, + func_sig: PolyFuncType, type_args: Vec, instantiation: FunctionType, // Cache, so we can fail in try_new() not in signature() } @@ -181,7 +181,7 @@ impl Call { /// /// [TypeParam]: crate::types::type_param::TypeParam pub fn try_new( - func_sig: PolyFixedFunc, + func_sig: PolyFuncType, type_args: impl Into>, exts: &ExtensionRegistry, ) -> Result { @@ -196,7 +196,7 @@ impl Call { #[inline] /// Return the signature of the function called by this op. - pub fn called_function_type(&self) -> &PolyFixedFunc { + pub fn called_function_type(&self) -> &PolyFuncType { &self.func_sig } @@ -246,7 +246,7 @@ impl DataflowOpTrait for CallIndirect { let mut s = self.signature.clone(); s.input.to_mut().insert( 0, - Type::new_function(PolyFixedFunc::from(self.signature.clone())), + Type::new_function(PolyFuncType::from(self.signature.clone())), ); s } diff --git a/quantinuum-hugr/src/ops/module.rs b/quantinuum-hugr/src/ops/module.rs index a5ebc40cc..060b3354a 100644 --- a/quantinuum-hugr/src/ops/module.rs +++ b/quantinuum-hugr/src/ops/module.rs @@ -2,7 +2,7 @@ use smol_str::SmolStr; -use crate::types::{EdgeKind, FunctionType, PolyFixedFunc}; +use crate::types::{EdgeKind, FunctionType, PolyFuncType}; use crate::types::{Type, TypeBound}; use super::dataflow::DataflowParent; @@ -37,7 +37,7 @@ pub struct FuncDefn { /// Name of function pub name: String, /// Signature of the function - pub signature: PolyFixedFunc, + pub signature: PolyFuncType, } impl_op_name!(FuncDefn); @@ -71,7 +71,7 @@ pub struct FuncDecl { /// Name of function pub name: String, /// Signature of the function - pub signature: PolyFixedFunc, + pub signature: PolyFuncType, } impl_op_name!(FuncDecl); diff --git a/quantinuum-hugr/src/types.rs b/quantinuum-hugr/src/types.rs index 372313556..2d7bcce94 100644 --- a/quantinuum-hugr/src/types.rs +++ b/quantinuum-hugr/src/types.rs @@ -12,7 +12,7 @@ pub use crate::ops::constant::{ConstTypeError, CustomCheckFailure}; use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; -pub use poly_func::{PolyFixedFunc, PolyFuncVarLen}; +pub use poly_func::{PolyFuncType, PolyFuncVarLen}; pub use signature::{FuncTypeVarLen, FunctionType}; use smol_str::SmolStr; pub use type_param::TypeArg; diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs index f9980916d..09ad1cafb 100644 --- a/quantinuum-hugr/src/types/poly_func.rs +++ b/quantinuum-hugr/src/types/poly_func.rs @@ -46,7 +46,9 @@ where /// Type of a function polymorphic over some variables, /// which may include row variables. pub type PolyFuncVarLen = PolyFuncBase; -pub type PolyFixedFunc = PolyFuncBase; + +/// Type of a function polymorphic only over types; i.e. fixed arity. +pub type PolyFuncType = PolyFuncBase; impl From> for PolyFuncBase where @@ -60,8 +62,8 @@ where } } -impl From for PolyFuncVarLen { - fn from(value: PolyFixedFunc) -> Self { +impl From for PolyFuncVarLen { + fn from(value: PolyFuncType) -> Self { Self { params: value.params, body: value.body.into(), From 28aa2f05b870a61ff4855c32d21442527e6c2d72 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 15:38:15 +0100 Subject: [PATCH 48/57] Try to fix, revert define_function change. 2 serialization tests fail --- hugr/src/builder.rs | 6 +- hugr/src/builder/build_traits.rs | 3 +- hugr/src/builder/cfg.rs | 16 +- hugr/src/builder/circuit.rs | 2 +- hugr/src/builder/conditional.rs | 6 +- hugr/src/builder/dataflow.rs | 49 +- hugr/src/builder/module.rs | 7 +- hugr/src/builder/tail_loop.rs | 4 +- hugr/src/extension.rs | 3 +- hugr/src/extension/infer/test.rs | 12 +- hugr/src/extension/op_def.rs | 2 +- hugr/src/hugr/rewrite/consts.rs | 3 +- hugr/src/hugr/rewrite/outline_cfg.rs | 2 +- hugr/src/hugr/rewrite/simple_replace.rs | 2 +- hugr/src/hugr/serialize.rs | 2 +- hugr/src/hugr/views/descendants.rs | 2 +- hugr/src/hugr/views/root_checked.rs | 3 +- hugr/src/hugr/views/sibling.rs | 2 +- hugr/src/hugr/views/tests.rs | 2 +- hugr/src/ops/constant.rs | 5 +- hugr/src/ops/dataflow.rs | 2 +- hugr/src/types.rs | 28 +- hugr/src/types/poly_func.rs | 73 ++- hugr/src/types/serialize.rs | 6 +- hugr/src/types/type_param.rs | 4 +- quantinuum-hugr/src/ops/leaf.rs | 284 --------- quantinuum-hugr/src/types/poly_func.rs | 765 ------------------------ 27 files changed, 151 insertions(+), 1144 deletions(-) delete mode 100644 quantinuum-hugr/src/ops/leaf.rs delete mode 100644 quantinuum-hugr/src/types/poly_func.rs diff --git a/hugr/src/builder.rs b/hugr/src/builder.rs index 79ecc5a2b..bfd361282 100644 --- a/hugr/src/builder.rs +++ b/hugr/src/builder.rs @@ -30,7 +30,7 @@ //! # use hugr::builder::{BuildError, BuildHandle, Container, DFGBuilder, Dataflow, DataflowHugr, ModuleBuilder, DataflowSubContainer, HugrBuilder}; //! use hugr::extension::prelude::BOOL_T; //! use hugr::std_extensions::logic::{NotOp, LOGIC_REG}; -//! use hugr::types::FuncTypeVarLen; +//! use hugr::types::FunctionType; //! //! # fn doctest() -> Result<(), BuildError> { //! let hugr = { @@ -42,7 +42,7 @@ //! let _dfg_handle = { //! let mut dfg = module_builder.define_function( //! "main", -//! FuncTypeVarLen::new(vec![BOOL_T], vec![BOOL_T]).into(), +//! FunctionType::new(vec![BOOL_T], vec![BOOL_T]).into(), //! )?; //! //! // Get the wires from the function inputs. @@ -59,7 +59,7 @@ //! let _circuit_handle = { //! let mut dfg = module_builder.define_function( //! "circuit", -//! FuncTypeVarLen::new(vec![BOOL_T, BOOL_T], vec![BOOL_T, BOOL_T]).into(), +//! FunctionType::new(vec![BOOL_T, BOOL_T], vec![BOOL_T, BOOL_T]).into(), //! )?; //! let mut circuit = dfg.as_circuit(dfg.input_wires()); //! diff --git a/hugr/src/builder/build_traits.rs b/hugr/src/builder/build_traits.rs index eb3dd4b51..7b510df68 100644 --- a/hugr/src/builder/build_traits.rs +++ b/hugr/src/builder/build_traits.rs @@ -85,9 +85,8 @@ pub trait Container { fn define_function( &mut self, name: impl Into, - signature: impl Into, + signature: PolyFuncType, ) -> Result, BuildError> { - let signature = signature.into(); let body = signature.body().clone(); let f_node = self.add_child_node(NodeType::new_pure(ops::FuncDefn { name: name.into(), diff --git a/hugr/src/builder/cfg.rs b/hugr/src/builder/cfg.rs index 072ce5b08..cd2923b12 100644 --- a/hugr/src/builder/cfg.rs +++ b/hugr/src/builder/cfg.rs @@ -5,9 +5,11 @@ use super::{ BasicBlockID, BuildError, CfgID, Container, Dataflow, HugrBuilder, Wire, }; -use crate::extension::{ExtensionRegistry, ExtensionSet}; use crate::ops::{self, handle::NodeHandle, DataflowBlock, DataflowParent, ExitBlock, OpType}; -use crate::types::FunctionType; +use crate::{ + extension::{ExtensionRegistry, ExtensionSet}, + types::FunctionType, +}; use crate::{hugr::views::HugrView, types::TypeRow}; use crate::Node; @@ -47,7 +49,7 @@ use crate::{ /// builder::{BuildError, CFGBuilder, Container, Dataflow, HugrBuilder}, /// Hugr, /// extension::{ExtensionSet, prelude}, -/// types::{FuncTypeVarLen, Type, SumType}, +/// types::{FunctionType, Type, SumType}, /// ops, /// type_row, /// }; @@ -55,7 +57,7 @@ use crate::{ /// const NAT: Type = prelude::USIZE_T; /// /// fn make_cfg() -> Result { -/// let mut cfg_builder = CFGBuilder::new(FuncTypeVarLen::new(type_row![NAT], type_row![NAT]))?; +/// let mut cfg_builder = CFGBuilder::new(FunctionType::new(type_row![NAT], type_row![NAT]))?; /// /// // Outputs from basic blocks must be packed in a sum which corresponds to /// // which successor to pick. We'll either choose the first branch and pass @@ -85,7 +87,7 @@ use crate::{ /// // entry node's `other_outputs`. /// let mut successor_builder = /// cfg_builder.simple_block_builder( -/// FuncTypeVarLen::new(type_row![NAT, NAT], type_row![NAT]), +/// FunctionType::new(type_row![NAT, NAT], type_row![NAT]), /// 1 // only one successor to this block /// )?; /// let successor_a = { @@ -100,7 +102,7 @@ use crate::{ /// /// // The only argument to this block is the entry node's `other_outputs`. /// let mut successor_builder = -/// cfg_builder.simple_block_builder(FuncTypeVarLen::new(type_row![NAT], type_row![NAT]), 1)?; +/// cfg_builder.simple_block_builder(FunctionType::new(type_row![NAT], type_row![NAT]), 1)?; /// let successor_b = { /// let sum_unary = successor_builder.add_load_const(ops::Const::unary_unit_sum()); /// let [in_wire] = successor_builder.input_wires_arr(); @@ -412,7 +414,7 @@ pub(crate) mod test { let build_result = { let mut module_builder = ModuleBuilder::new(); let mut func_builder = module_builder - .define_function("main", FunctionType::new(vec![NAT], type_row![NAT]))?; + .define_function("main", FunctionType::new(vec![NAT], type_row![NAT]).into())?; let _f_id = { let [int] = func_builder.input_wires_arr(); diff --git a/hugr/src/builder/circuit.rs b/hugr/src/builder/circuit.rs index eb220043e..89d6b45a6 100644 --- a/hugr/src/builder/circuit.rs +++ b/hugr/src/builder/circuit.rs @@ -237,7 +237,6 @@ mod test { use super::*; use cool_asserts::assert_matches; - use crate::types::FunctionType; use crate::utils::test_quantum_extension::{cx_gate, h_gate, measure, q_alloc, q_discard}; use crate::{ builder::{ @@ -247,6 +246,7 @@ mod test { extension::prelude::BOOL_T, ops::{custom::OpaqueOp, LeafOp}, type_row, + types::FunctionType, }; #[test] diff --git a/hugr/src/builder/conditional.rs b/hugr/src/builder/conditional.rs index c0e9eaf1d..3c27a8c86 100644 --- a/hugr/src/builder/conditional.rs +++ b/hugr/src/builder/conditional.rs @@ -238,8 +238,10 @@ mod test { fn basic_conditional_module() -> Result<(), BuildError> { let build_result: Result = { let mut module_builder = ModuleBuilder::new(); - let mut fbuild = module_builder - .define_function("main", FunctionType::new(type_row![NAT], type_row![NAT]))?; + let mut fbuild = module_builder.define_function( + "main", + FunctionType::new(type_row![NAT], type_row![NAT]).into(), + )?; let tru_const = fbuild.add_constant(Const::true_val()); let _fdef = { let const_wire = fbuild.load_const(&tru_const); diff --git a/hugr/src/builder/dataflow.rs b/hugr/src/builder/dataflow.rs index 762375fb4..cebdbd242 100644 --- a/hugr/src/builder/dataflow.rs +++ b/hugr/src/builder/dataflow.rs @@ -29,13 +29,8 @@ impl + AsRef> DFGBuilder { signature: FunctionType, input_extensions: Option, ) -> Result { - let FunctionType { - input, - output, - extension_reqs, - } = signature; - let num_in_wires = input.len(); - let num_out_wires = output.len(); + let num_in_wires = signature.input().len(); + let num_out_wires = signature.output().len(); /* For a given dataflow graph with extension requirements IR -> IR + dR, - The output node's extension requirements are IR + dR -> IR + dR (but we expect no output wires) @@ -48,15 +43,19 @@ impl + AsRef> DFGBuilder { from the input wires as we normally expect, but have to infer the output wires and make use of the equality between the two. */ - let input = ops::Input { types: input }; - let output = ops::Output { types: output }; + let input = ops::Input { + types: signature.input().clone(), + }; + let output = ops::Output { + types: signature.output().clone(), + }; base.as_mut() .add_node_with_parent(parent, NodeType::new(input, input_extensions.clone())); base.as_mut().add_node_with_parent( parent, NodeType::new( output, - input_extensions.map(|inp| inp.union(extension_reqs)), + input_extensions.map(|inp| inp.union(signature.extension_reqs)), ), ); @@ -208,17 +207,23 @@ pub(crate) mod test { use serde_json::json; use crate::builder::build_traits::DataflowHugr; - use crate::builder::{BuildError, BuilderWiringError, DataflowSubContainer, ModuleBuilder}; + use crate::builder::{BuilderWiringError, DataflowSubContainer, ModuleBuilder}; use crate::extension::prelude::BOOL_T; - use crate::extension::{ExtensionId, ExtensionSet, EMPTY_REG}; + use crate::extension::{ExtensionId, EMPTY_REG}; use crate::hugr::validate::InterGraphEdgeError; use crate::ops::{handle::NodeHandle, LeafOp, OpTag}; - use crate::builder::test::{n_identity, BIT, NAT, QB}; use crate::std_extensions::logic::test::and_op; use crate::types::Type; use crate::utils::test_quantum_extension::h_gate; - use crate::{type_row, Wire}; + use crate::{ + builder::{ + test::{n_identity, BIT, NAT, QB}, + BuildError, + }, + extension::ExtensionSet, + type_row, Wire, + }; use super::super::test::simple_dfg_hugr; use super::*; @@ -230,7 +235,7 @@ pub(crate) mod test { let _f_id = { let mut func_builder = module_builder.define_function( "main", - FunctionType::new(type_row![NAT, QB], type_row![NAT, QB]), + FunctionType::new(type_row![NAT, QB], type_row![NAT, QB]).into(), )?; let [int, qb] = func_builder.input_wires_arr(); @@ -264,7 +269,7 @@ pub(crate) mod test { let f_build = module_builder.define_function( "main", - FunctionType::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]), + FunctionType::new(type_row![BOOL_T], type_row![BOOL_T, BOOL_T]).into(), )?; f(f_build)?; @@ -312,8 +317,10 @@ pub(crate) mod test { let builder = || { let mut module_builder = ModuleBuilder::new(); - let f_build = module_builder - .define_function("main", FunctionType::new(type_row![QB], type_row![QB, QB]))?; + let f_build = module_builder.define_function( + "main", + FunctionType::new(type_row![QB], type_row![QB, QB]).into(), + )?; let [q1] = f_build.input_wires_arr(); f_build.finish_with_outputs([q1, q1])?; @@ -403,8 +410,10 @@ pub(crate) mod test { let mut module_builder = ModuleBuilder::new(); let (dfg_node, f_node) = { - let mut f_build = module_builder - .define_function("main", FunctionType::new(type_row![BIT], type_row![BIT]))?; + let mut f_build = module_builder.define_function( + "main", + FunctionType::new(type_row![BIT], type_row![BIT]).into(), + )?; let [i1] = f_build.input_wires_arr(); let dfg = f_build.add_hugr_with_wires(dfg_hugr, [i1])?; diff --git a/hugr/src/builder/module.rs b/hugr/src/builder/module.rs index 3ea607737..f6b4b7f20 100644 --- a/hugr/src/builder/module.rs +++ b/hugr/src/builder/module.rs @@ -208,7 +208,8 @@ mod test { FunctionType::new( vec![qubit_state_type.get_alias_type()], vec![qubit_state_type.get_alias_type()], - ), + ) + .into(), )?; n_identity(f_build)?; module_builder.finish_hugr(&EMPTY_REG) @@ -224,11 +225,11 @@ mod test { let mut f_build = module_builder.define_function( "main", - FunctionType::new(type_row![NAT], type_row![NAT, NAT]), + FunctionType::new(type_row![NAT], type_row![NAT, NAT]).into(), )?; let local_build = f_build.define_function( "local", - FunctionType::new(type_row![NAT], type_row![NAT, NAT]), + FunctionType::new(type_row![NAT], type_row![NAT, NAT]).into(), )?; let [wire] = local_build.input_wires_arr(); let f_id = local_build.finish_with_outputs([wire, wire])?; diff --git a/hugr/src/builder/tail_loop.rs b/hugr/src/builder/tail_loop.rs index d70f0d4e8..3d3022253 100644 --- a/hugr/src/builder/tail_loop.rs +++ b/hugr/src/builder/tail_loop.rs @@ -126,7 +126,9 @@ mod test { let mut module_builder = ModuleBuilder::new(); let mut fbuild = module_builder.define_function( "main", - FunctionType::new(type_row![BIT], type_row![NAT]).with_extension_delta(PRELUDE_ID), + FunctionType::new(type_row![BIT], type_row![NAT]) + .with_extension_delta(PRELUDE_ID) + .into(), )?; let _fdef = { let [b1] = fbuild diff --git a/hugr/src/extension.rs b/hugr/src/extension.rs index abedb0c27..a1973585d 100644 --- a/hugr/src/extension.rs +++ b/hugr/src/extension.rs @@ -17,8 +17,9 @@ use crate::ops; use crate::ops::custom::{ExtensionOp, OpaqueOp}; use crate::types::type_param::{check_type_args, TypeArgError}; use crate::types::type_param::{TypeArg, TypeParam}; +use crate::types::FunctionType; use crate::types::{ - check_typevar_decl, CustomType, PolyFuncVarLen, Substitution, TypeBound, TypeName, + check_typevar_decl, CustomType, Substitution, TypeBound, TypeName, }; #[allow(dead_code)] diff --git a/hugr/src/extension/infer/test.rs b/hugr/src/extension/infer/test.rs index 2a948a6c8..d9cba6793 100644 --- a/hugr/src/extension/infer/test.rs +++ b/hugr/src/extension/infer/test.rs @@ -157,7 +157,7 @@ fn plus() -> Result<(), InferExtensionError> { // because of a missing lift node fn missing_lift_node() { let mut hugr = Hugr::new(NodeType::new_pure(ops::DFG { - signature: FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).with_extension_delta(A), + signature: FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(A), })); let input = hugr.add_node_with_parent( @@ -218,7 +218,7 @@ fn dangling_src() -> Result<(), Box> { let rs = ExtensionSet::singleton(&"R".try_into().unwrap()); let mut hugr = closed_dfg_root_hugr( - FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).with_extension_delta(rs.clone()), + FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(rs.clone()), ); let [input, output] = hugr.get_io(hugr.root()).unwrap(); @@ -1015,7 +1015,9 @@ fn simple_funcdefn() -> Result<(), Box> { let mut builder = ModuleBuilder::new(); let mut func_builder = builder.define_function( "F", - FunctionType::new(vec![NAT], vec![NAT]).with_extension_delta(A), + FunctionType::new(vec![NAT], vec![NAT]) + .with_extension_delta(A) + .into(), )?; let [w] = func_builder.input_wires_arr(); @@ -1038,7 +1040,7 @@ fn funcdefn_signature_mismatch() -> Result<(), Box> { let mut builder = ModuleBuilder::new(); let mut func_builder = builder.define_function( "F", - FuncTypeVarLen::new(vec![NAT], vec![NAT]) + FunctionType::new(vec![NAT], vec![NAT]) .with_extension_delta(A) .into(), )?; @@ -1073,7 +1075,7 @@ fn funcdefn_signature_mismatch2() -> Result<(), Box> { let mut builder = ModuleBuilder::new(); let func_builder = builder.define_function( "F", - FuncTypeVarLen::new(vec![NAT], vec![NAT]) + FunctionType::new(vec![NAT], vec![NAT]) .with_extension_delta(A) .into(), )?; diff --git a/hugr/src/extension/op_def.rs b/hugr/src/extension/op_def.rs index 92060ec6f..6ede2e503 100644 --- a/hugr/src/extension/op_def.rs +++ b/hugr/src/extension/op_def.rs @@ -195,7 +195,7 @@ impl From for SignatureFunc { } impl From for SignatureFunc { - // ALAN might want to be Signature? + // ALAN might want to be FunctionType? fn from(v: FuncTypeVarLen) -> Self { Self::TypeScheme(CustomValidator::from_polyfunc(v)) } diff --git a/hugr/src/hugr/rewrite/consts.rs b/hugr/src/hugr/rewrite/consts.rs index d48551e94..3fbd0aabd 100644 --- a/hugr/src/hugr/rewrite/consts.rs +++ b/hugr/src/hugr/rewrite/consts.rs @@ -128,7 +128,8 @@ mod test { let mut build = ModuleBuilder::new(); let con_node = build.add_constant(ConstUsize::new(2)); - let mut dfg_build = build.define_function("main", FunctionType::new_endo(type_row![]))?; + let mut dfg_build = + build.define_function("main", FunctionType::new_endo(type_row![]).into())?; let load_1 = dfg_build.load_const(&con_node); let load_2 = dfg_build.load_const(&con_node); let tup = dfg_build.add_dataflow_op( diff --git a/hugr/src/hugr/rewrite/outline_cfg.rs b/hugr/src/hugr/rewrite/outline_cfg.rs index 88c1b2bd1..43f3b12f9 100644 --- a/hugr/src/hugr/rewrite/outline_cfg.rs +++ b/hugr/src/hugr/rewrite/outline_cfg.rs @@ -351,7 +351,7 @@ mod test { let mut fbuild = module_builder .define_function( "main", - FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]), + FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]).into(), ) .unwrap(); let [i1] = fbuild.input_wires_arr(); diff --git a/hugr/src/hugr/rewrite/simple_replace.rs b/hugr/src/hugr/rewrite/simple_replace.rs index f18bf7387..ebee0d1bf 100644 --- a/hugr/src/hugr/rewrite/simple_replace.rs +++ b/hugr/src/hugr/rewrite/simple_replace.rs @@ -234,7 +234,7 @@ pub(in crate::hugr::rewrite) mod test { let _f_id = { let mut func_builder = module_builder.define_function( "main", - FunctionType::new(type_row![QB, QB, QB], type_row![QB, QB, QB]), + FunctionType::new(type_row![QB, QB, QB], type_row![QB, QB, QB]).into(), )?; let [qb0, qb1, qb2] = func_builder.input_wires_arr(); diff --git a/hugr/src/hugr/serialize.rs b/hugr/src/hugr/serialize.rs index 5d0d51e3e..f1253a0a4 100644 --- a/hugr/src/hugr/serialize.rs +++ b/hugr/src/hugr/serialize.rs @@ -436,7 +436,7 @@ pub mod test { let t_row = vec![Type::new_sum([type_row![NAT], type_row![QB]])]; let mut f_build = module_builder - .define_function("main", FunctionType::new(t_row.clone(), t_row)) + .define_function("main", FunctionType::new(t_row.clone(), t_row).into()) .unwrap(); let outputs = f_build diff --git a/hugr/src/hugr/views/descendants.rs b/hugr/src/hugr/views/descendants.rs index 58831c325..453503509 100644 --- a/hugr/src/hugr/views/descendants.rs +++ b/hugr/src/hugr/views/descendants.rs @@ -222,7 +222,7 @@ pub(super) mod test { let (f_id, inner_id) = { let mut func_builder = module_builder.define_function( "main", - FunctionType::new(type_row![NAT, QB], type_row![NAT, QB]), + FunctionType::new(type_row![NAT, QB], type_row![NAT, QB]).into(), )?; let [int, qb] = func_builder.input_wires_arr(); diff --git a/hugr/src/hugr/views/root_checked.rs b/hugr/src/hugr/views/root_checked.rs index b21ac2abb..39aa332a8 100644 --- a/hugr/src/hugr/views/root_checked.rs +++ b/hugr/src/hugr/views/root_checked.rs @@ -75,8 +75,7 @@ mod test { use crate::hugr::{HugrError, HugrMut, NodeType}; use crate::ops::handle::{BasicBlockID, CfgID, DataflowParentID, DfgID}; use crate::ops::{DataflowBlock, LeafOp, OpTag}; - use crate::types::FunctionType; - use crate::{ops, type_row, Hugr, HugrView}; + use crate::{ops, type_row, types::FunctionType, Hugr, HugrView}; #[test] fn root_checked() { diff --git a/hugr/src/hugr/views/sibling.rs b/hugr/src/hugr/views/sibling.rs index 56068ecb1..7d69cc4b0 100644 --- a/hugr/src/hugr/views/sibling.rs +++ b/hugr/src/hugr/views/sibling.rs @@ -406,7 +406,7 @@ mod test { fn nested_flat() -> Result<(), Box> { let mut module_builder = ModuleBuilder::new(); let fty = FunctionType::new(type_row![NAT], type_row![NAT]); - let mut fbuild = module_builder.define_function("main", fty.clone())?; + let mut fbuild = module_builder.define_function("main", fty.clone().into())?; let dfg = fbuild.dfg_builder(fty, None, fbuild.input_wires())?; let ins = dfg.input_wires(); let sub_dfg = dfg.finish_with_outputs(ins)?; diff --git a/hugr/src/hugr/views/tests.rs b/hugr/src/hugr/views/tests.rs index dfa4b9712..678459578 100644 --- a/hugr/src/hugr/views/tests.rs +++ b/hugr/src/hugr/views/tests.rs @@ -181,7 +181,7 @@ fn test_dataflow_ports_only() { let local_and = dfg .define_function( "and", - FunctionType::new(type_row![BOOL_T; 2], type_row![BOOL_T]), + FunctionType::new(type_row![BOOL_T; 2], type_row![BOOL_T]).into(), ) .unwrap(); let first_input = local_and.input().out_wire(0); diff --git a/hugr/src/ops/constant.rs b/hugr/src/ops/constant.rs index 09d3edcd9..058dd16e2 100644 --- a/hugr/src/ops/constant.rs +++ b/hugr/src/ops/constant.rs @@ -285,7 +285,6 @@ where mod test { use super::Const; use crate::builder::test::simple_dfg_hugr; - use crate::types::FunctionType; use crate::{ builder::{BuildError, DFGBuilder, Dataflow, DataflowHugr}, extension::{ @@ -296,7 +295,7 @@ mod test { std_extensions::arithmetic::float_types::{self, ConstF64, FLOAT64_TYPE}, type_row, types::type_param::TypeArg, - types::{CustomType, FuncTypeVarLen, Type, TypeBound, TypeRow}, + types::{CustomType, FunctionType, Type, TypeBound, TypeRow}, }; use cool_asserts::assert_matches; use rstest::{fixture, rstest}; @@ -416,7 +415,7 @@ mod test { fn function_value(simple_dfg_hugr: Hugr) { let v = Const::function(simple_dfg_hugr).unwrap(); - let correct_type = Type::new_function(FuncTypeVarLen::new_endo(type_row![ + let correct_type = Type::new_function(FunctionType::new_endo(type_row![ crate::extension::prelude::BOOL_T ])); diff --git a/hugr/src/ops/dataflow.rs b/hugr/src/ops/dataflow.rs index 95561791d..27312d9bf 100644 --- a/hugr/src/ops/dataflow.rs +++ b/hugr/src/ops/dataflow.rs @@ -261,7 +261,7 @@ impl DataflowOpTrait for CallIndirect { let mut s = self.signature.clone(); s.input.to_mut().insert( 0, - Type::new_function(PolyFuncType::from(self.signature.clone())), + Type::new_function(self.signature.clone()), ); s } diff --git a/hugr/src/types.rs b/hugr/src/types.rs index cb2d98edb..4a261c0d1 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -9,7 +9,7 @@ pub mod type_param; pub mod type_row; pub use crate::ops::constant::{ConstTypeError, CustomCheckFailure}; -use crate::types::type_param::check_type_arg; +use crate::types::type_param::{check_type_arg, TypeArgVariable}; use crate::utils::display_list_with_separator; pub use check::SumTypeError; pub use custom::CustomType; @@ -199,7 +199,7 @@ pub enum TypeEnum { Alias(AliasDecl), #[allow(missing_docs)] #[display(fmt = "Function({})", "_0")] - Function(Box), + Function(Box), // Index into TypeParams, and cache of TypeBound (checked in validation) #[allow(missing_docs)] #[display(fmt = "Variable({})", _0)] @@ -230,7 +230,7 @@ impl TypeEnum { Clone, PartialEq, Debug, Eq, derive_more::Display, serde::Serialize, serde::Deserialize, )] #[display(fmt = "{}", "_0")] -#[serde(into = "serialize::SerSimpleType", from = "serialize::SerSimpleType")] +#[serde(into = "serialize::SerSimpleType", try_from = "serialize::SerSimpleType")] /// A HUGR type - the valid types of [EdgeKind::Value] and [EdgeKind::Const] edges. /// Such an edge is valid if the ports on either end agree on the [Type]. /// Types have an optional [TypeBound] which places limits on the valid @@ -263,13 +263,14 @@ impl Type { /// Unit type (empty tuple). pub const UNIT: Self = Self(TypeEnum::Sum(SumType::Unit { size: 1 }), TypeBound::Eq); + #[allow(unused)] const EMPTY_TYPEROW_REF: &'static TypeRow = &Self::EMPTY_TYPEROW; const EMPTY_VL_TYPEROW: TypeRowVarLen = TypeRowVarLen::new(); const EMPTY_VL_TYPEROW_REF: &'static TypeRowVarLen = &Self::EMPTY_VL_TYPEROW; /// Initialize a new function type. - pub fn new_function(fun_ty: impl Into) -> Self { + pub fn new_function(fun_ty: impl Into) -> Self { Self::new(TypeEnum::Function(Box::new(fun_ty.into()))) } @@ -396,8 +397,21 @@ impl<'a> Substitution<'a> { arg.clone() } - fn apply_rowvar(&self, idx: usize, bound: TypeBound) -> Vec { - vec![RowVarOrType::T(self.apply_typevar(idx, bound))] + fn apply_rowvar(&self, idx: usize, _bound: TypeBound) -> Vec { + fn flatten(ta: &TypeArg) -> Vec { + match ta { + TypeArg::Type { ty } => return vec![RowVarOrType::T(ty.clone())], + TypeArg::Sequence { elems } => return elems.iter().flat_map(flatten).collect(), + TypeArg::Variable { v: TypeArgVariable { idx, cached_decl: TypeParam::List { param }} } => { + if let TypeParam::Type { b } = &**param { + return vec![RowVarOrType::RV(*idx, *b)] + } + } + _ => () + } + panic!("TypeArg in a Row (List) was not a type or sequence") + } + flatten(self.0.get(idx).expect("Undeclared type variable - call validate() ?")) } fn extension_registry(&self) -> &ExtensionRegistry { @@ -447,7 +461,7 @@ pub(crate) mod test { fn construct() { let t: Type = Type::new_tuple(vec![ USIZE_T, - Type::new_function(FuncTypeVarLen::default()), + Type::new_function(FunctionType::new_endo(vec![])), Type::new_extension(CustomType::new( "my_custom", [], diff --git a/hugr/src/types/poly_func.rs b/hugr/src/types/poly_func.rs index d3717ece3..4fc2d7009 100644 --- a/hugr/src/types/poly_func.rs +++ b/hugr/src/types/poly_func.rs @@ -3,14 +3,16 @@ use crate::extension::{ExtensionRegistry, SignatureError}; use itertools::Itertools; +use super::signature::{FuncTypeBase, TypeRowElem}; use super::type_param::{check_type_args, TypeArg, TypeParam}; -use super::{FunctionType, Substitution}; +use super::{RowVarOrType, Substitution, Type}; /// A polymorphic type scheme, i.e. of a [FuncDecl], [FuncDefn] or [OpDef]. -/// (Nodes/operations in the Hugr are not polymorphic.) +/// (Nodes/operations in the Hugr and runtime [Graph] values are monomorphic.) /// /// [FuncDecl]: crate::ops::module::FuncDecl /// [FuncDefn]: crate::ops::module::FuncDefn +/// [Graph]: crate::ops::constant::Const::Function /// [OpDef]: crate::extension::OpDef #[derive( Clone, PartialEq, Debug, Default, Eq, derive_more::Display, serde::Serialize, serde::Deserialize, @@ -20,17 +22,28 @@ use super::{FunctionType, Substitution}; "params.iter().map(ToString::to_string).join(\" \")", "body" )] -pub struct PolyFuncType { +pub struct PolyFuncBase +where T: TypeRowElem, [T]: ToOwned> { /// The declared type parameters, i.e., these must be instantiated with /// the same number of [TypeArg]s before the function can be called. This /// defines the indices used by variables inside the body. params: Vec, /// Template for the function. May contain variables up to length of [Self::params] - body: FunctionType, + body: FuncTypeBase, } -impl From for PolyFuncType { - fn from(body: FunctionType) -> Self { +/// A polymorphic type scheme which may include row variables, hence the +/// actual number of inputs/outputs may vary according to instantiation. +pub type PolyFuncVarLen = PolyFuncBase; + +/// A type scheme that is polymorphic only over types, so fixed arity. +pub type PolyFuncType = PolyFuncBase; + +impl From> for PolyFuncBase +where + [T]: ToOwned>, +{ + fn from(body: FuncTypeBase) -> Self { Self { params: vec![], body, @@ -38,47 +51,60 @@ impl From for PolyFuncType { } } -impl TryFrom for FunctionType { - /// If the PolyFuncType is not a monomorphic FunctionType, fail with the binders +impl TryFrom> for FuncTypeBase { + /// If conversion fails, return the binders (which prevent conversion) type Error = Vec; - fn try_from(value: PolyFuncType) -> Result { - if value.params.is_empty() { - Ok(value.body) - } else { - Err(value.params) + fn try_from(value: PolyFuncBase) -> Result { + if value.params.is_empty() {Ok(value.body)} + else {Err(value.params)} + } +} + +impl From for PolyFuncVarLen { + fn from(value: PolyFuncType) -> Self { + Self { + params: value.params, + body: value.body.into(), } } } -impl PolyFuncType { +impl PolyFuncBase +where + [T]: ToOwned>, +{ /// The type parameters, aka binders, over which this type is polymorphic pub fn params(&self) -> &[TypeParam] { &self.params } /// The body of the type, a function type. - pub fn body(&self) -> &FunctionType { + pub fn body(&self) -> &FuncTypeBase { &self.body } - /// Create a new PolyFuncType given the kinds of the variables it declares - /// and the underlying [FunctionType]. - pub fn new(params: impl Into>, body: FunctionType) -> Self { + /// Create a new PolyFuncBase given the kinds of the variables it declares + /// and the underlying [FuncTypeVarLen]. + pub fn new(params: impl Into>, body: impl Into>) -> Self { Self { params: params.into(), - body, + body: body.into(), } } /// Validates this instance, checking that the types in the body are - /// wellformed with respect to the registry, and the type variables declared. - pub fn validate(&self, reg: &ExtensionRegistry) -> Result<(), SignatureError> { + /// wellformed with respect to the registry, and that all type variables + /// are declared (perhaps in an enclosing scope, kinds passed in). + pub fn validate( + &self, + reg: &ExtensionRegistry + ) -> Result<(), SignatureError> { // TODO https://github.com/CQCL/hugr/issues/624 validate TypeParams declared here, too self.body.validate(reg, &self.params) } - /// Instantiates an outer [PolyFuncType], i.e. with no free variables + /// Instantiates an outer [PolyFuncBase], i.e. with no free variables /// (as ensured by [Self::validate]), into a monomorphic type. /// /// # Errors @@ -88,14 +114,13 @@ impl PolyFuncType { &self, args: &[TypeArg], ext_reg: &ExtensionRegistry, - ) -> Result { + ) -> Result, SignatureError> { // Check that args are applicable, and that we have a value for each binder, // i.e. each possible free variable within the body. check_type_args(args, &self.params)?; Ok(self.body.substitute(&Substitution(args, ext_reg))) } } - #[cfg(test)] pub(crate) mod test { use std::num::NonZeroU64; diff --git a/hugr/src/types/serialize.rs b/hugr/src/types/serialize.rs index dbb8117e3..50515f75a 100644 --- a/hugr/src/types/serialize.rs +++ b/hugr/src/types/serialize.rs @@ -1,4 +1,4 @@ -use super::{FunctionType, SumType, Type, TypeArg, TypeBound, TypeEnum}; +use super::{FuncTypeVarLen, RowVarOrType, SumType, Type, TypeArg, TypeBound, TypeEnum}; use super::custom::CustomType; @@ -10,7 +10,7 @@ use crate::ops::AliasDecl; pub(super) enum SerSimpleType { Q, I, - G(Box), + G(Box), Sum(SumType), Array { inner: Box, len: u64 }, Opaque(CustomType), @@ -68,7 +68,7 @@ impl TryFrom for Type { match value.into() { RowVarOrType::T(t) => Ok(t), RowVarOrType::RV(idx, bound) => Err(format!( - "Type contained Row Variable with DeBruijn index {idx} and bound {bound}" + "Type contained Row Variable with index {idx} and bound {bound}" )), } } diff --git a/hugr/src/types/type_param.rs b/hugr/src/types/type_param.rs index 601dfda14..b6254a4f5 100644 --- a/hugr/src/types/type_param.rs +++ b/hugr/src/types/type_param.rs @@ -172,8 +172,8 @@ pub enum TypeArg { /// Variable in a TypeArg, that is not a [TypeArg::Type] or [TypeArg::Extensions], #[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)] pub struct TypeArgVariable { - idx: usize, - cached_decl: TypeParam, + pub(super) idx: usize, + pub(super) cached_decl: TypeParam, } impl TypeArg { diff --git a/quantinuum-hugr/src/ops/leaf.rs b/quantinuum-hugr/src/ops/leaf.rs deleted file mode 100644 index 3025a2c38..000000000 --- a/quantinuum-hugr/src/ops/leaf.rs +++ /dev/null @@ -1,284 +0,0 @@ -//! Definition of the leaf operations. - -use smol_str::SmolStr; - -use super::custom::{ExtensionOp, ExternalOp}; -use super::dataflow::DataflowOpTrait; -use super::{OpName, OpTag}; - -use crate::extension::{ExtensionId, ExtensionRegistry, ExtensionSet, SignatureError}; -use crate::types::type_param::TypeArg; -use crate::types::{EdgeKind, FunctionType, PolyFuncVarLen, Type, TypeRow}; - -/// Dataflow operations with no children. -#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -#[non_exhaustive] -#[serde(tag = "lop")] -pub enum LeafOp { - /// A user-defined operation that can be downcasted by the extensions that - /// define it. - CustomOp(Box), - - /// A no-op operation. - Noop { - /// The type of edges connecting the Noop. - ty: Type, - }, - /// An operation that packs all its inputs into a tuple. - MakeTuple { - ///Tuple element types. - tys: TypeRow, - }, - /// An operation that unpacks a tuple into its components. - UnpackTuple { - ///Tuple element types. - tys: TypeRow, - }, - /// An operation that creates a tagged sum value from one of its variants. - Tag { - /// The variant to create. - tag: usize, - /// The variants of the sum type. - variants: Vec, - }, - /// A node which adds a extension req to the types of the wires it is passed - /// It has no effect on the values passed along the edge - Lift { - /// The types of the edges - type_row: TypeRow, - /// The extensions which we're adding to the inputs - new_extension: ExtensionId, - }, - /// Fixes some [TypeParam]s of a polymorphic type by providing [TypeArg]s - /// - /// [TypeParam]: crate::types::type_param::TypeParam - TypeApply { - /// The type and args, plus a cache of the resulting type - ta: TypeApplication, - }, -} - -impl LeafOp { - /// If instance of [ExtensionOp] return a reference to it. - pub fn as_extension_op(&self) -> Option<&ExtensionOp> { - let LeafOp::CustomOp(ext) = self else { - return None; - }; - - match ext.as_ref() { - ExternalOp::Extension(e) => Some(e), - ExternalOp::Opaque(_) => None, - } - } -} - -/// Records details of an application of a [PolyFuncType] to some [TypeArg]s -/// and the result (a less-, but still potentially-, polymorphic type). -#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub struct TypeApplication { - input: PolyFuncVarLen, - args: Vec, - output: PolyFuncVarLen, // cached -} - -impl TypeApplication { - /// Checks that the specified args are correct for the [TypeParam]s of the polymorphic input. - /// Note the extension registry is required here to recompute [Type::least_upper_bound]s. - /// - /// [TypeParam]: crate::types::type_param::TypeParam - pub fn try_new( - input: PolyFuncVarLen, - args: impl Into>, - extension_registry: &ExtensionRegistry, - ) -> Result { - let args = args.into(); - // Should we require >=1 `arg`s here? Or that input declares >=1 params? - // At the moment we allow an identity TypeApply on a monomorphic function type. - let output = input.instantiate_poly(&args, extension_registry)?; - Ok(Self { - input, - args, - output, - }) - } - - pub(crate) fn validate( - &self, - extension_registry: &ExtensionRegistry, - ) -> Result<(), SignatureError> { - let other = Self::try_new(self.input.clone(), self.args.clone(), extension_registry)?; - if other.output == self.output { - Ok(()) - } else { - Err(SignatureError::TypeApplyIncorrectCache { - cached: self.output.clone(), - expected: other.output.clone(), - }) - } - } - - /// Returns the type of the input function. - pub fn input(&self) -> &PolyFuncVarLen { - &self.input - } - - /// Returns the args applied to the input function. - pub fn args(&self) -> &[TypeArg] { - &self.args - } - - /// Returns the type of the output function. - pub fn output(&self) -> &PolyFuncVarLen { - &self.output - } -} - -impl Default for LeafOp { - fn default() -> Self { - Self::Noop { ty: Type::UNIT } - } -} -impl OpName for LeafOp { - /// The name of the operation. - fn name(&self) -> SmolStr { - match self { - LeafOp::CustomOp(ext) => return ext.name(), - LeafOp::Noop { ty: _ } => "Noop", - LeafOp::MakeTuple { tys: _ } => "MakeTuple", - LeafOp::UnpackTuple { tys: _ } => "UnpackTuple", - LeafOp::Tag { .. } => "Tag", - LeafOp::Lift { .. } => "Lift", - LeafOp::TypeApply { .. } => "TypeApply", - } - .into() - } -} - -// impl StaticTag for LeafOp { -// } - -impl DataflowOpTrait for LeafOp { - const TAG: OpTag = OpTag::Leaf; - /// A human-readable description of the operation. - fn description(&self) -> &str { - match self { - LeafOp::CustomOp(ext) => ext.description(), - LeafOp::Noop { ty: _ } => "Noop gate", - LeafOp::MakeTuple { tys: _ } => "MakeTuple operation", - LeafOp::UnpackTuple { tys: _ } => "UnpackTuple operation", - LeafOp::Tag { .. } => "Tag Sum operation", - LeafOp::Lift { .. } => "Add a extension requirement to an edge", - LeafOp::TypeApply { .. } => { - "Instantiate (perhaps partially) a polymorphic type with some type arguments" - } - } - } - - /// The signature of the operation. - fn signature(&self) -> FunctionType { - // Static signatures. The `TypeRow`s in the `FuncTypeVarLen` use a - // copy-on-write strategy, so we can avoid unnecessary allocations. - - match self { - LeafOp::Noop { ty: typ } => FunctionType::new(vec![typ.clone()], vec![typ.clone()]), - LeafOp::CustomOp(ext) => ext.signature(), - LeafOp::MakeTuple { tys: types } => { - FunctionType::new(types.clone(), vec![Type::new_tuple(types.clone())]) - } - LeafOp::UnpackTuple { tys: types } => { - FunctionType::new(vec![Type::new_tuple(types.clone())], types.clone()) - } - LeafOp::Tag { tag, variants } => FunctionType::new( - variants.get(*tag).expect("Not a valid tag").clone(), - vec![Type::new_sum(variants.clone())], - ), - LeafOp::Lift { - type_row, - new_extension, - } => FunctionType::new(type_row.clone(), type_row.clone()) - .with_extension_delta(ExtensionSet::singleton(new_extension)), - LeafOp::TypeApply { ta } => FunctionType::new( - vec![Type::new_function(ta.input.clone())], - vec![Type::new_function(ta.output.clone())], - ), - } - } - - fn other_input(&self) -> Option { - Some(EdgeKind::StateOrder) - } - - fn other_output(&self) -> Option { - Some(EdgeKind::StateOrder) - } -} - -#[cfg(test)] -mod test { - use crate::builder::{BuildError, DFGBuilder, Dataflow, DataflowHugr}; - use crate::extension::prelude::BOOL_T; - use crate::extension::{prelude::USIZE_T, PRELUDE}; - use crate::extension::{ExtensionRegistry, SignatureError}; - use crate::hugr::ValidationError; - use crate::ops::handle::NodeHandle; - use crate::std_extensions::collections::EXTENSION; - use crate::types::test::nested_func; - use crate::types::{FunctionType, Type, TypeArg}; - - use super::{LeafOp, TypeApplication}; - - const USIZE_TA: TypeArg = TypeArg::Type { ty: USIZE_T }; - - #[test] - fn hugr_with_type_apply() -> Result<(), Box> { - let reg = ExtensionRegistry::try_new([PRELUDE.to_owned(), EXTENSION.to_owned()]).unwrap(); - let pf_in = nested_func(); - let pf_out = pf_in.instantiate(&[USIZE_TA], ®)?; - let mut dfg = DFGBuilder::new(FunctionType::new( - vec![Type::new_function(pf_in.clone())], - vec![Type::new_function(pf_out)], - ))?; - let ta = dfg.add_dataflow_op( - LeafOp::TypeApply { - ta: TypeApplication::try_new(pf_in, [USIZE_TA], ®).unwrap(), - }, - dfg.input_wires(), - )?; - dfg.finish_hugr_with_outputs(ta.outputs(), ®)?; - Ok(()) - } - - #[test] - fn bad_type_apply() -> Result<(), Box> { - let reg = ExtensionRegistry::try_new([PRELUDE.to_owned(), EXTENSION.to_owned()]).unwrap(); - let pf = nested_func(); - let pf_usz = pf.instantiate_poly(&[USIZE_TA], ®)?; - let pf_bool = pf.instantiate_poly(&[TypeArg::Type { ty: BOOL_T }], ®)?; - let mut dfg = DFGBuilder::new(FunctionType::new( - vec![Type::new_function(pf.clone())], - vec![Type::new_function(pf_usz.clone())], - ))?; - let ta = dfg.add_dataflow_op( - LeafOp::TypeApply { - ta: TypeApplication { - input: pf, - args: vec![TypeArg::Type { ty: BOOL_T }], - output: pf_usz.clone(), - }, - }, - dfg.input_wires(), - )?; - let res = dfg.finish_hugr_with_outputs(ta.outputs(), ®); - assert_eq!( - res.unwrap_err(), - BuildError::InvalidHUGR(ValidationError::SignatureError { - node: ta.node(), - cause: SignatureError::TypeApplyIncorrectCache { - cached: pf_usz, - expected: pf_bool - } - }) - ); - Ok(()) - } -} diff --git a/quantinuum-hugr/src/types/poly_func.rs b/quantinuum-hugr/src/types/poly_func.rs deleted file mode 100644 index 09ad1cafb..000000000 --- a/quantinuum-hugr/src/types/poly_func.rs +++ /dev/null @@ -1,765 +0,0 @@ -//! Polymorphic Function Types - -use crate::{ - extension::{ExtensionRegistry, SignatureError}, - types::type_param::check_type_arg, -}; -use itertools::Itertools; - -use super::{ - signature::{FuncTypeBase, TypeRowElem}, - type_param::{check_type_args, TypeArg, TypeParam}, - type_row::RowVarOrType, - Type, -}; -use super::{Substitution, TypeBound}; - -/// A polymorphic function type, e.g. of a [Graph], or perhaps an [OpDef]. -/// (Nodes/operations in the Hugr are not polymorphic.) -/// -/// [Graph]: crate::ops::constant::Const::Function -/// [OpDef]: crate::extension::OpDef -#[derive( - Clone, PartialEq, Debug, Default, Eq, derive_more::Display, serde::Serialize, serde::Deserialize, -)] -#[display( - fmt = "forall {}. {}", - "params.iter().map(ToString::to_string).join(\" \")", - "body" -)] -pub struct PolyFuncBase -where - T: TypeRowElem, - [T]: ToOwned>, -{ - /// The declared type parameters, i.e., these must be instantiated with - /// the same number of [TypeArg]s before the function can be called. Note that within - /// the [Self::body], variable (DeBruijn) index 0 is element 0 of this array, i.e. the - /// variables are bound from right to left. - /// - /// [TypeArg]: super::type_param::TypeArg - params: Vec, - /// Template for the function. May contain variables up to length of [Self::params] - body: FuncTypeBase, -} - -/// Type of a function polymorphic over some variables, -/// which may include row variables. -pub type PolyFuncVarLen = PolyFuncBase; - -/// Type of a function polymorphic only over types; i.e. fixed arity. -pub type PolyFuncType = PolyFuncBase; - -impl From> for PolyFuncBase -where - [T]: ToOwned>, -{ - fn from(body: FuncTypeBase) -> Self { - Self { - params: vec![], - body, - } - } -} - -impl From for PolyFuncVarLen { - fn from(value: PolyFuncType) -> Self { - Self { - params: value.params, - body: value.body.into(), - } - } -} - -impl PolyFuncBase -where - [T]: ToOwned>, -{ - /// The type parameters, aka binders, over which this type is polymorphic - pub fn params(&self) -> &[TypeParam] { - &self.params - } - - /// The body of the type, a function type. - pub fn body(&self) -> &FuncTypeBase { - &self.body - } - - /// Create a new PolyFuncBase given the kinds of the variables it declares - /// and the underlying [FuncTypeVarLen]. - pub fn new(params: impl Into>, body: impl Into>) -> Self { - Self { - params: params.into(), - body: body.into(), - } - } - - /// Validates this instance, checking that the types in the body are - /// wellformed with respect to the registry, and that all type variables - /// are declared (perhaps in an enclosing scope, kinds passed in). - pub fn validate( - &self, - reg: &ExtensionRegistry, - external_var_decls: &[TypeParam], - ) -> Result<(), SignatureError> { - // TODO https://github.com/CQCL/hugr/issues/624 validate TypeParams declared here, too - let mut v; // Declared here so live until end of scope - let all_var_decls = if self.params.is_empty() { - external_var_decls - } else { - // Type vars declared here go at lowest indices (as per DeBruijn) - v = self.params.clone(); - v.extend_from_slice(external_var_decls); - v.as_slice() - }; - self.body.validate(reg, all_var_decls) - } - - pub(super) fn substitute(&self, t: &impl Substitution) -> Self { - if self.params.is_empty() { - // Avoid using complex code for simple Monomorphic case - return self.body.substitute(t).into(); - } - PolyFuncBase { - params: self.params.clone(), - body: self.body.substitute(&InsideBinders { - num_binders: self.params.len(), - underlying: t, - }), - } - } - - /// (Perhaps-partially) instantiates this [PolyFuncBase] into another with fewer binders. - /// Note that indices into `args` correspond to the same index within [Self::params], - /// so we instantiate the lowest-index [Self::params] first, even though these - /// would be considered "innermost" / "closest" according to DeBruijn numbering. - pub(crate) fn instantiate_poly( - &self, - args: &[TypeArg], - exts: &ExtensionRegistry, - ) -> Result { - let remaining = self.params.get(args.len()..).unwrap_or_default(); - let mut v; - let args = if remaining.is_empty() { - args // instantiate below will fail if there were too many - } else { - // Partial application - renumber remaining params (still bound) downward - v = args.to_vec(); - v.extend( - remaining - .iter() - .enumerate() - .map(|(i, decl)| TypeArg::new_var_use(i, decl.clone())), - ); - v.as_slice() - }; - Ok(Self { - params: remaining.to_vec(), - body: self.instantiate(args, exts)?, - }) - } - - /// Instantiates an outer [PolyFuncBase], i.e. with no free variables - /// (as ensured by [Self::validate]), into a monomorphic type. - /// - /// # Errors - /// If there is not exactly one [TypeArg] for each binder ([Self::params]), - /// or an arg does not fit into its corresponding [TypeParam] - pub(crate) fn instantiate( - &self, - args: &[TypeArg], - ext_reg: &ExtensionRegistry, - ) -> Result, SignatureError> { - // Check that args are applicable, and that we have a value for each binder, - // i.e. each possible free variable within the body. - check_type_args(args, &self.params)?; - Ok(self.body.substitute(&SubstValues(args, ext_reg))) - } -} - -/// A [Substitution] with a finite list of known values. -/// (Variables out of the range of the list will result in a panic) -struct SubstValues<'a>(&'a [TypeArg], &'a ExtensionRegistry); - -impl<'a> Substitution for SubstValues<'a> { - fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg { - let arg = self - .0 - .get(idx) - .expect("Undeclared type variable - call validate() ?"); - debug_assert_eq!(check_type_arg(arg, decl), Ok(())); - arg.clone() - } - - fn apply_rowvar(&self, idx: usize, _bound: TypeBound) -> Vec { - let arg = self - .0 - .get(idx) - .expect("Undeclared type variable - call validate() ?"); - match arg { - TypeArg::Sequence { elems } => elems - .iter() - .map(|ta| match ta { - TypeArg::Type { ty } => ty.clone(), - _ => panic!("Not a list of types - did validate() ?"), - }) - .map(RowVarOrType::T) - .collect(), - _ => panic!("Not a type or list of types - did validate() ?"), - } - } - - fn extension_registry(&self) -> &ExtensionRegistry { - self.1 - } -} - -/// A [Substitution] that renumbers any type variable to another (of the same kind) -/// with a index increased by a fixed `usize``. -struct Renumber<'a> { - offset: usize, - exts: &'a ExtensionRegistry, -} - -impl<'a> Substitution for Renumber<'a> { - fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg { - TypeArg::new_var_use(idx + self.offset, decl.clone()) - } - - fn extension_registry(&self) -> &ExtensionRegistry { - self.exts - } -} - -/// Given a [Substitution] defined outside a binder (i.e. [PolyFuncBase]), -/// applies that transformer to types inside the binder (i.e. arguments/results of said function) -struct InsideBinders<'a> { - /// The number of binders we have entered since (beneath where) we started to apply - /// [Self::underlying]). - /// That is, the lowest `num_binders` variable indices refer to locals bound since then. - num_binders: usize, - /// Substitution that was being applied outside those binders (i.e. in outer scope) - underlying: &'a dyn Substitution, -} - -impl<'a> Substitution for InsideBinders<'a> { - fn apply_var(&self, idx: usize, decl: &TypeParam) -> TypeArg { - // Convert variable index into outer scope - match idx.checked_sub(self.num_binders) { - None => TypeArg::new_var_use(idx, decl.clone()), // Bound locally, unknown to `underlying` - Some(idx_in_outer_scope) => { - let result_in_outer_scope = self.underlying.apply_var(idx_in_outer_scope, decl); - // Transform returned value into the current scope, i.e. avoid the variables newly bound - result_in_outer_scope.substitute(&Renumber { - offset: self.num_binders, - exts: self.extension_registry(), - }) - } - } - } - - fn extension_registry(&self) -> &ExtensionRegistry { - self.underlying.extension_registry() - } -} - -#[cfg(test)] -pub(crate) mod test { - use std::num::NonZeroU64; - - use lazy_static::lazy_static; - use smol_str::SmolStr; - - use crate::extension::prelude::{array_type, BOOL_T, PRELUDE_ID, USIZE_CUSTOM_T, USIZE_T}; - use crate::extension::{ - ExtensionId, ExtensionRegistry, SignatureError, TypeDefBound, PRELUDE, PRELUDE_REGISTRY, - }; - use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; - use crate::types::signature::FuncTypeBase; - use crate::types::type_param::{TypeArg, TypeArgError, TypeParam}; - use crate::types::type_row::RowVarOrType; - use crate::types::{CustomType, FuncTypeVarLen, PolyFuncVarLen, Type, TypeBound}; - use crate::Extension; - - use super::{PolyFuncBase, TypeRowElem}; - - lazy_static! { - static ref REGISTRY: ExtensionRegistry = - ExtensionRegistry::try_new([PRELUDE.to_owned(), EXTENSION.to_owned()]).unwrap(); - } - - impl PolyFuncBase - where - [T]: ToOwned>, - { - fn new_validated( - params: impl Into>, - body: FuncTypeBase, - extension_registry: &ExtensionRegistry, - ) -> Result { - let res = Self::new(params, body); - res.validate(extension_registry, &[])?; - Ok(res) - } - } - - #[test] - fn test_opaque() -> Result<(), SignatureError> { - let list_def = EXTENSION.get_type(&LIST_TYPENAME).unwrap(); - let tyvar = TypeArg::new_var_use(0, TypeBound::Any.into()); - let list_of_var = Type::new_extension(list_def.instantiate([tyvar.clone()])?); - let list_len = PolyFuncBase::new_validated( - [TypeBound::Any.into()], - FuncTypeVarLen::new(vec![list_of_var], vec![USIZE_T]), - ®ISTRY, - )?; - - let t = list_len.instantiate(&[TypeArg::Type { ty: USIZE_T }], ®ISTRY)?; - assert_eq!( - t, - FuncTypeVarLen::new( - vec![Type::new_extension( - list_def - .instantiate([TypeArg::Type { ty: USIZE_T }]) - .unwrap() - )], - vec![USIZE_T] - ) - ); - - Ok(()) - } - - fn id_fn(t: Type) -> FuncTypeVarLen { - FuncTypeVarLen::new(vec![t.clone()], vec![t]) - } - - #[test] - fn test_mismatched_args() -> Result<(), SignatureError> { - let ar_def = PRELUDE.get_type("array").unwrap(); - let typarams = [TypeParam::max_nat(), TypeBound::Any.into()]; - let [tyvar, szvar] = - [0, 1].map(|i| TypeArg::new_var_use(i, typarams.get(i).unwrap().clone())); - - // Valid schema... - let good_array = Type::new_extension(ar_def.instantiate([tyvar.clone(), szvar.clone()])?); - let good_ts = - PolyFuncBase::new_validated(typarams.clone(), id_fn(good_array), &PRELUDE_REGISTRY)?; - - // Sanity check (good args) - good_ts.instantiate( - &[TypeArg::BoundedNat { n: 5 }, TypeArg::Type { ty: USIZE_T }], - &PRELUDE_REGISTRY, - )?; - - let wrong_args = good_ts.instantiate( - &[TypeArg::Type { ty: USIZE_T }, TypeArg::BoundedNat { n: 5 }], - &PRELUDE_REGISTRY, - ); - assert_eq!( - wrong_args, - Err(SignatureError::TypeArgMismatch( - TypeArgError::TypeMismatch { - param: typarams[0].clone(), - arg: TypeArg::Type { ty: USIZE_T } - } - )) - ); - - // (Try to) make a schema with bad args - let arg_err = SignatureError::TypeArgMismatch(TypeArgError::TypeMismatch { - param: typarams[0].clone(), - arg: szvar.clone(), - }); - assert_eq!( - ar_def.instantiate([szvar.clone(), tyvar.clone()]), - Err(arg_err.clone()) - ); - // ok, so that doesn't work - well, it shouldn't! So let's say we just have this signature (with bad args)... - let bad_array = Type::new_extension(CustomType::new( - "array", - [szvar, tyvar], - PRELUDE_ID, - TypeBound::Any, - )); - let bad_ts = - PolyFuncBase::new_validated(typarams.clone(), id_fn(bad_array), &PRELUDE_REGISTRY); - assert_eq!(bad_ts.err(), Some(arg_err)); - - Ok(()) - } - - #[test] - fn test_misused_variables() -> Result<(), SignatureError> { - // Variables in args have different bounds from variable declaration - let tv = TypeArg::new_var_use(0, TypeBound::Copyable.into()); - let list_def = EXTENSION.get_type(&LIST_TYPENAME).unwrap(); - let body_type = id_fn(Type::new_extension(list_def.instantiate([tv])?)); - for decl in [ - TypeParam::Extensions, - TypeParam::List { - param: Box::new(TypeParam::max_nat()), - }, - TypeParam::Opaque { ty: USIZE_CUSTOM_T }, - TypeParam::Tuple { - params: vec![TypeBound::Any.into(), TypeParam::max_nat()], - }, - ] { - let invalid_ts = - PolyFuncBase::new_validated([decl.clone()], body_type.clone(), ®ISTRY); - assert_eq!( - invalid_ts.err(), - Some(SignatureError::TypeVarDoesNotMatchDeclaration { - cached: TypeBound::Copyable.into(), - actual: decl - }) - ); - } - // Variable not declared at all - let invalid_ts = PolyFuncBase::new_validated([], body_type, ®ISTRY); - assert_eq!( - invalid_ts.err(), - Some(SignatureError::FreeTypeVar { - idx: 0, - num_decls: 0 - }) - ); - - Ok(()) - } - - fn decl_accepts_rejects_var( - bound: TypeParam, - accepted: &[TypeParam], - rejected: &[TypeParam], - ) -> Result<(), SignatureError> { - const EXT_ID: ExtensionId = ExtensionId::new_unchecked("my_ext"); - const TYPE_NAME: SmolStr = SmolStr::new_inline("MyType"); - - let mut e = Extension::new(EXT_ID); - e.add_type( - TYPE_NAME, - vec![bound.clone()], - "".into(), - TypeDefBound::Explicit(TypeBound::Any), - ) - .unwrap(); - - let reg = ExtensionRegistry::try_new([e]).unwrap(); - - let make_scheme = |tp: TypeParam| { - PolyFuncBase::new_validated( - [tp.clone()], - id_fn(Type::new_extension(CustomType::new( - TYPE_NAME, - [TypeArg::new_var_use(0, tp)], - EXT_ID, - TypeBound::Any, - ))), - ®, - ) - }; - for decl in accepted { - make_scheme(decl.clone())?; - } - for decl in rejected { - assert_eq!( - make_scheme(decl.clone()).err(), - Some(SignatureError::TypeArgMismatch( - TypeArgError::TypeMismatch { - param: bound.clone(), - arg: TypeArg::new_var_use(0, decl.clone()) - } - )) - ); - } - Ok(()) - } - - #[test] - fn test_bound_covariance() -> Result<(), SignatureError> { - decl_accepts_rejects_var( - TypeBound::Copyable.into(), - &[TypeBound::Copyable.into(), TypeBound::Eq.into()], - &[TypeBound::Any.into()], - )?; - - let list_of_tys = |b: TypeBound| TypeParam::List { - param: Box::new(b.into()), - }; - decl_accepts_rejects_var( - list_of_tys(TypeBound::Copyable), - &[list_of_tys(TypeBound::Copyable), list_of_tys(TypeBound::Eq)], - &[list_of_tys(TypeBound::Any)], - )?; - - decl_accepts_rejects_var( - TypeParam::max_nat(), - &[TypeParam::bounded_nat(NonZeroU64::new(5).unwrap())], - &[], - )?; - decl_accepts_rejects_var( - TypeParam::bounded_nat(NonZeroU64::new(10).unwrap()), - &[TypeParam::bounded_nat(NonZeroU64::new(5).unwrap())], - &[TypeParam::max_nat()], - )?; - Ok(()) - } - - fn new_pf1(param: TypeParam, input: Type, output: Type) -> PolyFuncVarLen { - PolyFuncVarLen { - params: vec![param], - body: FuncTypeVarLen::new(vec![input], vec![output]), - } - } - - const USIZE_TA: TypeArg = TypeArg::Type { ty: USIZE_T }; - - #[test] - fn partial_instantiate() -> Result<(), SignatureError> { - // forall A,N.(Array -> A) - let array_max = PolyFuncBase::new_validated( - vec![TypeBound::Any.into(), TypeParam::max_nat()], - FuncTypeVarLen::new( - vec![array_type( - TypeArg::new_var_use(1, TypeParam::max_nat()), - Type::new_var_use(0, TypeBound::Any), - )], - vec![Type::new_var_use(0, TypeBound::Any)], - ), - &PRELUDE_REGISTRY, - )?; - - let concrete = FuncTypeVarLen::new( - vec![array_type(TypeArg::BoundedNat { n: 3 }, USIZE_T)], - vec![USIZE_T], - ); - let actual = array_max - .instantiate_poly(&[USIZE_TA, TypeArg::BoundedNat { n: 3 }], &PRELUDE_REGISTRY)?; - - assert_eq!(actual, concrete.into()); - - // forall N.(Array -> usize) - let partial = PolyFuncBase::new_validated( - vec![TypeParam::max_nat()], - FuncTypeVarLen::new( - vec![array_type( - TypeArg::new_var_use(0, TypeParam::max_nat()), - USIZE_T, - )], - vec![USIZE_T], - ), - &PRELUDE_REGISTRY, - )?; - let res = array_max.instantiate_poly(&[USIZE_TA], &PRELUDE_REGISTRY)?; - assert_eq!(res, partial); - - Ok(()) - } - - fn list_of_tup(t1: Type, t2: Type) -> Type { - let list_def = EXTENSION.get_type(LIST_TYPENAME.as_str()).unwrap(); - Type::new_extension( - list_def - .instantiate([TypeArg::Type { - ty: Type::new_tuple(vec![t1, t2]), - }]) - .unwrap(), - ) - } - - // forall A. A -> (forall C. C -> List(Tuple(C, A)) - pub(crate) fn nested_func() -> PolyFuncVarLen { - PolyFuncBase::new_validated( - vec![TypeBound::Any.into()], - FuncTypeVarLen::new( - vec![Type::new_var_use(0, TypeBound::Any)], - vec![Type::new_function(new_pf1( - TypeBound::Copyable.into(), - Type::new_var_use(0, TypeBound::Copyable), - list_of_tup( - Type::new_var_use(0, TypeBound::Copyable), - Type::new_var_use(1, TypeBound::Any), // The outer variable (renumbered) - ), - ))], - ), - ®ISTRY, - ) - .unwrap() - } - - #[test] - fn test_instantiate_nested() -> Result<(), SignatureError> { - let outer = nested_func(); - - let arg = array_type(TypeArg::BoundedNat { n: 5 }, USIZE_T); - // `arg` -> (forall C. C -> List(Tuple(C, `arg`))) - let outer_applied = FuncTypeVarLen::new( - vec![arg.clone()], // This had index 0, but is replaced - vec![Type::new_function(new_pf1( - TypeBound::Copyable.into(), - // We are checking that the substitution has been applied to the right var - // - NOT to the inner_var which has index 0 here - Type::new_var_use(0, TypeBound::Copyable), - list_of_tup( - Type::new_var_use(0, TypeBound::Copyable), - arg.clone(), // This had index 1, but is replaced - ), - ))], - ); - - let res = outer.instantiate(&[TypeArg::Type { ty: arg }], ®ISTRY)?; - assert_eq!(res, outer_applied); - Ok(()) - } - - #[test] - fn free_var_under_binder() { - let outer = nested_func(); - - // Now substitute in a free var from further outside - const FREE: usize = 3; - const TP_EQ: TypeParam = TypeParam::Type { b: TypeBound::Eq }; - let res = outer - .instantiate(&[TypeArg::new_var_use(FREE, TP_EQ)], ®ISTRY) - .unwrap(); - assert_eq!( - res, - // F -> forall C. (C -> List(Tuple(C, F))) - FuncTypeVarLen::new( - vec![Type::new_var_use(FREE, TypeBound::Eq)], - vec![Type::new_function(new_pf1( - TypeBound::Copyable.into(), - Type::new_var_use(0, TypeBound::Copyable), // unchanged - list_of_tup( - Type::new_var_use(0, TypeBound::Copyable), - // Next is the free variable that we substituted in (hence Eq) - // - renumbered because of the intervening forall (Copyable) - Type::new_var_use(FREE + 1, TypeBound::Eq) - ) - ))] - ) - ); - - // Also try substituting in a type containing both free and bound vars - let rhs = |i| { - Type::new_function(new_pf1( - TP_EQ, - Type::new_var_use(0, TypeBound::Eq), - array_type( - TypeArg::new_var_use(i, TypeParam::max_nat()), - Type::new_var_use(0, TypeBound::Eq), - ), - )) - }; - - let res = outer - .instantiate(&[TypeArg::Type { ty: rhs(FREE) }], ®ISTRY) - .unwrap(); - assert_eq!( - res, - FuncTypeVarLen::new( - vec![rhs(FREE)], // Input: forall TEQ. (TEQ -> Array(TEQ, FREE)) - // Output: forall C. C -> List(Tuple(C, Input)) - vec![Type::new_function(new_pf1( - TypeBound::Copyable.into(), - Type::new_var_use(0, TypeBound::Copyable), - list_of_tup( - Type::new_var_use(0, TypeBound::Copyable), // not renumbered... - rhs(FREE + 1) // renumbered - ) - ))] - ) - ) - } - - #[test] - fn row_variables() { - const TP: TypeParam = TypeParam::Type { b: TypeBound::Any }; - // Mismatched TypeBound (Copyable vs Any) - PolyFuncBase::new_validated( - [TypeParam::List { - param: Box::new(TypeParam::Type { - b: TypeBound::Copyable, - }), - }], - FuncTypeVarLen::new( - vec![USIZE_T, Type::new_var_use(0, TypeBound::Any)], - vec![Type::new_sum(vec![RowVarOrType::RV(0, TypeBound::Any)])], - ), - &PRELUDE_REGISTRY, - ) - .unwrap_err(); - - let pf = PolyFuncBase::new_validated( - [TypeParam::List { - param: Box::new(TP), - }], - FuncTypeVarLen::new( - vec![USIZE_T.into(), RowVarOrType::RV(0, TypeBound::Any)], - vec![Type::new_tuple(RowVarOrType::RV(0, TypeBound::Any))], - ), - &PRELUDE_REGISTRY, - ) - .unwrap(); - - fn seq2() -> Vec { - vec![USIZE_T.into(), BOOL_T.into()] - } - pf.instantiate(&[TypeArg::Type { ty: USIZE_T }], &PRELUDE_REGISTRY) - .unwrap_err(); - pf.instantiate( - &[TypeArg::Sequence { - elems: vec![USIZE_T.into(), TypeArg::Sequence { elems: seq2() }], - }], - &PRELUDE_REGISTRY, - ) - .unwrap_err(); - - let t2 = pf - .instantiate(&[TypeArg::Sequence { elems: seq2() }], &PRELUDE_REGISTRY) - .unwrap(); - assert_eq!( - t2, - FuncTypeVarLen::new( - vec![USIZE_T, USIZE_T, BOOL_T], - vec![Type::new_tuple(vec![ - RowVarOrType::T(USIZE_T), - BOOL_T.into() - ])] - ) - ); - } - - #[test] - fn row_variables_inner() { - let inner_fty = Type::new_function(FuncTypeVarLen::new_endo(vec![RowVarOrType::RV( - 0, - TypeBound::Copyable, - )])); - let pf = PolyFuncBase::new_validated( - [TypeParam::List { - param: Box::new(TypeParam::Type { - b: TypeBound::Copyable, - }), - }], - FuncTypeVarLen::new(vec![USIZE_T, inner_fty.clone()], vec![inner_fty]), - &PRELUDE_REGISTRY, - ) - .unwrap(); - - let inner3 = Type::new_function(FuncTypeVarLen::new_endo(vec![USIZE_T, BOOL_T, USIZE_T])); - let t3 = pf - .instantiate( - &[TypeArg::Sequence { - elems: vec![USIZE_T.into(), BOOL_T.into(), USIZE_T.into()], - }], - &PRELUDE_REGISTRY, - ) - .unwrap(); - assert_eq!( - t3, - FuncTypeVarLen::new(vec![USIZE_T, inner3.clone()], vec![inner3]) - ); - } -} From 87f276c15b6900fca2649ebbfe8a6597506e5b88 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 16:06:46 +0100 Subject: [PATCH 49/57] fix serialization --- hugr/src/types/serialize.rs | 9 +++++++++ hugr/src/types/type_row.rs | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hugr/src/types/serialize.rs b/hugr/src/types/serialize.rs index 50515f75a..b7fa608da 100644 --- a/hugr/src/types/serialize.rs +++ b/hugr/src/types/serialize.rs @@ -39,6 +39,15 @@ impl From for SerSimpleType { } } +impl From for SerSimpleType { + fn from(value: RowVarOrType) -> Self { + match value { + RowVarOrType::T(t) => t.into(), + RowVarOrType::RV(i, b) => SerSimpleType::V {i, b}, + } + } +} + impl From for RowVarOrType { fn from(value: SerSimpleType) -> RowVarOrType { let ty = match value { diff --git a/hugr/src/types/type_row.rs b/hugr/src/types/type_row.rs index 2ed6d8aae..af549e92d 100644 --- a/hugr/src/types/type_row.rs +++ b/hugr/src/types/type_row.rs @@ -7,7 +7,7 @@ use std::{ ops::{Deref, DerefMut}, }; -use super::{Type, TypeBound}; +use super::{serialize::SerSimpleType, Type, TypeBound}; use crate::utils::display_list; use crate::PortIndex; use delegate::delegate; @@ -16,6 +16,7 @@ use itertools::Itertools; #[derive( Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display, )] +#[serde(into="SerSimpleType", from="SerSimpleType")] pub enum RowVarOrType { #[display(fmt = "{}", _0)] T(Type), From 73617c401ca12dd8f416539297fac02417d04f9e Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 16:06:58 +0100 Subject: [PATCH 50/57] Fix (revert?) doctests --- hugr/src/lib.rs | 10 +++++----- hugr/src/macros.rs | 4 ++-- hugr/src/ops/dataflow.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hugr/src/lib.rs b/hugr/src/lib.rs index 831420485..560ae6a2d 100644 --- a/hugr/src/lib.rs +++ b/hugr/src/lib.rs @@ -31,7 +31,7 @@ //! use hugr::extension::prelude::{BOOL_T, QB_T}; //! use hugr::hugr::Hugr; //! use hugr::type_row; -//! use hugr::types::FuncTypeVarLen; +//! use hugr::types::FunctionType; //! //! // The type of qubits, `QB_T` is in the prelude but, by default, no gateset //! // is defined. This module provides Hadamard and CX gates. @@ -45,17 +45,17 @@ //! }, //! ops::LeafOp, //! type_row, -//! types::{FuncTypeVarLen, PolyFuncType}, +//! types::{FuncTypeVarLen, PolyFuncVarLen}, //! Extension, //! }; //! //! use lazy_static::lazy_static; //! -//! fn one_qb_func() -> PolyFuncType { +//! fn one_qb_func() -> PolyFuncVarLen { //! FuncTypeVarLen::new_endo(type_row![QB_T]).into() //! } //! -//! fn two_qb_func() -> PolyFuncType { +//! fn two_qb_func() -> PolyFuncVarLen { //! FuncTypeVarLen::new_endo(type_row![QB_T, QB_T]).into() //! } //! /// The extension identifier. @@ -117,7 +117,7 @@ //! // └───┘└───┘└╥┘ //! // c: ╚═ //! fn make_dfg_hugr() -> Result { -//! let mut dfg_builder = DFGBuilder::new(FuncTypeVarLen::new( +//! let mut dfg_builder = DFGBuilder::new(FunctionType::new( //! type_row![QB_T, QB_T], //! type_row![QB_T, QB_T, BOOL_T], //! ))?; diff --git a/hugr/src/macros.rs b/hugr/src/macros.rs index 00308d41b..fdeacfe2d 100644 --- a/hugr/src/macros.rs +++ b/hugr/src/macros.rs @@ -43,11 +43,11 @@ pub(crate) use impl_box_clone; /// Example: /// ``` /// # use hugr::macros::type_row; -/// # use hugr::types::{FuncTypeVarLen, Type, TypeRow}; +/// # use hugr::types::{FunctionType, Type, TypeRow}; /// const U: Type = Type::UNIT; /// let static_row: TypeRow = type_row![U, U]; /// let dynamic_row: TypeRow = vec![U, U, U].into(); -/// let sig = FuncTypeVarLen::new(static_row, dynamic_row); +/// let sig = FunctionType::new(static_row, dynamic_row); /// /// let repeated_row: TypeRow = type_row![U; 3]; /// assert_eq!(repeated_row, *sig.output()); diff --git a/hugr/src/ops/dataflow.rs b/hugr/src/ops/dataflow.rs index 27312d9bf..0fb96098d 100644 --- a/hugr/src/ops/dataflow.rs +++ b/hugr/src/ops/dataflow.rs @@ -206,7 +206,7 @@ impl Call { /// ``` /// # use hugr::ops::dataflow::Call; /// # use hugr::ops::OpType; - /// # use hugr::types::Signature; + /// # use hugr::types::FunctionType; /// # use hugr::extension::prelude::QB_T; /// # use hugr::extension::PRELUDE_REGISTRY; /// let signature = FunctionType::new(vec![QB_T, QB_T], vec![QB_T, QB_T]); From ac9b887a7bd50a9c5f279b97cebf1f82631f7e60 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 16:47:10 +0100 Subject: [PATCH 51/57] Drop unnecessary TypeRow -> Cow --- hugr/src/types/type_row.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/hugr/src/types/type_row.rs b/hugr/src/types/type_row.rs index af549e92d..bf3d3622d 100644 --- a/hugr/src/types/type_row.rs +++ b/hugr/src/types/type_row.rs @@ -157,16 +157,6 @@ where } } -impl From for Cow<'static, [RowVarOrType]> { - fn from(val: TypeRow) -> Self { - val.types - .into_owned() - .into_iter() - .map(RowVarOrType::from) - .collect() - } -} - impl From for TypeRowVarLen where RowVarOrType: From, From 4f8b2be3f1aa2771f74ece9767d1c636a23224ee Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 16:21:25 +0100 Subject: [PATCH 52/57] Fix some warnings. Visibility problem with subst_row --- hugr/src/extension.rs | 3 --- hugr/src/types/check.rs | 1 + hugr/src/types/signature.rs | 3 ++- hugr/src/types/type_row.rs | 14 ++++++++++++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/hugr/src/extension.rs b/hugr/src/extension.rs index a1973585d..05ba72d3b 100644 --- a/hugr/src/extension.rs +++ b/hugr/src/extension.rs @@ -167,9 +167,6 @@ pub enum SignatureError { /// A type variable that was used has not been declared #[error("Type variable {idx} was not declared ({num_decls} in scope)")] FreeTypeVar { idx: usize, num_decls: usize }, - /// A row variable was found outside of a row - #[error("Row variable {idx} was found outside of a type row")] - RowTypeVarOutsideRow { idx: usize }, /// The result of the type application stored in a [Call] /// is not what we get by applying the type-args to the polymorphic function /// diff --git a/hugr/src/types/check.rs b/hugr/src/types/check.rs index 4a45dfb0a..2a990a333 100644 --- a/hugr/src/types/check.rs +++ b/hugr/src/types/check.rs @@ -31,6 +31,7 @@ pub enum SumTypeError { /// The length of the sum variant found. found: usize, }, + /// The value claims to be of a variant which contains a row variable, i.e. is not a concrete type #[error("Sum variant #{tag} contained row variable with index {idx} standing for a row of {bound} types")] ContainsRowVariables { /// The tag of the sum (and value) diff --git a/hugr/src/types/signature.rs b/hugr/src/types/signature.rs index 5892963a6..f2e19308c 100644 --- a/hugr/src/types/signature.rs +++ b/hugr/src/types/signature.rs @@ -27,7 +27,8 @@ where pub extension_reqs: ExtensionSet, } -pub(super) trait TypeRowElem: 'static + Sized + Clone +/// A thing of which we can make rows (i.e. [TypeRowBase]'s) +pub trait TypeRowElem: 'static + Sized + Clone where [Self]: ToOwned>, { diff --git a/hugr/src/types/type_row.rs b/hugr/src/types/type_row.rs index bf3d3622d..7251a6c10 100644 --- a/hugr/src/types/type_row.rs +++ b/hugr/src/types/type_row.rs @@ -17,16 +17,21 @@ use itertools::Itertools; Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display, )] #[serde(into="SerSimpleType", from="SerSimpleType")] +/// Either exactly one type; or a variable that can stand for an arbitrary-length [TypeArg::List] of types pub enum RowVarOrType { #[display(fmt = "{}", _0)] + /// A single type, fixed arity T(Type), - /// DeBruijn index, and cache of inner TypeBound - matches a [TypeParam::List] of [TypeParam::Type] - /// of this bound (checked in validation) + /// A Row variable that can stand for any number of types. + /// Contains index, and cache of inner TypeBound - the variable must have been declared + /// as a [TypeParam::List] of [TypeParam::Type] of this bound (checked in validation) #[display(fmt = "RowVar({})", _0)] RV(usize, TypeBound), } impl RowVarOrType { + /// The smallest type bound that covers all type(s) that might + /// result after substituting a list in place of the row variable pub fn least_upper_bound(&self) -> TypeBound { match self { RowVarOrType::T(t) => t.least_upper_bound(), @@ -54,7 +59,12 @@ where types: Cow<'static, [T]>, } +/// A row of some fixed number of types, i.e. whose length cannot +/// change as a result of substitution of values for variables pub type TypeRow = TypeRowBase; + +/// A row of types whose length may vary if values are substituted +/// for variables. (That is, it may contain Row Variables.) pub type TypeRowVarLen = TypeRowBase; impl Display for TypeRowBase From a2e29199a2e14a1f9dbbc7195f3283c20d072511 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 16:39:48 +0100 Subject: [PATCH 53/57] Faff with visibility, add some private_bounds --- hugr/src/types/poly_func.rs | 16 ++++++++----- hugr/src/types/signature.rs | 45 +++++++++++++++++++++---------------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/hugr/src/types/poly_func.rs b/hugr/src/types/poly_func.rs index 4fc2d7009..0bd836644 100644 --- a/hugr/src/types/poly_func.rs +++ b/hugr/src/types/poly_func.rs @@ -23,7 +23,7 @@ use super::{RowVarOrType, Substitution, Type}; "body" )] pub struct PolyFuncBase -where T: TypeRowElem, [T]: ToOwned> { +where T: 'static + Sized + Clone, [T]: ToOwned> { /// The declared type parameters, i.e., these must be instantiated with /// the same number of [TypeArg]s before the function can be called. This /// defines the indices used by variables inside the body. @@ -39,7 +39,7 @@ pub type PolyFuncVarLen = PolyFuncBase; /// A type scheme that is polymorphic only over types, so fixed arity. pub type PolyFuncType = PolyFuncBase; -impl From> for PolyFuncBase +impl From> for PolyFuncBase where [T]: ToOwned>, { @@ -51,7 +51,8 @@ where } } -impl TryFrom> for FuncTypeBase { +impl TryFrom> for FuncTypeBase +where [T]: ToOwned> { /// If conversion fails, return the binders (which prevent conversion) type Error = Vec; @@ -70,7 +71,7 @@ impl From for PolyFuncVarLen { } } -impl PolyFuncBase +impl PolyFuncBase where [T]: ToOwned>, { @@ -92,11 +93,15 @@ where body: body.into(), } } +} + +#[allow(private_bounds)] // TypeRowElem is pub(super) and these are pub(crate) +impl PolyFuncBase { /// Validates this instance, checking that the types in the body are /// wellformed with respect to the registry, and that all type variables /// are declared (perhaps in an enclosing scope, kinds passed in). - pub fn validate( + pub(crate) fn validate( &self, reg: &ExtensionRegistry ) -> Result<(), SignatureError> { @@ -121,6 +126,7 @@ where Ok(self.body.substitute(&Substitution(args, ext_reg))) } } + #[cfg(test)] pub(crate) mod test { use std::num::NonZeroU64; diff --git a/hugr/src/types/signature.rs b/hugr/src/types/signature.rs index f2e19308c..892bb6dfa 100644 --- a/hugr/src/types/signature.rs +++ b/hugr/src/types/signature.rs @@ -16,7 +16,7 @@ use crate::{Direction, IncomingPort, OutgoingPort, Port}; /// and also the target (value) of a call (static). pub struct FuncTypeBase where - T: TypeRowElem, + T: 'static + Sized, [T]: ToOwned>, { /// Value inputs of the function. @@ -27,8 +27,7 @@ where pub extension_reqs: ExtensionSet, } -/// A thing of which we can make rows (i.e. [TypeRowBase]'s) -pub trait TypeRowElem: 'static + Sized + Clone +pub(super) trait TypeRowElem: Sized where [Self]: ToOwned>, { @@ -43,7 +42,7 @@ where impl Default for FuncTypeBase where - T: TypeRowElem, + T: Clone, [T]: ToOwned>, { fn default() -> Self { @@ -111,7 +110,7 @@ impl TypeRowElem for Type { impl FuncTypeBase where - T: TypeRowElem, + T: 'static + Sized + Clone, [T]: ToOwned>, { /// Builder method, add extension_reqs to an FuncTypeVarLen @@ -135,7 +134,27 @@ where Self::new(linear.clone(), linear) } - pub(crate) fn validate( + #[inline] + /// Returns the input row + pub fn input(&self) -> &TypeRowBase { + &self.input + } + + #[inline] + /// Returns the output row + pub fn output(&self) -> &TypeRowBase { + &self.output + } +} + +#[allow(private_bounds)] // These methods and TypeRowElem are pub(crate::types) +impl FuncTypeBase +where + T: TypeRowElem + 'static + Sized + Clone, + [T]: ToOwned>, + +{ + pub(super) fn validate( &self, extension_registry: &ExtensionRegistry, var_decls: &[TypeParam], @@ -147,7 +166,7 @@ where self.extension_reqs.validate(var_decls) } - pub(crate) fn substitute(&self, tr: &Substitution) -> Self { + pub(super) fn substitute(&self, tr: &Substitution) -> Self { Self { input: TypeRowElem::subst_row(&self.input, tr), output: TypeRowElem::subst_row(&self.output, tr), @@ -155,19 +174,7 @@ where } } - #[inline] - /// Returns the input row - pub fn input(&self) -> &TypeRowBase { - &self.input - } - - #[inline] - /// Returns the output row - pub fn output(&self) -> &TypeRowBase { - &self.output - } } - impl FunctionType { /// The number of wires in the signature. #[inline(always)] From 5eb88114cc8cb86cee920fe4c9ea1b80abbc2a17 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 16:47:45 +0100 Subject: [PATCH 54/57] Turn off some bad clippy warnings --- hugr/src/types/type_row.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hugr/src/types/type_row.rs b/hugr/src/types/type_row.rs index 7251a6c10..d752ce4b7 100644 --- a/hugr/src/types/type_row.rs +++ b/hugr/src/types/type_row.rs @@ -225,6 +225,7 @@ impl IntoIterator for TypeRow { type IntoIter = itertools::MapInto< as IntoIterator>::IntoIter, RowVarOrType>; fn into_iter(self) -> Self::IntoIter { + #[allow(clippy::unnecessary_to_owned)] // Suggestion always copies, rather than only if not already owned self.types.into_owned().into_iter().map_into() } } @@ -233,6 +234,7 @@ impl TryInto for TypeRowVarLen { type Error = (usize, TypeBound); fn try_into(self) -> Result { + #[allow(clippy::unnecessary_to_owned)] // Suggestion always copies, rather than only if not already owned self.types .into_owned() .into_iter() From c7c986fec5f091189a6f723955c6afa682151709 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 16:52:17 +0100 Subject: [PATCH 55/57] Fix doclinks --- hugr/src/extension/op_def.rs | 4 ++-- hugr/src/hugr/views.rs | 2 +- hugr/src/types/type_row.rs | 8 +++++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/hugr/src/extension/op_def.rs b/hugr/src/extension/op_def.rs index 6ede2e503..5bb66d36a 100644 --- a/hugr/src/extension/op_def.rs +++ b/hugr/src/extension/op_def.rs @@ -215,7 +215,7 @@ impl SignatureFunc { } } - /// Compute the concrete [Signature] for a node + /// Compute the concrete signature ([FunctionType]) for a node /// /// # Panics /// @@ -444,7 +444,7 @@ impl OpDef { impl Extension { /// Add an operation definition to the extension. Must be a type scheme - /// (defined by a [`PolyFuncType`]), a type scheme along with binary + /// (defined by a [`PolyFuncVarLen`]), a type scheme along with binary /// validation for type arguments ([`CustomValidator`]), or a custom binary /// function for computing the signature given type arguments (`impl [CustomSignatureFunc]`). pub fn add_op( diff --git a/hugr/src/hugr/views.rs b/hugr/src/hugr/views.rs index 1940128ef..4a07df510 100644 --- a/hugr/src/hugr/views.rs +++ b/hugr/src/hugr/views.rs @@ -335,7 +335,7 @@ pub trait HugrView: sealed::HugrInternals { /// graph. Otherwise, returns `None`. /// /// In contrast to [`get_function_type`][HugrView::get_function_type], this - /// method always return a concrete [`Signature`]. + /// method always return a concrete [`FunctionType`]. fn get_df_function_type(&self) -> Option { let op = self.get_optype(self.root()); op.inner_function_type() diff --git a/hugr/src/types/type_row.rs b/hugr/src/types/type_row.rs index d752ce4b7..6d092e84e 100644 --- a/hugr/src/types/type_row.rs +++ b/hugr/src/types/type_row.rs @@ -17,7 +17,10 @@ use itertools::Itertools; Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display, )] #[serde(into="SerSimpleType", from="SerSimpleType")] -/// Either exactly one type; or a variable that can stand for an arbitrary-length [TypeArg::List] of types +/// Either exactly one type; or a "row variable" that can stand for +/// an arbitrary-length [TypeArg::Sequence] of types. +/// +/// [TypeArg::Sequence]: crate::types::TypeArg::Sequence pub enum RowVarOrType { #[display(fmt = "{}", _0)] /// A single type, fixed arity @@ -25,6 +28,9 @@ pub enum RowVarOrType { /// A Row variable that can stand for any number of types. /// Contains index, and cache of inner TypeBound - the variable must have been declared /// as a [TypeParam::List] of [TypeParam::Type] of this bound (checked in validation) + /// + /// [TypeParam::List]: crate::types::TypeParam::List + /// [TypeParam::Type]: crate::types::TypeParam::Type #[display(fmt = "RowVar({})", _0)] RV(usize, TypeBound), } From eae3d5ee7d1bd74e661ab786ac0590608f2357aa Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 16:52:35 +0100 Subject: [PATCH 56/57] fmt --- hugr/src/extension.rs | 4 +--- hugr/src/ops/dataflow.rs | 7 +++---- hugr/src/types.rs | 23 ++++++++++++++++++----- hugr/src/types/poly_func.rs | 26 +++++++++++++++----------- hugr/src/types/serialize.rs | 2 +- hugr/src/types/signature.rs | 2 -- hugr/src/types/type_row.rs | 12 +++++++----- 7 files changed, 45 insertions(+), 31 deletions(-) diff --git a/hugr/src/extension.rs b/hugr/src/extension.rs index 05ba72d3b..e00db872e 100644 --- a/hugr/src/extension.rs +++ b/hugr/src/extension.rs @@ -18,9 +18,7 @@ use crate::ops::custom::{ExtensionOp, OpaqueOp}; use crate::types::type_param::{check_type_args, TypeArgError}; use crate::types::type_param::{TypeArg, TypeParam}; use crate::types::FunctionType; -use crate::types::{ - check_typevar_decl, CustomType, Substitution, TypeBound, TypeName, -}; +use crate::types::{check_typevar_decl, CustomType, Substitution, TypeBound, TypeName}; #[allow(dead_code)] mod infer; diff --git a/hugr/src/ops/dataflow.rs b/hugr/src/ops/dataflow.rs index 0fb96098d..d8a6ed4fc 100644 --- a/hugr/src/ops/dataflow.rs +++ b/hugr/src/ops/dataflow.rs @@ -259,10 +259,9 @@ impl DataflowOpTrait for CallIndirect { fn signature(&self) -> FunctionType { let mut s = self.signature.clone(); - s.input.to_mut().insert( - 0, - Type::new_function(self.signature.clone()), - ); + s.input + .to_mut() + .insert(0, Type::new_function(self.signature.clone())); s } } diff --git a/hugr/src/types.rs b/hugr/src/types.rs index 4a261c0d1..52c28f161 100644 --- a/hugr/src/types.rs +++ b/hugr/src/types.rs @@ -230,7 +230,10 @@ impl TypeEnum { Clone, PartialEq, Debug, Eq, derive_more::Display, serde::Serialize, serde::Deserialize, )] #[display(fmt = "{}", "_0")] -#[serde(into = "serialize::SerSimpleType", try_from = "serialize::SerSimpleType")] +#[serde( + into = "serialize::SerSimpleType", + try_from = "serialize::SerSimpleType" +)] /// A HUGR type - the valid types of [EdgeKind::Value] and [EdgeKind::Const] edges. /// Such an edge is valid if the ports on either end agree on the [Type]. /// Types have an optional [TypeBound] which places limits on the valid @@ -402,16 +405,26 @@ impl<'a> Substitution<'a> { match ta { TypeArg::Type { ty } => return vec![RowVarOrType::T(ty.clone())], TypeArg::Sequence { elems } => return elems.iter().flat_map(flatten).collect(), - TypeArg::Variable { v: TypeArgVariable { idx, cached_decl: TypeParam::List { param }} } => { + TypeArg::Variable { + v: + TypeArgVariable { + idx, + cached_decl: TypeParam::List { param }, + }, + } => { if let TypeParam::Type { b } = &**param { - return vec![RowVarOrType::RV(*idx, *b)] + return vec![RowVarOrType::RV(*idx, *b)]; } } - _ => () + _ => (), } panic!("TypeArg in a Row (List) was not a type or sequence") } - flatten(self.0.get(idx).expect("Undeclared type variable - call validate() ?")) + flatten( + self.0 + .get(idx) + .expect("Undeclared type variable - call validate() ?"), + ) } fn extension_registry(&self) -> &ExtensionRegistry { diff --git a/hugr/src/types/poly_func.rs b/hugr/src/types/poly_func.rs index 0bd836644..2f4e64b92 100644 --- a/hugr/src/types/poly_func.rs +++ b/hugr/src/types/poly_func.rs @@ -23,7 +23,10 @@ use super::{RowVarOrType, Substitution, Type}; "body" )] pub struct PolyFuncBase -where T: 'static + Sized + Clone, [T]: ToOwned> { +where + T: 'static + Sized + Clone, + [T]: ToOwned>, +{ /// The declared type parameters, i.e., these must be instantiated with /// the same number of [TypeArg]s before the function can be called. This /// defines the indices used by variables inside the body. @@ -52,13 +55,18 @@ where } impl TryFrom> for FuncTypeBase -where [T]: ToOwned> { +where + [T]: ToOwned>, +{ /// If conversion fails, return the binders (which prevent conversion) type Error = Vec; fn try_from(value: PolyFuncBase) -> Result { - if value.params.is_empty() {Ok(value.body)} - else {Err(value.params)} + if value.params.is_empty() { + Ok(value.body) + } else { + Err(value.params) + } } } @@ -95,16 +103,12 @@ where } } -#[allow(private_bounds)] // TypeRowElem is pub(super) and these are pub(crate) -impl PolyFuncBase { - +#[allow(private_bounds)] // TypeRowElem is pub(super) and these are pub(crate) +impl PolyFuncBase { /// Validates this instance, checking that the types in the body are /// wellformed with respect to the registry, and that all type variables /// are declared (perhaps in an enclosing scope, kinds passed in). - pub(crate) fn validate( - &self, - reg: &ExtensionRegistry - ) -> Result<(), SignatureError> { + pub(crate) fn validate(&self, reg: &ExtensionRegistry) -> Result<(), SignatureError> { // TODO https://github.com/CQCL/hugr/issues/624 validate TypeParams declared here, too self.body.validate(reg, &self.params) } diff --git a/hugr/src/types/serialize.rs b/hugr/src/types/serialize.rs index b7fa608da..e12e71e05 100644 --- a/hugr/src/types/serialize.rs +++ b/hugr/src/types/serialize.rs @@ -43,7 +43,7 @@ impl From for SerSimpleType { fn from(value: RowVarOrType) -> Self { match value { RowVarOrType::T(t) => t.into(), - RowVarOrType::RV(i, b) => SerSimpleType::V {i, b}, + RowVarOrType::RV(i, b) => SerSimpleType::V { i, b }, } } } diff --git a/hugr/src/types/signature.rs b/hugr/src/types/signature.rs index 892bb6dfa..41e29b0d9 100644 --- a/hugr/src/types/signature.rs +++ b/hugr/src/types/signature.rs @@ -152,7 +152,6 @@ impl FuncTypeBase where T: TypeRowElem + 'static + Sized + Clone, [T]: ToOwned>, - { pub(super) fn validate( &self, @@ -173,7 +172,6 @@ where extension_reqs: self.extension_reqs.substitute(tr), } } - } impl FunctionType { /// The number of wires in the signature. diff --git a/hugr/src/types/type_row.rs b/hugr/src/types/type_row.rs index 6d092e84e..13db963b9 100644 --- a/hugr/src/types/type_row.rs +++ b/hugr/src/types/type_row.rs @@ -16,10 +16,10 @@ use itertools::Itertools; #[derive( Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize, derive_more::Display, )] -#[serde(into="SerSimpleType", from="SerSimpleType")] +#[serde(into = "SerSimpleType", from = "SerSimpleType")] /// Either exactly one type; or a "row variable" that can stand for /// an arbitrary-length [TypeArg::Sequence] of types. -/// +/// /// [TypeArg::Sequence]: crate::types::TypeArg::Sequence pub enum RowVarOrType { #[display(fmt = "{}", _0)] @@ -28,7 +28,7 @@ pub enum RowVarOrType { /// A Row variable that can stand for any number of types. /// Contains index, and cache of inner TypeBound - the variable must have been declared /// as a [TypeParam::List] of [TypeParam::Type] of this bound (checked in validation) - /// + /// /// [TypeParam::List]: crate::types::TypeParam::List /// [TypeParam::Type]: crate::types::TypeParam::Type #[display(fmt = "RowVar({})", _0)] @@ -231,7 +231,8 @@ impl IntoIterator for TypeRow { type IntoIter = itertools::MapInto< as IntoIterator>::IntoIter, RowVarOrType>; fn into_iter(self) -> Self::IntoIter { - #[allow(clippy::unnecessary_to_owned)] // Suggestion always copies, rather than only if not already owned + #[allow(clippy::unnecessary_to_owned)] + // Suggestion always copies, rather than only if not already owned self.types.into_owned().into_iter().map_into() } } @@ -240,7 +241,8 @@ impl TryInto for TypeRowVarLen { type Error = (usize, TypeBound); fn try_into(self) -> Result { - #[allow(clippy::unnecessary_to_owned)] // Suggestion always copies, rather than only if not already owned + #[allow(clippy::unnecessary_to_owned)] + // Suggestion always copies, rather than only if not already owned self.types .into_owned() .into_iter() From 34bd13b0589f9b0265da656241fa2fd422e45441 Mon Sep 17 00:00:00 2001 From: Alan Lawrence Date: Wed, 10 Apr 2024 17:04:08 +0100 Subject: [PATCH 57/57] Fix --all-features by reverting FuncTypeVarLen back to FunctionType --- hugr/src/extension/op_def.rs | 4 ++-- hugr/src/hugr.rs | 4 ++-- hugr/src/hugr/rewrite/replace.rs | 2 +- hugr/src/hugr/validate/test.rs | 23 +++++++++++------------ 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/hugr/src/extension/op_def.rs b/hugr/src/extension/op_def.rs index 5bb66d36a..99c9c46b0 100644 --- a/hugr/src/extension/op_def.rs +++ b/hugr/src/extension/op_def.rs @@ -486,8 +486,8 @@ mod test { use crate::ops::custom::ExternalOp; use crate::ops::LeafOp; use crate::std_extensions::collections::{EXTENSION, LIST_TYPENAME}; - use crate::types::{type_param::TypeParam, FuncTypeVarLen, FunctionType, TypeArg, TypeBound}; - use crate::types::{PolyFuncVarLen, Type}; + use crate::types::type_param::TypeParam; + use crate::types::{FuncTypeVarLen, FunctionType, PolyFuncVarLen, Type, TypeArg, TypeBound}; use crate::Hugr; use crate::{const_extension_ids, Extension}; diff --git a/hugr/src/hugr.rs b/hugr/src/hugr.rs index 15eb45700..9a60cf90d 100644 --- a/hugr/src/hugr.rs +++ b/hugr/src/hugr.rs @@ -376,13 +376,13 @@ mod test { use crate::hugr::HugrMut; use crate::ops::LeafOp; use crate::type_row; - use crate::types::{FuncTypeVarLen, Type}; + use crate::types::{FunctionType, Type}; const BIT: Type = crate::extension::prelude::USIZE_T; let r = ExtensionSet::singleton(&"R".try_into().unwrap()); let mut hugr = closed_dfg_root_hugr( - FuncTypeVarLen::new(type_row![BIT], type_row![BIT]).with_extension_delta(r.clone()), + FunctionType::new(type_row![BIT], type_row![BIT]).with_extension_delta(r.clone()), ); let [input, output] = hugr.get_io(hugr.root()).unwrap(); let lift = hugr.add_node_with_parent( diff --git a/hugr/src/hugr/rewrite/replace.rs b/hugr/src/hugr/rewrite/replace.rs index 8924029b8..972a81440 100644 --- a/hugr/src/hugr/rewrite/replace.rs +++ b/hugr/src/hugr/rewrite/replace.rs @@ -628,7 +628,7 @@ mod test { OpType::CFG(c) => &c.signature.input, _ => panic!(), }, - &op_sig.input + op_sig.input() ); h.simple_entry_builder(op_sig.output, 1, op_sig.extension_reqs.clone())? } else { diff --git a/hugr/src/hugr/validate/test.rs b/hugr/src/hugr/validate/test.rs index 445fb96d0..0878f12dd 100644 --- a/hugr/src/hugr/validate/test.rs +++ b/hugr/src/hugr/validate/test.rs @@ -663,7 +663,7 @@ mod extension_tests { b.replace_op( copy, NodeType::new_pure(ops::CFG { - signature: FuncTypeVarLen::new(type_row![BOOL_T], type_row![BOOL_T]), + signature: FunctionType::new(type_row![BOOL_T], type_row![BOOL_T]), }), ) .unwrap(); @@ -745,7 +745,7 @@ mod extension_tests { // The DFG node declares that it has an empty extension delta, // but it's child graph adds extension "XB", causing a mismatch. let mut hugr = Hugr::new(NodeType::new_pure(ops::DFG { - signature: FuncTypeVarLen::new(type_row![USIZE_T], type_row![USIZE_T]), + signature: FunctionType::new(type_row![USIZE_T], type_row![USIZE_T]), })); let input = hugr.add_node_with_parent( @@ -792,12 +792,12 @@ mod extension_tests { let mut module_builder = ModuleBuilder::new(); let mut main = module_builder.define_function( "main", - FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).into(), + FunctionType::new(type_row![NAT], type_row![NAT]).into(), )?; let [main_input] = main.input_wires_arr(); let f_builder = main.dfg_builder( - FuncTypeVarLen::new(type_row![NAT], type_row![NAT]), + FunctionType::new(type_row![NAT], type_row![NAT]), // Inner DFG has extension requirements that the wire wont satisfy Some(ExtensionSet::from_iter([XA, XB])), [main_input], @@ -825,13 +825,12 @@ mod extension_tests { fn too_many_extension() -> Result<(), BuildError> { let mut module_builder = ModuleBuilder::new(); - let main_sig = FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).into(); + let main_sig = FunctionType::new(type_row![NAT], type_row![NAT]).into(); let mut main = module_builder.define_function("main", main_sig)?; let [main_input] = main.input_wires_arr(); - let inner_sig = - FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).with_extension_delta(XA); + let inner_sig = FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(XA); let f_builder = main.dfg_builder(inner_sig, Some(ExtensionSet::new()), [main_input])?; let f_inputs = f_builder.input_wires(); @@ -858,7 +857,7 @@ mod extension_tests { let all_rs = ExtensionSet::from_iter([XA, XB]); - let main_sig = FuncTypeVarLen::new(type_row![], type_row![NAT]) + let main_sig = FunctionType::new(type_row![], type_row![NAT]) .with_extension_delta(all_rs.clone()) .into(); @@ -866,7 +865,7 @@ mod extension_tests { let [left_wire] = main .dfg_builder( - FuncTypeVarLen::new(type_row![], type_row![NAT]), + FunctionType::new(type_row![], type_row![NAT]), Some(XA.into()), [], )? @@ -875,7 +874,7 @@ mod extension_tests { let [right_wire] = main .dfg_builder( - FuncTypeVarLen::new(type_row![], type_row![NAT]), + FunctionType::new(type_row![], type_row![NAT]), Some(XB.into()), [], )? @@ -883,7 +882,7 @@ mod extension_tests { .outputs_arr(); let builder = main.dfg_builder( - FuncTypeVarLen::new(type_row![NAT, NAT], type_row![NAT]), + FunctionType::new(type_row![NAT, NAT], type_row![NAT]), Some(all_rs), [left_wire, right_wire], )?; @@ -904,7 +903,7 @@ mod extension_tests { #[test] fn parent_signature_mismatch() { let main_signature = - FuncTypeVarLen::new(type_row![NAT], type_row![NAT]).with_extension_delta(XA); + FunctionType::new(type_row![NAT], type_row![NAT]).with_extension_delta(XA); let mut hugr = Hugr::new(NodeType::new_pure(ops::DFG { signature: main_signature,