1use std::cmp::min;
2use std::collections::HashMap;
3use std::collections::btree_map::Entry;
4use std::fmt::{Debug, Formatter};
5use std::sync::{Arc, Weak};
6
7use serde_with::serde_as;
8
9use super::{
10 ConstFold, ConstFoldResult, Extension, ExtensionBuildError, ExtensionId, ExtensionSet,
11 SignatureError,
12};
13
14use crate::Hugr;
15use crate::envelope::serde_with::AsStringEnvelope;
16use crate::ops::{OpName, OpNameRef};
17use crate::types::type_param::{TypeArg, TypeParam, check_term_types};
18use crate::types::{FuncValueType, PolyFuncType, PolyFuncTypeRV, Signature};
19mod serialize_signature_func;
20
21pub trait CustomSignatureFunc: Send + Sync {
23 fn compute_signature<'o, 'a: 'o>(
27 &'a self,
28 arg_values: &[TypeArg],
29 def: &'o OpDef,
30 ) -> Result<PolyFuncTypeRV, SignatureError>;
31 fn static_params(&self) -> &[TypeParam];
34}
35
36pub trait SignatureFromArgs: Send + Sync {
38 fn compute_signature(&self, arg_values: &[TypeArg]) -> Result<PolyFuncTypeRV, SignatureError>;
41 fn static_params(&self) -> &[TypeParam];
44}
45
46impl<T: SignatureFromArgs> CustomSignatureFunc for T {
47 #[inline]
48 fn compute_signature<'o, 'a: 'o>(
49 &'a self,
50 arg_values: &[TypeArg],
51 _def: &'o OpDef,
52 ) -> Result<PolyFuncTypeRV, SignatureError> {
53 SignatureFromArgs::compute_signature(self, arg_values)
54 }
55
56 #[inline]
57 fn static_params(&self) -> &[TypeParam] {
58 SignatureFromArgs::static_params(self)
59 }
60}
61
62pub trait ValidateTypeArgs: Send + Sync {
65 fn validate<'o, 'a: 'o>(
69 &self,
70 arg_values: &[TypeArg],
71 def: &'o OpDef,
72 ) -> Result<(), SignatureError>;
73}
74
75pub trait ValidateJustArgs: Send + Sync {
78 fn validate(&self, arg_values: &[TypeArg]) -> Result<(), SignatureError>;
81}
82
83impl<T: ValidateJustArgs> ValidateTypeArgs for T {
84 #[inline]
85 fn validate<'o, 'a: 'o>(
86 &self,
87 arg_values: &[TypeArg],
88 _def: &'o OpDef,
89 ) -> Result<(), SignatureError> {
90 ValidateJustArgs::validate(self, arg_values)
91 }
92}
93
94pub trait CustomLowerFunc: Send + Sync {
105 fn try_lower(
109 &self,
110 name: &OpNameRef,
111 arg_values: &[TypeArg],
112 misc: &HashMap<String, serde_json::Value>,
113 available_extensions: &ExtensionSet,
114 ) -> Option<Hugr>;
115}
116
117pub struct CustomValidator {
121 poly_func: PolyFuncTypeRV,
122 pub(crate) validate: Box<dyn ValidateTypeArgs>,
124}
125
126impl CustomValidator {
127 pub fn new(
130 poly_func: impl Into<PolyFuncTypeRV>,
131 validate: impl ValidateTypeArgs + 'static,
132 ) -> Self {
133 Self {
134 poly_func: poly_func.into(),
135 validate: Box::new(validate),
136 }
137 }
138
139 pub(super) fn poly_func_mut(&mut self) -> &mut PolyFuncTypeRV {
141 &mut self.poly_func
142 }
143}
144
145pub enum SignatureFunc {
147 PolyFuncType(PolyFuncTypeRV),
149 CustomValidator(CustomValidator),
151 MissingValidateFunc(PolyFuncTypeRV),
153 CustomFunc(Box<dyn CustomSignatureFunc>),
156 MissingComputeFunc,
158}
159
160impl<T: CustomSignatureFunc + 'static> From<T> for SignatureFunc {
161 fn from(v: T) -> Self {
162 Self::CustomFunc(Box::new(v))
163 }
164}
165
166impl From<PolyFuncType> for SignatureFunc {
167 fn from(value: PolyFuncType) -> Self {
168 Self::PolyFuncType(value.into())
169 }
170}
171
172impl From<PolyFuncTypeRV> for SignatureFunc {
173 fn from(v: PolyFuncTypeRV) -> Self {
174 Self::PolyFuncType(v)
175 }
176}
177
178impl From<FuncValueType> for SignatureFunc {
179 fn from(v: FuncValueType) -> Self {
180 Self::PolyFuncType(v.into())
181 }
182}
183
184impl From<Signature> for SignatureFunc {
185 fn from(v: Signature) -> Self {
186 Self::PolyFuncType(FuncValueType::from(v).into())
187 }
188}
189
190impl From<CustomValidator> for SignatureFunc {
191 fn from(v: CustomValidator) -> Self {
192 Self::CustomValidator(v)
193 }
194}
195
196impl SignatureFunc {
197 fn static_params(&self) -> Result<&[TypeParam], SignatureError> {
198 Ok(match self {
199 SignatureFunc::PolyFuncType(ts)
200 | SignatureFunc::CustomValidator(CustomValidator { poly_func: ts, .. })
201 | SignatureFunc::MissingValidateFunc(ts) => ts.params(),
202 SignatureFunc::CustomFunc(func) => func.static_params(),
203 SignatureFunc::MissingComputeFunc => return Err(SignatureError::MissingComputeFunc),
204 })
205 }
206
207 pub fn ignore_missing_validation(&mut self) {
210 if let SignatureFunc::MissingValidateFunc(ts) = self {
211 *self = SignatureFunc::PolyFuncType(ts.clone());
212 }
213 }
214
215 pub fn compute_signature(
227 &self,
228 def: &OpDef,
229 args: &[TypeArg],
230 ) -> Result<Signature, SignatureError> {
231 let temp: PolyFuncTypeRV; let (pf, args) = match &self {
233 SignatureFunc::CustomValidator(custom) => {
234 custom.validate.validate(args, def)?;
235 (&custom.poly_func, args)
236 }
237 SignatureFunc::PolyFuncType(ts) => (ts, args),
238 SignatureFunc::CustomFunc(func) => {
239 let static_params = func.static_params();
240 let (static_args, other_args) = args.split_at(min(static_params.len(), args.len()));
241
242 check_term_types(static_args, static_params)?;
243 temp = func.compute_signature(static_args, def)?;
244 (&temp, other_args)
245 }
246 SignatureFunc::MissingComputeFunc => return Err(SignatureError::MissingComputeFunc),
247 SignatureFunc::MissingValidateFunc(ts) => (ts, args),
249 };
250 let res = pf.instantiate(args)?;
251
252 res.try_into()
254 }
255}
256
257impl Debug for SignatureFunc {
258 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
259 match self {
260 Self::CustomValidator(ts) => ts.poly_func.fmt(f),
261 Self::PolyFuncType(ts) => ts.fmt(f),
262 Self::CustomFunc { .. } => f.write_str("<custom sig>"),
263 Self::MissingComputeFunc => f.write_str("<missing custom sig>"),
264 Self::MissingValidateFunc(_) => f.write_str("<missing custom validation>"),
265 }
266 }
267}
268
269#[serde_as]
272#[derive(serde::Deserialize, serde::Serialize)]
273#[serde(untagged)]
274pub enum LowerFunc {
275 FixedHugr {
278 extensions: ExtensionSet,
280 #[serde_as(as = "Box<AsStringEnvelope>")]
285 hugr: Box<Hugr>,
286 },
287 #[serde(skip)]
290 CustomFunc(Box<dyn CustomLowerFunc>),
291}
292
293impl Debug for LowerFunc {
294 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
295 match self {
296 Self::FixedHugr { .. } => write!(f, "FixedHugr"),
297 Self::CustomFunc(_) => write!(f, "<custom lower>"),
298 }
299 }
300}
301
302#[derive(Debug, serde::Serialize, serde::Deserialize)]
306pub struct OpDef {
307 extension: ExtensionId,
309 #[serde(skip)]
311 extension_ref: Weak<Extension>,
312 name: OpName,
315 description: String,
317 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
319 misc: HashMap<String, serde_json::Value>,
320
321 #[serde(with = "serialize_signature_func", flatten)]
322 signature_func: SignatureFunc,
323 #[serde(default, skip_serializing_if = "Vec::is_empty")]
326 pub(crate) lower_funcs: Vec<LowerFunc>,
327
328 #[serde(skip)]
330 constant_folder: Option<Box<dyn ConstFold>>,
331}
332
333impl OpDef {
334 pub fn validate_args(
338 &self,
339 args: &[TypeArg],
340 var_decls: &[TypeParam],
341 ) -> Result<(), SignatureError> {
342 let temp: PolyFuncTypeRV; let (pf, args) = match &self.signature_func {
344 SignatureFunc::CustomValidator(ts) => (&ts.poly_func, args),
345 SignatureFunc::PolyFuncType(ts) => (ts, args),
346 SignatureFunc::CustomFunc(custom) => {
347 let (static_args, other_args) =
348 args.split_at(min(custom.static_params().len(), args.len()));
349 static_args.iter().try_for_each(|ta| ta.validate(&[]))?;
350 check_term_types(static_args, custom.static_params())?;
351 temp = custom.compute_signature(static_args, self)?;
352 (&temp, other_args)
353 }
354 SignatureFunc::MissingComputeFunc => return Err(SignatureError::MissingComputeFunc),
355 SignatureFunc::MissingValidateFunc(_) => {
356 return Err(SignatureError::MissingValidateFunc);
357 }
358 };
359 args.iter().try_for_each(|ta| ta.validate(var_decls))?;
360 check_term_types(args, pf.params())?;
361 Ok(())
362 }
363
364 pub fn compute_signature(&self, args: &[TypeArg]) -> Result<Signature, SignatureError> {
367 self.signature_func.compute_signature(self, args)
368 }
369
370 #[must_use]
373 pub fn try_lower(&self, args: &[TypeArg], available_extensions: &ExtensionSet) -> Option<Hugr> {
374 self.lower_funcs
376 .iter()
377 .filter_map(|f| match f {
378 LowerFunc::FixedHugr { extensions, hugr } => {
379 if available_extensions.is_superset(extensions) {
380 Some(hugr.as_ref().clone())
381 } else {
382 None
383 }
384 }
385 LowerFunc::CustomFunc(f) => {
386 f.try_lower(&self.name, args, &self.misc, available_extensions)
387 }
388 })
389 .next()
390 }
391
392 #[must_use]
394 pub fn name(&self) -> &OpName {
395 &self.name
396 }
397
398 #[must_use]
400 pub fn extension_id(&self) -> &ExtensionId {
401 &self.extension
402 }
403
404 #[must_use]
406 pub fn extension(&self) -> Weak<Extension> {
407 self.extension_ref.clone()
408 }
409
410 pub(super) fn extension_mut(&mut self) -> &mut Weak<Extension> {
412 &mut self.extension_ref
413 }
414
415 #[must_use]
417 pub fn description(&self) -> &str {
418 self.description.as_ref()
419 }
420
421 pub fn params(&self) -> Result<&[TypeParam], SignatureError> {
423 self.signature_func.static_params()
424 }
425
426 pub(super) fn validate(&self) -> Result<(), SignatureError> {
427 if let SignatureFunc::CustomValidator(ts) = &self.signature_func {
430 ts.poly_func.validate()?;
434 }
435 Ok(())
436 }
437
438 pub fn add_lower_func(&mut self, lower: LowerFunc) {
440 self.lower_funcs.push(lower);
441 }
442
443 pub fn add_misc(
445 &mut self,
446 k: impl ToString,
447 v: serde_json::Value,
448 ) -> Option<serde_json::Value> {
449 self.misc.insert(k.to_string(), v)
450 }
451
452 #[allow(unused)] pub(crate) fn iter_misc(&self) -> impl ExactSizeIterator<Item = (&str, &serde_json::Value)> {
455 self.misc.iter().map(|(k, v)| (k.as_str(), v))
456 }
457
458 pub fn set_constant_folder(&mut self, fold: impl ConstFold + 'static) {
461 self.constant_folder = Some(Box::new(fold));
462 }
463
464 #[must_use]
467 pub fn constant_fold(
468 &self,
469 type_args: &[TypeArg],
470 consts: &[(crate::IncomingPort, crate::ops::Value)],
471 ) -> ConstFoldResult {
472 (self.constant_folder.as_ref())?.fold(type_args, consts)
473 }
474
475 #[must_use]
477 pub fn signature_func(&self) -> &SignatureFunc {
478 &self.signature_func
479 }
480
481 pub(super) fn signature_func_mut(&mut self) -> &mut SignatureFunc {
483 &mut self.signature_func
484 }
485}
486
487impl Extension {
488 pub fn add_op(
517 &mut self,
518 name: OpName,
519 description: String,
520 signature_func: impl Into<SignatureFunc>,
521 extension_ref: &Weak<Extension>,
522 ) -> Result<&mut OpDef, ExtensionBuildError> {
523 let op = OpDef {
524 extension: self.name.clone(),
525 extension_ref: extension_ref.clone(),
526 name,
527 description,
528 signature_func: signature_func.into(),
529 misc: Default::default(),
530 lower_funcs: Default::default(),
531 constant_folder: Default::default(),
532 };
533
534 match self.operations.entry(op.name.clone()) {
535 Entry::Occupied(_) => Err(ExtensionBuildError::OpDefExists(op.name)),
536 Entry::Vacant(ve) => Ok(Arc::get_mut(ve.insert(Arc::new(op))).unwrap()),
538 }
539 }
540}
541
542#[cfg(test)]
543pub(super) mod test {
544 use std::num::NonZeroU64;
545
546 use itertools::Itertools;
547
548 use super::SignatureFromArgs;
549 use crate::builder::{DFGBuilder, Dataflow, DataflowHugr, endo_sig};
550 use crate::extension::SignatureError;
551 use crate::extension::op_def::{CustomValidator, LowerFunc, OpDef, SignatureFunc};
552 use crate::extension::prelude::usize_t;
553 use crate::extension::{ExtensionRegistry, ExtensionSet, PRELUDE};
554 use crate::ops::OpName;
555 use crate::std_extensions::collections::list;
556 use crate::types::type_param::{TermTypeError, TypeParam};
557 use crate::types::{PolyFuncTypeRV, Signature, Type, TypeArg, TypeBound, TypeRV};
558 use crate::{Extension, const_extension_ids};
559
560 const_extension_ids! {
561 const EXT_ID: ExtensionId = "MyExt";
562 }
563
564 #[derive(serde::Serialize, serde::Deserialize, Debug)]
566 pub struct SimpleOpDef(OpDef);
567
568 impl SimpleOpDef {
569 #[must_use]
571 pub fn new(op_def: OpDef) -> Self {
572 assert!(op_def.constant_folder.is_none());
573 assert!(matches!(
574 op_def.signature_func,
575 SignatureFunc::PolyFuncType(_)
576 ));
577 assert!(
578 op_def
579 .lower_funcs
580 .iter()
581 .all(|lf| matches!(lf, LowerFunc::FixedHugr { .. }))
582 );
583 Self(op_def)
584 }
585 }
586
587 impl From<SimpleOpDef> for OpDef {
588 fn from(value: SimpleOpDef) -> Self {
589 value.0
590 }
591 }
592
593 impl PartialEq for SimpleOpDef {
594 fn eq(&self, other: &Self) -> bool {
595 let OpDef {
596 extension,
597 extension_ref: _,
598 name,
599 description,
600 misc,
601 signature_func,
602 lower_funcs,
603 constant_folder: _,
604 } = &self.0;
605 let OpDef {
606 extension: other_extension,
607 extension_ref: _,
608 name: other_name,
609 description: other_description,
610 misc: other_misc,
611 signature_func: other_signature_func,
612 lower_funcs: other_lower_funcs,
613 constant_folder: _,
614 } = &other.0;
615
616 let get_sig = |sf: &_| match sf {
617 SignatureFunc::CustomValidator(CustomValidator {
622 poly_func,
623 validate: _,
624 })
625 | SignatureFunc::PolyFuncType(poly_func)
626 | SignatureFunc::MissingValidateFunc(poly_func) => Some(poly_func.clone()),
627 SignatureFunc::CustomFunc(_) | SignatureFunc::MissingComputeFunc => None,
628 };
629
630 let get_lower_funcs = |lfs: &Vec<LowerFunc>| {
631 lfs.iter()
632 .map(|lf| match lf {
633 LowerFunc::FixedHugr { extensions, hugr } => {
636 Some((extensions.clone(), hugr.clone()))
637 }
638 LowerFunc::CustomFunc(_) => None,
640 })
641 .collect_vec()
642 };
643
644 extension == other_extension
645 && name == other_name
646 && description == other_description
647 && misc == other_misc
648 && get_sig(signature_func) == get_sig(other_signature_func)
649 && get_lower_funcs(lower_funcs) == get_lower_funcs(other_lower_funcs)
650 }
651 }
652
653 #[test]
654 fn op_def_with_type_scheme() -> Result<(), Box<dyn std::error::Error>> {
655 let list_def = list::EXTENSION.get_type(&list::LIST_TYPENAME).unwrap();
656 const OP_NAME: OpName = OpName::new_inline("Reverse");
657
658 let ext = Extension::try_new_test_arc(EXT_ID, |ext, extension_ref| {
659 const TP: TypeParam = TypeParam::RuntimeType(TypeBound::Linear);
660 let list_of_var =
661 Type::new_extension(list_def.instantiate(vec![TypeArg::new_var_use(0, TP)])?);
662 let type_scheme = PolyFuncTypeRV::new(vec![TP], Signature::new_endo(vec![list_of_var]));
663
664 let def = ext.add_op(OP_NAME, "desc".into(), type_scheme, extension_ref)?;
665 def.add_lower_func(LowerFunc::FixedHugr {
666 extensions: ExtensionSet::new(),
667 hugr: Box::new(crate::builder::test::simple_dfg_hugr()), });
669 def.add_misc("key", Default::default());
670 assert_eq!(def.description(), "desc");
671 assert_eq!(def.lower_funcs.len(), 1);
672 assert_eq!(def.misc.len(), 1);
673
674 Ok(())
675 })?;
676
677 let reg = ExtensionRegistry::new([PRELUDE.clone(), list::EXTENSION.clone(), ext]);
678 reg.validate()?;
679 let e = reg.get(&EXT_ID).unwrap();
680
681 let list_usize = Type::new_extension(list_def.instantiate(vec![usize_t().into()])?);
682 let mut dfg = DFGBuilder::new(endo_sig(vec![list_usize]))?;
683 let rev = dfg.add_dataflow_op(
684 e.instantiate_extension_op(&OP_NAME, vec![usize_t().into()])
685 .unwrap(),
686 dfg.input_wires(),
687 )?;
688 dfg.finish_hugr_with_outputs(rev.outputs())?;
689
690 Ok(())
691 }
692
693 #[test]
694 fn binary_polyfunc() -> Result<(), Box<dyn std::error::Error>> {
695 struct SigFun();
700 impl SignatureFromArgs for SigFun {
701 fn compute_signature(
702 &self,
703 arg_values: &[TypeArg],
704 ) -> Result<PolyFuncTypeRV, SignatureError> {
705 const TP: TypeParam = TypeParam::RuntimeType(TypeBound::Linear);
706 let [TypeArg::BoundedNat(n)] = arg_values else {
707 return Err(SignatureError::InvalidTypeArgs);
708 };
709 let n = *n as usize;
710 let tvs: Vec<Type> = (0..n)
711 .map(|_| Type::new_var_use(0, TypeBound::Linear))
712 .collect();
713 Ok(PolyFuncTypeRV::new(
714 vec![TP.clone()],
715 Signature::new(tvs.clone(), vec![Type::new_tuple(tvs)]),
716 ))
717 }
718
719 fn static_params(&self) -> &[TypeParam] {
720 const MAX_NAT: &[TypeParam] = &[TypeParam::max_nat_type()];
721 MAX_NAT
722 }
723 }
724 let _ext = Extension::try_new_test_arc(EXT_ID, |ext, extension_ref| {
725 let def: &mut crate::extension::OpDef =
726 ext.add_op("MyOp".into(), String::new(), SigFun(), extension_ref)?;
727
728 let args = [TypeArg::BoundedNat(3), usize_t().into()];
730 assert_eq!(
731 def.compute_signature(&args),
732 Ok(Signature::new(
733 vec![usize_t(); 3],
734 vec![Type::new_tuple(vec![usize_t(); 3])]
735 ))
736 );
737 assert_eq!(def.validate_args(&args, &[]), Ok(()));
738
739 let tyvar = Type::new_var_use(0, TypeBound::Copyable);
741 let tyvars: Vec<Type> = vec![tyvar.clone(); 3];
742 let args = [TypeArg::BoundedNat(3), tyvar.clone().into()];
743 assert_eq!(
744 def.compute_signature(&args),
745 Ok(Signature::new(
746 tyvars.clone(),
747 vec![Type::new_tuple(tyvars)]
748 ))
749 );
750 def.validate_args(&args, &[TypeBound::Copyable.into()])
751 .unwrap();
752
753 assert_eq!(
755 def.validate_args(&args, &[TypeBound::Linear.into()]),
756 Err(SignatureError::TypeVarDoesNotMatchDeclaration {
757 actual: Box::new(TypeBound::Linear.into()),
758 cached: Box::new(TypeBound::Copyable.into())
759 })
760 );
761
762 let kind = TypeParam::bounded_nat_type(NonZeroU64::new(5).unwrap());
764 let args = [TypeArg::new_var_use(0, kind.clone()), usize_t().into()];
765 assert_eq!(
767 def.compute_signature(&args),
768 Err(SignatureError::InvalidTypeArgs)
769 );
770 assert_eq!(
772 def.validate_args(&args, &[kind]),
773 Err(SignatureError::FreeTypeVar {
774 idx: 0,
775 num_decls: 0
776 })
777 );
778
779 Ok(())
780 })?;
781
782 Ok(())
783 }
784
785 #[test]
786 fn type_scheme_instantiate_var() -> Result<(), Box<dyn std::error::Error>> {
787 let _ext = Extension::try_new_test_arc(EXT_ID, |ext, extension_ref| {
790 let def = ext.add_op(
791 "SimpleOp".into(),
792 String::new(),
793 PolyFuncTypeRV::new(
794 vec![TypeBound::Linear.into()],
795 Signature::new_endo(vec![Type::new_var_use(0, TypeBound::Linear)]),
796 ),
797 extension_ref,
798 )?;
799 let tv = Type::new_var_use(0, TypeBound::Copyable);
800 let args = [tv.clone().into()];
801 let decls = [TypeBound::Copyable.into()];
802 def.validate_args(&args, &decls).unwrap();
803 assert_eq!(def.compute_signature(&args), Ok(Signature::new_endo(tv)));
804 let arg: TypeArg = TypeRV::new_row_var_use(0, TypeBound::Copyable).into();
806 assert_eq!(
807 def.compute_signature(&[arg.clone()]),
808 Err(SignatureError::TypeArgMismatch(
809 TermTypeError::TypeMismatch {
810 type_: Box::new(TypeBound::Linear.into()),
811 term: Box::new(arg),
812 }
813 ))
814 );
815 Ok(())
816 })?;
817 Ok(())
818 }
819
820 mod proptest {
821 use std::sync::Weak;
822
823 use super::SimpleOpDef;
824 use ::proptest::prelude::*;
825
826 use crate::{
827 builder::test::simple_dfg_hugr,
828 extension::{ExtensionId, ExtensionSet, OpDef, SignatureFunc, op_def::LowerFunc},
829 types::PolyFuncTypeRV,
830 };
831
832 impl Arbitrary for SignatureFunc {
833 type Parameters = ();
834 type Strategy = BoxedStrategy<Self>;
835 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
836 any::<PolyFuncTypeRV>()
840 .prop_map(SignatureFunc::PolyFuncType)
841 .boxed()
842 }
843 }
844
845 impl Arbitrary for LowerFunc {
846 type Parameters = ();
847 type Strategy = BoxedStrategy<Self>;
848 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
849 any::<ExtensionSet>()
852 .prop_map(|extensions| LowerFunc::FixedHugr {
853 extensions,
854 hugr: Box::new(simple_dfg_hugr()),
855 })
856 .boxed()
857 }
858 }
859
860 impl Arbitrary for SimpleOpDef {
861 type Parameters = ();
862 type Strategy = BoxedStrategy<Self>;
863 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
864 use crate::proptest::{any_serde_json_value, any_smolstr, any_string};
865 use proptest::collection::{hash_map, vec};
866 let misc = hash_map(any_string(), any_serde_json_value(), 0..3);
867 (
868 any::<ExtensionId>(),
869 any_smolstr(),
870 any_string(),
871 misc,
872 any::<SignatureFunc>(),
873 vec(any::<LowerFunc>(), 0..2),
874 )
875 .prop_map(
876 |(extension, name, description, misc, signature_func, lower_funcs)| {
877 Self::new(OpDef {
878 extension,
879 extension_ref: Weak::default(),
881 name,
882 description,
883 misc,
884 signature_func,
885 lower_funcs,
886 constant_folder: None,
889 })
890 },
891 )
892 .boxed()
893 }
894 }
895 }
896}