Skip to main content

mz_expr/scalar/func/
macros.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10// Convenience macro for generating `inverse` values.
11macro_rules! to_unary {
12    ($f:expr) => {
13        Some(crate::UnaryFunc::from($f))
14    };
15}
16
17#[cfg(test)]
18mod test {
19    use mz_expr_derive::sqlfunc;
20    use mz_repr::SqlScalarType;
21
22    use crate::EvalError;
23    use crate::scalar::func::LazyUnaryFunc;
24
25    #[sqlfunc(sqlname = "INFALLIBLE")]
26    fn infallible1(a: f32) -> f32 {
27        a
28    }
29
30    #[sqlfunc]
31    fn infallible2(a: Option<f32>) -> f32 {
32        a.unwrap_or_default()
33    }
34
35    #[sqlfunc]
36    fn infallible3(a: f32) -> Option<f32> {
37        Some(a)
38    }
39
40    #[mz_ore::test]
41    fn elision_rules_infallible() {
42        assert_eq!(format!("{}", Infallible1), "INFALLIBLE");
43        assert!(Infallible1.propagates_nulls());
44        assert!(!Infallible1.introduces_nulls());
45
46        assert!(!Infallible2.propagates_nulls());
47        assert!(!Infallible2.introduces_nulls());
48
49        assert!(Infallible3.propagates_nulls());
50        assert!(Infallible3.introduces_nulls());
51    }
52
53    #[mz_ore::test]
54    fn output_types_infallible() {
55        assert_eq!(
56            Infallible1.output_sql_type(SqlScalarType::Float32.nullable(true)),
57            SqlScalarType::Float32.nullable(true)
58        );
59        assert_eq!(
60            Infallible1.output_sql_type(SqlScalarType::Float32.nullable(false)),
61            SqlScalarType::Float32.nullable(false)
62        );
63
64        assert_eq!(
65            Infallible2.output_sql_type(SqlScalarType::Float32.nullable(true)),
66            SqlScalarType::Float32.nullable(false)
67        );
68        assert_eq!(
69            Infallible2.output_sql_type(SqlScalarType::Float32.nullable(false)),
70            SqlScalarType::Float32.nullable(false)
71        );
72
73        assert_eq!(
74            Infallible3.output_sql_type(SqlScalarType::Float32.nullable(true)),
75            SqlScalarType::Float32.nullable(true)
76        );
77        assert_eq!(
78            Infallible3.output_sql_type(SqlScalarType::Float32.nullable(false)),
79            SqlScalarType::Float32.nullable(true)
80        );
81    }
82
83    #[sqlfunc]
84    fn fallible1(a: f32) -> Result<f32, EvalError> {
85        Ok(a)
86    }
87
88    #[sqlfunc]
89    fn fallible2(a: Option<f32>) -> Result<f32, EvalError> {
90        Ok(a.unwrap_or_default())
91    }
92
93    #[sqlfunc]
94    fn fallible3(a: f32) -> Result<Option<f32>, EvalError> {
95        Ok(Some(a))
96    }
97
98    #[mz_ore::test]
99    fn elision_rules_fallible() {
100        assert!(Fallible1.propagates_nulls());
101        assert!(!Fallible1.introduces_nulls());
102
103        assert!(!Fallible2.propagates_nulls());
104        assert!(!Fallible2.introduces_nulls());
105
106        assert!(Fallible3.propagates_nulls());
107        assert!(Fallible3.introduces_nulls());
108    }
109
110    #[mz_ore::test]
111    fn output_types_fallible() {
112        assert_eq!(
113            Fallible1.output_sql_type(SqlScalarType::Float32.nullable(true)),
114            SqlScalarType::Float32.nullable(true)
115        );
116        assert_eq!(
117            Fallible1.output_sql_type(SqlScalarType::Float32.nullable(false)),
118            SqlScalarType::Float32.nullable(false)
119        );
120
121        assert_eq!(
122            Fallible2.output_sql_type(SqlScalarType::Float32.nullable(true)),
123            SqlScalarType::Float32.nullable(false)
124        );
125        assert_eq!(
126            Fallible2.output_sql_type(SqlScalarType::Float32.nullable(false)),
127            SqlScalarType::Float32.nullable(false)
128        );
129
130        assert_eq!(
131            Fallible3.output_sql_type(SqlScalarType::Float32.nullable(true)),
132            SqlScalarType::Float32.nullable(true)
133        );
134        assert_eq!(
135            Fallible3.output_sql_type(SqlScalarType::Float32.nullable(false)),
136            SqlScalarType::Float32.nullable(true)
137        );
138    }
139
140    // Separate from the tests above, which call the lazy traits' methods and would
141    // find them ambiguous with the eager traits in scope.
142    mod stateful {
143        use mz_expr_derive::sqlfunc;
144        use mz_repr::RowArena;
145
146        use crate::EvalError;
147        use crate::scalar::func::EagerUnaryFunc;
148        use crate::scalar::func::binary::EagerBinaryFunc;
149
150        pub struct AddOffset(i64);
151
152        #[sqlfunc(sqlname = "add_offset")]
153        fn add_offset(&self, a: i64) -> i64 {
154            a + self.0
155        }
156
157        pub struct ScaleSum(i64);
158
159        #[sqlfunc(sqlname = "scale_sum")]
160        fn scale_sum(&self, a: i64, b: i64) -> Result<i64, EvalError> {
161            (a + b)
162                .checked_mul(self.0)
163                .ok_or(EvalError::NumericFieldOverflow)
164        }
165
166        #[mz_ore::test]
167        fn stateful_unary_and_binary_read_their_state() {
168            let arena = RowArena::new();
169            assert_eq!(EagerUnaryFunc::call(&AddOffset(3), 4, &arena), 7);
170            assert_eq!(EagerBinaryFunc::call(&ScaleSum(2), (3, 4), &arena), Ok(14));
171            assert_eq!(format!("{}", AddOffset(3)), "add_offset");
172            assert_eq!(format!("{}", ScaleSum(2)), "scale_sum");
173        }
174    }
175}
176
177/// Temporary macro that generates the equivalent of what enum_dispatch will do in the future. We
178/// need this manual macro implementation to delegate to the previous manual implementation for
179/// variants that use the old definitions.
180///
181/// Once everything is handled by this macro we can remove it and replace it with `enum_dispatch`
182///
183/// Variants marked `(E)` have payload structs generic over the stored expression type. The
184/// marker must be the literal ident `E`, matching the generic parameter the macro declares.
185macro_rules! derive_unary {
186    // Internal rules that rebuild one variant payload during expression
187    // conversion. Payloads without a marker are expression free and clone.
188    (@try_map_payload $f:ident) => { $f.clone() };
189    (@try_map_payload $f:ident $marker:ident) => { $f.try_map_expr()? };
190    (@map_payload $f:ident) => { $f.clone() };
191    (@map_payload $f:ident $marker:ident) => { $f.map_expr() };
192    // Internal rules that name a payload type at the MIR instantiation, for
193    // use in the impl block where `E` is not in scope.
194    (@mir_ty $name:ident) => { $name };
195    (@mir_ty $name:ident $marker:ident) => { $name<crate::MirScalarExpr> };
196    ($($name:ident $(($marker:ident))?),* $(,)?) => {
197        #[derive(
198            Ord, PartialOrd, Clone, Debug, Eq, PartialEq,
199            serde::Serialize, serde::Deserialize, Hash,
200                )]
201        pub enum UnaryFunc<E = crate::MirScalarExpr> {
202            $($name($name $(<$marker>)?),)*
203        }
204
205        // The `Eval` bound is required by the expression bearing payloads'
206        // `LazyUnaryFunc` impls, even for methods that never evaluate.
207        impl<E: Eval> UnaryFunc<E> {
208            pub fn eval<'a>(
209                &'a self,
210                datums: &[Datum<'a>],
211                temp_storage: &'a RowArena,
212                a: &'a impl Eval,
213            ) -> Result<Datum<'a>, EvalError> {
214                match self {
215                    $(Self::$name(f) => f.eval(datums, temp_storage, a),)*
216                }
217            }
218
219            pub fn output_sql_type(&self, input_type: SqlColumnType) -> SqlColumnType {
220                match self {
221                    $(Self::$name(f) => LazyUnaryFunc::output_sql_type(f, input_type),)*
222                }
223            }
224            pub fn output_type(&self, input_type: ReprColumnType) -> ReprColumnType {
225                match self {
226                    $(Self::$name(f) => LazyUnaryFunc::output_type(f, input_type),)*
227                }
228            }
229            pub fn propagates_nulls(&self) -> bool {
230                match self {
231                    $(Self::$name(f) => LazyUnaryFunc::propagates_nulls(f),)*
232                }
233            }
234            pub fn introduces_nulls(&self) -> bool {
235                match self {
236                    $(Self::$name(f) => LazyUnaryFunc::introduces_nulls(f),)*
237                }
238            }
239            pub fn preserves_uniqueness(&self) -> bool {
240                match self {
241                    $(Self::$name(f) => LazyUnaryFunc::preserves_uniqueness(f),)*
242                }
243            }
244            pub fn is_monotone(&self) -> bool {
245                match self {
246                    $(Self::$name(f) => LazyUnaryFunc::is_monotone(f),)*
247                }
248            }
249            pub fn could_error(&self) -> bool {
250                match self {
251                    $(Self::$name(f) => LazyUnaryFunc::could_error(f),)*
252                }
253            }
254            pub fn is_eliminable_cast(&self) -> bool {
255                match self {
256                    $(Self::$name(f) => LazyUnaryFunc::is_eliminable_cast(f),)*
257                }
258            }
259        }
260
261        impl<E> UnaryFunc<E> {
262            /// The canonical name of this variant, as declared by its
263            /// [`FuncName`](crate::func::FuncName) impl.
264            pub fn variant_name(&self) -> &'static str {
265                match self {
266                    $(Self::$name(_) =>
267                        <$name $(<$marker>)? as crate::func::FuncName>::NAME,)*
268                }
269            }
270
271            /// The `#[sqlfunc]` source of this variant's function, `None` for
272            /// hand-written functions. See [`FuncName::SQLFUNC`](crate::func::FuncName::SQLFUNC).
273            #[cfg(feature = "func-registry")]
274            pub fn sqlfunc_source(&self) -> Option<crate::func::SqlFuncSource> {
275                match self {
276                    $(Self::$name(_) =>
277                        <$name $(<$marker>)? as crate::func::FuncName>::SQLFUNC,)*
278                }
279            }
280
281            /// See [`FuncName::sqlfunc_input_types`](crate::func::FuncName::sqlfunc_input_types).
282            #[cfg(feature = "func-registry")]
283            pub fn sqlfunc_input_types(&self) -> Option<Vec<SqlColumnType>> {
284                match self {
285                    $(Self::$name(_) =>
286                        <$name $(<$marker>)? as crate::func::FuncName>::sqlfunc_input_types(),)*
287                }
288            }
289
290            /// Rebuilds this function with any stored expressions converted to
291            /// `E2`. Fails if any expression conversion fails, reporting the
292            /// first failure.
293            pub fn try_map_expr<'a, E2: TryFrom<&'a E>>(
294                &'a self,
295            ) -> Result<UnaryFunc<E2>, E2::Error> {
296                Ok(match self {
297                    $(Self::$name(f) => UnaryFunc::$name(
298                        derive_unary!(@try_map_payload f $($marker)?),
299                    ),)*
300                })
301            }
302
303            /// Rebuilds this function with any stored expressions converted to
304            /// `E2`.
305            pub fn map_expr<'a, E2: From<&'a E>>(&'a self) -> UnaryFunc<E2> {
306                match self {
307                    $(Self::$name(f) => UnaryFunc::$name(
308                        derive_unary!(@map_payload f $($marker)?),
309                    ),)*
310                }
311            }
312        }
313
314        // Methods that only exist at the MIR instantiation. `inverse` is an
315        // optimizer concept and the name lookup helpers serve MIR test
316        // tooling.
317        impl UnaryFunc {
318            pub fn inverse(&self) -> Option<UnaryFunc> {
319                match self {
320                    $(Self::$name(f) => LazyUnaryFunc::inverse(f),)*
321                }
322            }
323
324            /// Attempts to construct a `UnaryFunc` from the canonical name of
325            /// one of its variants, as declared by the variant's
326            /// [`FuncName`](crate::func::FuncName) impl (the name of the
327            /// underlying Rust function, e.g. `cast_int32_to_numeric`).
328            ///
329            /// Intended for test tooling that needs to name exact function
330            /// variants. Only variants whose inner function deserializes from
331            /// no data (unit functions and functions all of whose parameters
332            /// may default to `None`) are constructible. Returns `None` for
333            /// other variants and for unknown names. Returns the MIR
334            /// instantiation.
335            pub fn from_variant_name(name: &str) -> Option<Self> {
336                use crate::func::FuncName;
337                $(
338                    if name == <derive_unary!(@mir_ty $name $($marker)?) as FuncName>::NAME {
339                        return serde_json::from_value(
340                            serde_json::json!({ stringify!($name): null }),
341                        )
342                        .ok();
343                    }
344                )*
345                None
346            }
347
348            /// The canonical names of all variants, in declaration order.
349            pub fn variant_names() -> impl Iterator<Item = &'static str> {
350                use crate::func::FuncName;
351                [$(
352                    <derive_unary!(@mir_ty $name $($marker)?) as FuncName>::NAME,
353                )*]
354                .into_iter()
355            }
356        }
357
358        impl<E> fmt::Display for UnaryFunc<E> {
359            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
360                match self {
361                    $(Self::$name(func) => func.fmt(f),)*
362                }
363            }
364        }
365
366        $(
367            impl<E> From<$name $(<$marker>)?> for crate::UnaryFunc<E> {
368                fn from(variant: $name $(<$marker>)?) -> Self {
369                    Self::$name(variant)
370                }
371            }
372        )*
373    }
374}
375
376/// Generates the `VariadicFunc` enum, its `impl` block,
377/// `Display` impl, and `From<InnerType>` impls for each variant.
378///
379/// All variants must use explicit `Name(Type)` syntax. When the variant name equals
380/// the inner type name, write e.g. `And(And)`.
381macro_rules! derive_variadic {
382    ($($name:ident ( $variant:ident )),* $(,)?) => {
383        #[derive(
384            Ord, PartialOrd, Clone, Debug, Eq, PartialEq,
385            serde::Serialize, serde::Deserialize, Hash,
386        )]
387        pub enum VariadicFunc {
388            $($name($variant),)*
389        }
390
391        impl VariadicFunc {
392            pub fn eval<'a>(
393                &'a self,
394                datums: &[Datum<'a>],
395                temp_storage: &'a RowArena,
396                exprs: &'a [impl Eval],
397            ) -> Result<Datum<'a>, EvalError> {
398                match self {
399                    $(Self::$name(f) => f.eval(datums, temp_storage, exprs),)*
400                }
401            }
402
403            pub fn output_sql_type(&self, input_types: Vec<SqlColumnType>) -> SqlColumnType {
404                match self {
405                    $(Self::$name(f) => LazyVariadicFunc::output_type(f, &input_types),)*
406                }
407            }
408
409            /// Computes the representation type of this variadic function.
410            ///
411            /// Wrapper around [`Self::output_sql_type`] that converts to representation types.
412            pub fn output_type(&self, input_types: Vec<ReprColumnType>) -> ReprColumnType {
413                let sql_types = input_types.iter().map(SqlColumnType::from_repr).collect();
414                ReprColumnType::from(&self.output_sql_type(sql_types))
415            }
416
417            pub fn propagates_nulls(&self) -> bool {
418                match self {
419                    $(Self::$name(f) => LazyVariadicFunc::propagates_nulls(f),)*
420                }
421            }
422
423            pub fn introduces_nulls(&self) -> bool {
424                match self {
425                    $(Self::$name(f) => LazyVariadicFunc::introduces_nulls(f),)*
426                }
427            }
428
429            pub fn could_error(&self) -> bool {
430                match self {
431                    $(Self::$name(f) => LazyVariadicFunc::could_error(f),)*
432                }
433            }
434
435            pub fn is_monotone(&self) -> bool {
436                match self {
437                    $(Self::$name(f) => LazyVariadicFunc::is_monotone(f),)*
438                }
439            }
440
441            pub fn is_associative(&self) -> bool {
442                match self {
443                    $(Self::$name(f) => LazyVariadicFunc::is_associative(f),)*
444                }
445            }
446
447            pub fn is_infix_op(&self) -> bool {
448                match self {
449                    $(Self::$name(f) => LazyVariadicFunc::is_infix_op(f),)*
450                }
451            }
452
453            /// The canonical name of this variant, as declared by its
454            /// [`FuncName`](crate::func::FuncName) impl.
455            pub fn variant_name(&self) -> &'static str {
456                match self {
457                    $(Self::$name(_) => <$variant as crate::func::FuncName>::NAME,)*
458                }
459            }
460
461            /// The `#[sqlfunc]` source of this variant's function, `None` for
462            /// hand-written functions. See [`FuncName::SQLFUNC`](crate::func::FuncName::SQLFUNC).
463            #[cfg(feature = "func-registry")]
464            pub fn sqlfunc_source(&self) -> Option<crate::func::SqlFuncSource> {
465                match self {
466                    $(Self::$name(_) => <$variant as crate::func::FuncName>::SQLFUNC,)*
467                }
468            }
469
470            /// See [`FuncName::sqlfunc_input_types`](crate::func::FuncName::sqlfunc_input_types).
471            #[cfg(feature = "func-registry")]
472            pub fn sqlfunc_input_types(&self) -> Option<Vec<SqlColumnType>> {
473                match self {
474                    $(Self::$name(_) =>
475                        <$variant as crate::func::FuncName>::sqlfunc_input_types(),)*
476                }
477            }
478
479            /// Attempts to construct a `VariadicFunc` from the canonical name
480            /// of one of its variants, as declared by the variant's
481            /// [`FuncName`](crate::func::FuncName) impl (the name of the
482            /// underlying Rust function, e.g. `record_create`).
483            ///
484            /// Intended for test tooling that needs to name exact function
485            /// variants. Only variants whose inner function deserializes from
486            /// no data (unit functions and functions all of whose parameters
487            /// may default to `None`) are constructible. Returns `None` for
488            /// other variants and for unknown names.
489            pub fn from_variant_name(name: &str) -> Option<Self> {
490                $(
491                    if name == <$variant as crate::func::FuncName>::NAME {
492                        return serde_json::from_value(
493                            serde_json::json!({ stringify!($name): null }),
494                        )
495                        .ok();
496                    }
497                )*
498                None
499            }
500
501            /// The canonical names of all variants, in declaration order.
502            pub fn variant_names() -> impl Iterator<Item = &'static str> {
503                [$(<$variant as crate::func::FuncName>::NAME,)*].into_iter()
504            }
505        }
506
507        impl fmt::Display for VariadicFunc {
508            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
509                match self {
510                    $(Self::$name(func) => func.fmt(f),)*
511                }
512            }
513        }
514
515        $(
516            impl From<$variant> for crate::VariadicFunc {
517                fn from(variant: $variant) -> Self {
518                    Self::$name(variant)
519                }
520            }
521        )*
522    }
523}
524
525/// Generates the `BinaryFunc` enum, its `impl` block (with 8 delegating methods),
526/// `Display` impl, and `From<InnerType>` impls for each variant.
527///
528/// All variants must use explicit `Name(Type)` syntax. When the variant name equals
529/// the inner type name, write e.g. `AddInt16(AddInt16)`.
530macro_rules! derive_binary {
531    ($($name:ident ( $variant:ident )),* $(,)?) => {
532        #[derive(
533            Ord, PartialOrd, Clone, Debug, Eq, PartialEq,
534            serde::Serialize, serde::Deserialize, Hash,
535                )]
536        pub enum BinaryFunc {
537            $($name($variant),)*
538        }
539
540        impl BinaryFunc {
541            pub fn eval<'a>(
542                &'a self,
543                datums: &[Datum<'a>],
544                temp_storage: &'a RowArena,
545                exprs: &[&'a impl Eval],
546            ) -> Result<Datum<'a>, EvalError> {
547                match self {
548                    $(Self::$name(f) => f.eval(datums, temp_storage, exprs),)*
549                }
550            }
551
552            pub fn output_sql_type(&self, input_types: &[SqlColumnType]) -> SqlColumnType {
553                match self {
554                    $(Self::$name(f) => {
555                        LazyBinaryFunc::output_sql_type(f, input_types)
556                    },)*
557                }
558            }
559
560            pub fn output_type(&self, input_types: &[ReprColumnType]) -> ReprColumnType {
561                match self {
562                    $(Self::$name(f) => LazyBinaryFunc::output_type(f, input_types),)*
563                }
564            }
565
566            pub fn propagates_nulls(&self) -> bool {
567                match self {
568                    $(Self::$name(f) => LazyBinaryFunc::propagates_nulls(f),)*
569                }
570            }
571
572            pub fn introduces_nulls(&self) -> bool {
573                match self {
574                    $(Self::$name(f) => LazyBinaryFunc::introduces_nulls(f),)*
575                }
576            }
577
578            pub fn is_infix_op(&self) -> bool {
579                match self {
580                    $(Self::$name(f) => LazyBinaryFunc::is_infix_op(f),)*
581                }
582            }
583
584            pub fn negate(&self) -> Option<BinaryFunc> {
585                match self {
586                    $(Self::$name(f) => LazyBinaryFunc::negate(f),)*
587                }
588            }
589
590            pub fn could_error(&self) -> bool {
591                match self {
592                    $(Self::$name(f) => LazyBinaryFunc::could_error(f),)*
593                }
594            }
595
596            pub fn is_monotone(&self) -> (bool, bool) {
597                match self {
598                    $(Self::$name(f) => LazyBinaryFunc::is_monotone(f),)*
599                }
600            }
601
602            pub fn is_infinity_monotone(&self) -> bool {
603                match self {
604                    $(Self::$name(f) => LazyBinaryFunc::is_infinity_monotone(f),)*
605                }
606            }
607
608            /// The canonical name of this variant, as declared by its
609            /// [`FuncName`](crate::func::FuncName) impl.
610            pub fn variant_name(&self) -> &'static str {
611                match self {
612                    $(Self::$name(_) => <$variant as crate::func::FuncName>::NAME,)*
613                }
614            }
615
616            /// The `#[sqlfunc]` source of this variant's function, `None` for
617            /// hand-written functions. See [`FuncName::SQLFUNC`](crate::func::FuncName::SQLFUNC).
618            #[cfg(feature = "func-registry")]
619            pub fn sqlfunc_source(&self) -> Option<crate::func::SqlFuncSource> {
620                match self {
621                    $(Self::$name(_) => <$variant as crate::func::FuncName>::SQLFUNC,)*
622                }
623            }
624
625            /// See [`FuncName::sqlfunc_input_types`](crate::func::FuncName::sqlfunc_input_types).
626            #[cfg(feature = "func-registry")]
627            pub fn sqlfunc_input_types(&self) -> Option<Vec<SqlColumnType>> {
628                match self {
629                    $(Self::$name(_) =>
630                        <$variant as crate::func::FuncName>::sqlfunc_input_types(),)*
631                }
632            }
633
634            /// Attempts to construct a `BinaryFunc` from the canonical name of
635            /// one of its variants, as declared by the variant's
636            /// [`FuncName`](crate::func::FuncName) impl (the name of the
637            /// underlying Rust function, e.g. `add_int32`).
638            ///
639            /// Intended for test tooling that needs to name exact function
640            /// variants. Only variants whose inner function deserializes from
641            /// no data (unit functions and functions all of whose parameters
642            /// may default to `None`) are constructible. Returns `None` for
643            /// other variants and for unknown names.
644            pub fn from_variant_name(name: &str) -> Option<Self> {
645                $(
646                    if name == <$variant as crate::func::FuncName>::NAME {
647                        return serde_json::from_value(
648                            serde_json::json!({ stringify!($name): null }),
649                        )
650                        .ok();
651                    }
652                )*
653                None
654            }
655
656            /// The canonical names of all variants, in declaration order.
657            pub fn variant_names() -> impl Iterator<Item = &'static str> {
658                [$(<$variant as crate::func::FuncName>::NAME,)*].into_iter()
659            }
660        }
661
662        impl fmt::Display for BinaryFunc {
663            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
664                match self {
665                    $(Self::$name(func) => func.fmt(f),)*
666                }
667            }
668        }
669
670        $(
671            impl From<$variant> for crate::BinaryFunc {
672                fn from(variant: $variant) -> Self {
673                    Self::$name(variant)
674                }
675            }
676        )*
677    }
678}