Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: polymorphic function types (inc OpDefs) using dyn trait #630

Merged
merged 166 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from 162 commits
Commits
Show all changes
166 commits
Select commit Hold shift + click to select a range
943e407
Add PrimType::Variable, and validation (passing type_vars: &[TypeParam])
acl-cqc Sep 1, 2023
2341df9
Allow TypeArg::Variable of arbitrary TypeParam
acl-cqc Sep 1, 2023
94db46a
Add substitute(&[TypeArg]). Note unable to recompute bound of CustomT…
acl-cqc Sep 1, 2023
e5ec9d6
(Preliminary) refactor: break out check_type_args (plural) and Functi…
acl-cqc Sep 1, 2023
62e5312
Add extension::type_scheme::OpDefTypeScheme
acl-cqc Sep 1, 2023
80d8d8d
Implement extension type-vars
acl-cqc Sep 1, 2023
51c8e2c
Add TypeArgVariable and new_type_variable to enforce proper represent…
acl-cqc Sep 1, 2023
03a2533
Add hugr::Ident with regex validity check
acl-cqc Sep 4, 2023
a10910b
Extension does not derive Default
acl-cqc Sep 4, 2023
2da1468
ExtensionId = Ident; use paste for 'test_const_ext_id!'
acl-cqc Sep 4, 2023
f54c100
don't macro_export test_const_ext_id as it won't be usable
acl-cqc Sep 4, 2023
288c52e
Change to IdentList and PATH_REGEX
acl-cqc Sep 4, 2023
41fcaa3
Merge remote-tracking branch 'origin/main' into new/ident_extensionid
acl-cqc Sep 4, 2023
b508ca1
Merge branch 'new/ident_extensionid' into new/type_schemes
acl-cqc Sep 4, 2023
4683cde
ExtensionSet: back to ~~main, represent TypeVars as malformed Extensi…
acl-cqc Sep 4, 2023
4d5abd5
Comment CustomTypeArg
acl-cqc Sep 4, 2023
7ff61ae
Use 'as &str' to avoid need for PartialEq
acl-cqc Sep 5, 2023
f6cad32
test_const_ext_id takes body of const variable decls
acl-cqc Sep 5, 2023
2307266
Move to macros.rs with pub(crate) use
acl-cqc Sep 5, 2023
82c9b3d
Make pub, export, add doctest
acl-cqc Sep 5, 2023
3f0ad07
Use &* in ops/custom.rs
acl-cqc Sep 5, 2023
7476fc3
Merge remote-tracking branch 'origin/main' into new/ident_extensionid
acl-cqc Sep 5, 2023
9132e43
substitute takes &ExtensionRegistry; store in OpDefTypeScheme w/ 'a p…
acl-cqc Sep 5, 2023
2a7d49b
panic => expect (*2)
acl-cqc Sep 5, 2023
dd00c63
Experiment: make substitute consume the receiver
acl-cqc Sep 5, 2023
5552c9a
Revert "Experiment: make substitute consume the receiver"
acl-cqc Sep 5, 2023
d866567
Add some tests(1)
acl-cqc Sep 5, 2023
ec90738
Tests(2) - covariance
acl-cqc Sep 5, 2023
087ec80
new_type_variable -> use_var; the var must already have been declared!
acl-cqc Sep 5, 2023
45292a8
macro visibility specifiers (+doctest)
acl-cqc Sep 6, 2023
64a6d7d
Macro: add meta-attributes (+doctest)
acl-cqc Sep 6, 2023
95b5c9b
Merge remote-tracking branch 'origin/main' into new/ident_extensionid
acl-cqc Sep 8, 2023
fe227c0
regex literal => expr; include doc-comment in test
acl-cqc Sep 8, 2023
cf89634
Rename test_const_ext_id => const_extension_ids
acl-cqc Sep 8, 2023
3148fa6
Merge remote-tracking branch 'origin/main' into new/ident_extensionid
acl-cqc Sep 8, 2023
6d4f29a
Merge branch 'new/ident_extensionid' into new/type_schemes
acl-cqc Sep 8, 2023
73805f0
TypeArg::Variable into tagged struct
acl-cqc Sep 8, 2023
405d362
driveby: rename TypeArg::Sequence.(args => elems)
acl-cqc Sep 8, 2023
0b422a9
refactor/tidy: use filter_map
acl-cqc Sep 8, 2023
a4a403e
Remove unnecessary (common+implied) into_iter
acl-cqc Sep 8, 2023
4d578a0
Update test to use array defined in PRELUDE
acl-cqc Sep 8, 2023
ab82f5e
doclinks
acl-cqc Sep 8, 2023
bac9af9
Drop debug printouts
acl-cqc Sep 8, 2023
4ea9df1
doc TypeArg::Variable
acl-cqc Sep 8, 2023
14e3db8
Merge remote-tracking branch 'origin/main' into new/type_schemes
acl-cqc Sep 18, 2023
6842095
Merge remote-tracking branch 'origin/main' into HEAD
acl-cqc Sep 19, 2023
4bb237b
Drop &ExtensionRegistry and <'a> param on OpDefTypeScheme
acl-cqc Sep 18, 2023
708a643
SignatureFunc::FromDecl => ::TypeScheme(OpDefTypeScheme), don't impl …
acl-cqc Sep 18, 2023
f456d64
FIX recomputation of bound
acl-cqc Sep 19, 2023
6a50ea5
Add PolyFuncType (derive Display for TypeParam, UpperBound)
acl-cqc Sep 18, 2023
586f92b
Preliminary - pass decls thru substitute. Not used anywhere yet
acl-cqc Sep 19, 2023
d1fe65c
Put PolyFuncType into Type hierarchy
acl-cqc Sep 18, 2023
6d87b52
Try combining args/decls into a list of pairs. Less linewrap, more ma…
acl-cqc Sep 19, 2023
dcb66e6
Revert "Try combining args/decls into a list of pairs. Less linewrap,…
acl-cqc Sep 19, 2023
8c881dc
Add LeafOp::TypeApply (w/ struct TypeApplication to create w/ Extensi…
acl-cqc Sep 18, 2023
19948e7
Validate LeafOp::TypeApply's. Beginnings of a new interface/trait here??
acl-cqc Sep 18, 2023
fc9f20c
Test type application
acl-cqc Sep 18, 2023
ad3c923
Substitution class. Puts all the hard stuff in one place.
acl-cqc Sep 19, 2023
b1a352a
Move PolyFuncType into poly_func.rs
acl-cqc Sep 19, 2023
03481e8
Remove OpDefTypeScheme, use PolyFuncType; move tests {type_scheme=>po…
acl-cqc Sep 19, 2023
4703d62
Strengthen test_type_apply_nested, fix PolyFuncType::validate
acl-cqc Sep 19, 2023
e51b984
CustomSignatureFunc returns PolyFuncType with all_params declared in …
acl-cqc Sep 19, 2023
e022341
Fix tests (need some real registries now)
acl-cqc Sep 19, 2023
53faec5
Comment in 'enum SignatureFunc'
acl-cqc Sep 20, 2023
870665f
Test (with broken bits to match current)
acl-cqc Sep 21, 2023
ea3b1ec
Remove renumber_down from Substitution, we can just map
acl-cqc Sep 21, 2023
a343312
Substitution can renumber up (but clones RHSes) via Either; fixing tests
acl-cqc Sep 21, 2023
f6a26e8
Check args are closed first
acl-cqc Sep 21, 2023
55cd3fd
Add check_typevar_declared, split Error into two
acl-cqc Sep 21, 2023
79d2ae0
comment validate
acl-cqc Sep 21, 2023
5fd6110
More tests (remove one redundant by the covariance tests)
acl-cqc Sep 21, 2023
ee2862d
Common-up tyvar/szvar computation
acl-cqc Sep 21, 2023
1aa6e1d
Comment as_typevar
acl-cqc Sep 21, 2023
e506aea
Hide OpDefTypeScheme::params
acl-cqc Sep 21, 2023
a1fd0a9
Rename (TypeDef::){instantiate_concrete=>instantiate}
acl-cqc Sep 21, 2023
457255f
Merge remote-tracking branch 'origin/main' into new/type_schemes
acl-cqc Sep 24, 2023
ff3dde4
Merge branch 'new/type_schemes' into HEAD; move TypeApply code into P…
acl-cqc Sep 24, 2023
eb3540f
Make subst_row a method 'apply_row' of Substitution
acl-cqc Sep 24, 2023
dd730e6
Move Substitution into subst.rs
acl-cqc Sep 24, 2023
46b2ff5
Change itertools::Either for explicit (private) Mapping struct, some …
acl-cqc Sep 24, 2023
f4ce471
Substitution: use Cow not Vec
acl-cqc Sep 24, 2023
cc4c9a4
Substitution::new -> impl From, and use to avoid to_vec
acl-cqc Sep 24, 2023
dc6ec43
instantiate_all should unwrap
acl-cqc Sep 24, 2023
6ca68b0
Improve comments
acl-cqc Sep 25, 2023
9e5d2c3
Drop unused to_leaf
acl-cqc Sep 25, 2023
02b4e3a
Simplfy poly_func::validate cloning
acl-cqc Sep 25, 2023
b051f5e
In PolyFuncType, Box<FunctionType> -> FunctionType
acl-cqc Sep 25, 2023
cb4edca
And reinstate Box inside PrimType::Function
acl-cqc Sep 25, 2023
1923416
Substitution::{get -> apply_var}
acl-cqc Sep 25, 2023
a6bf7f8
easier check.rs (make body pub(super))
acl-cqc Sep 25, 2023
48d7eba
{new_variable,use_var}=>new_var_use
acl-cqc Sep 25, 2023
ec198ec
Merge branch 'new/type_schemes' into new/poly_types
acl-cqc Sep 25, 2023
619c2f5
collections.rs: use add_op_custom_sig_simple
acl-cqc Sep 27, 2023
aa916d1
quantum.rs: reorder imports + lazy_static!
acl-cqc Sep 27, 2023
600d548
PolyFunc: switch dependence direction of instantiate{,_all}, fixing p…
acl-cqc Sep 27, 2023
375ef33
Rename {CachedType=>TypeApplyCache}Incorrect, drop comment about #508
acl-cqc Sep 28, 2023
c3ee452
Merge remote-tracking branch 'origin/main' into new/type_schemes
acl-cqc Oct 13, 2023
d964606
Rename: type_vars (an &[TypeParam]) -> var_decls
acl-cqc Oct 13, 2023
bafb55e
Clarify naming wrt. cache of bound in typevar
acl-cqc Oct 13, 2023
9d3072d
Comment on TypeArg::Variable
acl-cqc Oct 13, 2023
573041d
UpperBound::contains
acl-cqc Oct 13, 2023
543dba1
Merge branch 'new/type_schemes' into new/poly_types, reduce changes t…
acl-cqc Oct 13, 2023
1a3af5d
Comments re. cache-vs-check_type_arg, new_var_use
acl-cqc Oct 17, 2023
0d63596
Rename apply_var/get_type to apply_to_(var,type_var)
acl-cqc Oct 18, 2023
f866b7b
Merge branch 'new/type_schemes' into new/poly_types
acl-cqc Oct 18, 2023
abc3913
OpDef TODO: reconsider add_op_custom_sig_simple
acl-cqc Oct 18, 2023
ef28482
Note about variable lifetime
acl-cqc Oct 18, 2023
c37f35f
Rename (external,all)_(type_vars=>var_decls)
acl-cqc Oct 18, 2023
b2a9311
PolyFunc::instantiate comment re. too many args
acl-cqc Oct 18, 2023
ed8c974
(More) SignatureFunc intra-field doclinks
acl-cqc Oct 18, 2023
cdd56cd
add_op_custom_sig: break apart tuple, #[allow(too_many_arguments)], a…
acl-cqc Oct 18, 2023
19a2e4d
OpDef's predeclare only type params to binary func, not whatever it r…
acl-cqc Oct 21, 2023
aec53d1
Drop TODOs, these seem ok now we are not predeclaring params to compu…
acl-cqc Oct 21, 2023
45bdd20
Check we don't pass free typevars to binary function
acl-cqc Oct 21, 2023
361ecf2
(??? another PR?) Move ExtensionRegistry into Substitution
acl-cqc Oct 21, 2023
662996b
poly_func tests: add comments describing function types
acl-cqc Oct 23, 2023
6519f21
Comment why Substitution has an Extension Registry
acl-cqc Oct 25, 2023
a9bc987
Remove TODO about validating a TypeParam, raised #624
acl-cqc Oct 25, 2023
dc3b73a
Remove obsolete comment (Ext Reg in Subst)
acl-cqc Oct 25, 2023
1c4ce4b
Impl Eq<FunctionType> for PolyFuncType, simplify PrimType::check_type
acl-cqc Oct 25, 2023
22ccea4
test_type_apply_nested: inline 'inner'
acl-cqc Oct 25, 2023
4ddf77a
poly_func.rs: reorder tests, some outlining + renaming
acl-cqc Oct 25, 2023
22ce702
test_instantiate_nested: use same nested_func as free_var_under_binder
acl-cqc Oct 25, 2023
e5bfe48
Remove no-longer-needed clippy::too_many_arguments
acl-cqc Oct 25, 2023
1d45118
WIP allow CustomSignatureFunc to return OpDefTypeScheme (builds, test…
acl-cqc Oct 25, 2023
3abb748
Fix tests via ExtensionRegistrys etc
acl-cqc Oct 25, 2023
75166fc
keep-alive can use OpDefTypeScheme, not option
acl-cqc Oct 26, 2023
4fbc8e4
Merge branch 'new/binary_type_schemes' into new/poly_types
acl-cqc Oct 26, 2023
bfccb00
Change substitute to transform, w/trait TypeTransformer
acl-cqc Oct 26, 2023
4ae07e6
apply_custom => CustomType::transform, FunctionType::transform
acl-cqc Oct 26, 2023
be2928f
WIP Merge branch 'new/type_schemes_map' into new/poly_types_map
acl-cqc Oct 26, 2023
f85c754
EnterScope uses dyn, 'coz EnterScope<T> creates EnterScope<EnterScope…
acl-cqc Oct 26, 2023
2f112a4
Remove Sized constraint; clippy
acl-cqc Oct 29, 2023
bf480a2
No need to pass decl/bound to apply_to_(type_)var
acl-cqc Oct 29, 2023
171dd89
Revert "No need to pass decl/bound to apply_to_(type_)var"
acl-cqc Oct 29, 2023
28aedfe
Merge new/type_schemes_map (+extra bound/decl param) into new/poly_ty…
acl-cqc Oct 30, 2023
fcbfd6d
Rename EnterScope to InsideBinders, comment
acl-cqc Oct 29, 2023
9d8dee3
Avoid using InsideBinders etc. for monomorphic hugrs
acl-cqc Oct 30, 2023
2842742
Optimize dyn using associated types
acl-cqc Oct 27, 2023
692e0fd
Revert "Optimize dyn using associated types"
acl-cqc Oct 30, 2023
65c564b
Ooops, remove unused type_scheme.rs
acl-cqc Oct 30, 2023
66e004e
Merge branch 'new/poly_types' into new/poly_types_map
acl-cqc Oct 30, 2023
357318d
Reduce change in custom.rs
acl-cqc Oct 30, 2023
f951c20
Rename transform (back) to substitute
acl-cqc Nov 6, 2023
e4bd21a
Rename TypeTransformer to Substitution
acl-cqc Nov 6, 2023
bc9fa2b
Rename Instantiation to SubstValues
acl-cqc Nov 6, 2023
79cb1e7
Convert InsideBinders/Renumber tuple structs into named fields
acl-cqc Nov 6, 2023
9121b31
docs
acl-cqc Nov 6, 2023
41e8037
Clarify InsideBinders::apply_var using usize::checked_sub
acl-cqc Nov 6, 2023
546d0d0
Merge remote-tracking branch 'origin/main' into new/poly_types_map
acl-cqc Nov 6, 2023
c074c63
Note about variable binding order
acl-cqc Nov 6, 2023
98faff9
Another note - instantiate works the reverse way around
acl-cqc Nov 6, 2023
e0c732f
CI fmt
acl-cqc Nov 6, 2023
5a89a19
Hide PolyFuncType::params, add accessor
acl-cqc Nov 6, 2023
3145e8c
skip_lowest => num_binders, comment
acl-cqc Nov 7, 2023
3584036
instantiate => instantiate_poly (but one test is of instantiate_all)
acl-cqc Nov 7, 2023
c7c8d09
instantiate_all => instantiate
acl-cqc Nov 7, 2023
ebfec42
Merge remote-tracking branch 'origin/main' into new/poly_types_map, t…
acl-cqc Nov 7, 2023
b989014
Test creating and instantiating an OpDef with a PolyFuncType scheme
acl-cqc Nov 7, 2023
e0d3c9d
poly_func::test: hide new_array, (re-)export nested_func (through typ…
acl-cqc Nov 7, 2023
c3211d5
TypeApply tests
acl-cqc Nov 7, 2023
a9e03bc
Oops, remove rotation.rs
acl-cqc Nov 7, 2023
11f813e
in comment, validate()d -> validated
acl-cqc Nov 8, 2023
71336cc
assert -> debug_assert
acl-cqc Nov 8, 2023
f57198e
Merge remote-tracking branch 'origin/main' into new/poly_types_map
acl-cqc Nov 8, 2023
6a64953
Fix replace.rs rename instantiate_concrete -> instantiate
acl-cqc Nov 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 63 additions & 11 deletions src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use thiserror::Error;
use crate::hugr::IdentList;
use crate::ops;
use crate::ops::custom::{ExtensionOp, OpaqueOp};
use crate::types::type_param::{check_type_arg, TypeArgError};
use crate::types::type_param::{check_type_args, TypeArgError};
use crate::types::type_param::{TypeArg, TypeParam};
use crate::types::{CustomType, TypeBound};
use crate::types::{check_typevar_decl, CustomType, PolyFuncType, Substitution, TypeBound};

mod infer;
pub use infer::{infer_extensions, ExtensionSolution, InferExtensionError};
Expand Down Expand Up @@ -91,6 +91,24 @@ pub enum SignatureError {
actual: TypeBound,
expected: TypeBound,
},
/// A Type Variable's cache of its declared kind is incorrect
#[error("Type Variable claims to be {cached:?} but actual declaration {actual:?}")]
TypeVarDoesNotMatchDeclaration {
actual: TypeParam,
cached: TypeParam,
},
/// 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 },
/// The type stored in a [LeafOp::TypeApply] is not what we compute from the
/// [ExtensionRegistry].
///
/// [LeafOp::TypeApply]: crate::ops::LeafOp::TypeApply
#[error("Incorrect result of type application - cached {cached} but expected {expected}")]
TypeApplyIncorrectCache {
cached: PolyFuncType,
expected: PolyFuncType,
},
}

/// Concrete instantiations of types and operations defined in extensions.
Expand Down Expand Up @@ -140,15 +158,7 @@ trait TypeParametrised {
fn extension(&self) -> &ExtensionId;
/// Check provided type arguments are valid against parameters.
fn check_args_impl(&self, args: &[TypeArg]) -> Result<(), SignatureError> {
if args.len() != self.params().len() {
return Err(SignatureError::TypeArgMismatch(
TypeArgError::WrongNumberArgs(args.len(), self.params().len()),
));
}
for (a, p) in args.iter().zip(self.params().iter()) {
check_type_arg(a, p).map_err(SignatureError::TypeArgMismatch)?;
}
Ok(())
check_type_args(args, self.params()).map_err(SignatureError::TypeArgMismatch)
}
}

Expand Down Expand Up @@ -315,6 +325,14 @@ impl ExtensionSet {
self.0.insert(extension.clone());
}

/// Adds a type var (which must have been declared as a [TypeParam::Extensions]) to this set
pub fn insert_type_var(&mut self, idx: usize) {
// Represent type vars as string representation of DeBruijn index.
// This is not a legal IdentList or ExtensionId so should not conflict.
self.0
.insert(ExtensionId::new_unchecked(idx.to_string().as_str()));
}

/// Returns `true` if the set contains the given extension.
pub fn contains(&self, extension: &ExtensionId) -> bool {
self.0.contains(extension)
Expand All @@ -337,6 +355,14 @@ impl ExtensionSet {
set
}

/// An ExtensionSet containing a single type variable
/// (which must have been declared as a [TypeParam::Extensions])
pub fn type_var(idx: usize) -> Self {
let mut set = Self::new();
set.insert_type_var(idx);
set
}

/// Returns the union of two extension sets.
pub fn union(mut self, other: &Self) -> Self {
self.0.extend(other.0.iter().cloned());
Expand All @@ -357,6 +383,32 @@ impl ExtensionSet {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}

pub(crate) fn validate(&self, params: &[TypeParam]) -> Result<(), SignatureError> {
self.iter()
.filter_map(as_typevar)
.try_for_each(|var_idx| check_typevar_decl(params, var_idx, &TypeParam::Extensions))
}

pub(crate) fn substitute(&self, t: &impl Substitution) -> Self {
Self::from_iter(self.0.iter().flat_map(|e| match as_typevar(e) {
None => vec![e.clone()],
Some(i) => match t.apply_var(i, &TypeParam::Extensions) {
TypeArg::Extensions{es} => es.iter().cloned().collect::<Vec<_>>(),
_ => panic!("value for type var was not extension set - type scheme should be validate()d first"),
acl-cqc marked this conversation as resolved.
Show resolved Hide resolved
},
}))
}
}

fn as_typevar(e: &ExtensionId) -> Option<usize> {
// Type variables are represented as radix-10 numbers, which are illegal
// as standard ExtensionIds. Hence if an ExtensionId starts with a digit,
// we assume it must be a type variable, and fail fast if it isn't.
match e.chars().next() {
Some(c) if c.is_ascii_digit() => Some(str::parse(e).unwrap()),
_ => None,
}
}

impl Display for ExtensionSet {
Expand Down
Loading