equator_macro/
lib.rs

1use proc_macro2::{Span, TokenStream};
2use quote::quote;
3use spanned::Spanned;
4use syn::*;
5use syn_expr::{CmpOp, CustomExpr};
6
7mod syn_expr {
8    #![allow(dead_code)]
9
10    use syn::{
11        custom_keyword, parenthesized, punctuated::Punctuated, token::Paren, BinOp, Expr,
12        ExprBinary, Token,
13    };
14
15    custom_keyword!(all);
16    custom_keyword!(any);
17
18    #[derive(Clone)]
19    pub enum CmpOp {
20        Custom(Token![:], Expr, Token![:]),
21        Approx(Token![~]),
22        Eq(Token![==]),
23        Ne(Token![!=]),
24        Ge(Token![>=]),
25        Le(Token![<=]),
26        Gt(Token![>]),
27        Lt(Token![<]),
28    }
29
30    #[derive(Clone)]
31    pub enum CustomExpr {
32        All {
33            all_token: all,
34            paren_token: Paren,
35            args: Punctuated<CustomExpr, Token![,]>,
36        },
37        Any {
38            any_token: any,
39            paren_token: Paren,
40            args: Punctuated<CustomExpr, Token![,]>,
41        },
42        Cmp {
43            left: Expr,
44            op: CmpOp,
45            right: Expr,
46        },
47        Boolean(Expr),
48    }
49
50    impl syn::parse::Parse for CustomExpr {
51        fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
52            let lookahead = input.lookahead1();
53            if lookahead.peek(all) {
54                let _: syn::token::Tilde;
55                let content;
56                Ok(CustomExpr::All {
57                    all_token: input.parse()?,
58                    paren_token: parenthesized!(content in input),
59                    args: content.parse_terminated(Self::parse, Token![,])?,
60                })
61            } else if lookahead.peek(any) {
62                let content;
63                Ok(CustomExpr::Any {
64                    any_token: input.parse()?,
65                    paren_token: parenthesized!(content in input),
66                    args: content.parse_terminated(Self::parse, Token![,])?,
67                })
68            } else {
69                let expr = input.parse()?;
70                let lookahead = input.lookahead1();
71
72                match expr {
73                    Expr::Binary(ExprBinary {
74                        attrs: _,
75                        left,
76                        op:
77                            op @ (BinOp::Eq(_)
78                            | BinOp::Ne(_)
79                            | BinOp::Ge(_)
80                            | BinOp::Le(_)
81                            | BinOp::Gt(_)
82                            | BinOp::Lt(_)),
83
84                        right,
85                    }) => match op {
86                        BinOp::Eq(op) => Ok(CustomExpr::Cmp {
87                            left: *left,
88                            op: CmpOp::Eq(op),
89                            right: *right,
90                        }),
91                        BinOp::Ne(op) => Ok(CustomExpr::Cmp {
92                            left: *left,
93                            op: CmpOp::Ne(op),
94                            right: *right,
95                        }),
96                        BinOp::Ge(op) => Ok(CustomExpr::Cmp {
97                            left: *left,
98                            op: CmpOp::Ge(op),
99                            right: *right,
100                        }),
101                        BinOp::Le(op) => Ok(CustomExpr::Cmp {
102                            left: *left,
103                            op: CmpOp::Le(op),
104                            right: *right,
105                        }),
106                        BinOp::Gt(op) => Ok(CustomExpr::Cmp {
107                            left: *left,
108                            op: CmpOp::Gt(op),
109                            right: *right,
110                        }),
111                        BinOp::Lt(op) => Ok(CustomExpr::Cmp {
112                            left: *left,
113                            op: CmpOp::Lt(op),
114                            right: *right,
115                        }),
116                        _ => unreachable!(),
117                    },
118                    expr => {
119                        if lookahead.peek(Token![~]) {
120                            let left = expr;
121                            let op = CmpOp::Approx(input.parse()?);
122                            let right: Expr = input.parse()?;
123                            return Ok(CustomExpr::Cmp { left, op, right });
124                        }
125
126                        if lookahead.peek(Token![:]) {
127                            let left = expr;
128                            let op = CmpOp::Custom(input.parse()?, input.parse()?, input.parse()?);
129                            let right = input.parse()?;
130                            return Ok(CustomExpr::Cmp { left, op, right });
131                        };
132
133                        Ok(CustomExpr::Boolean(expr))
134                    }
135                }
136            }
137        }
138    }
139}
140
141struct Operand {
142    placeholder_id: Ident,
143    diagnostic_expr: TokenStream,
144}
145
146enum AssertExpr {
147    BoolExpr(Operand),
148    CmpExpr {
149        custom: bool,
150        cmp: Operand,
151        left: Operand,
152        right: Operand,
153    },
154    AndExpr(Box<(AssertExpr, AssertExpr)>),
155    OrExpr(Box<(AssertExpr, AssertExpr)>),
156}
157
158struct Code {
159    assert_expr: TokenStream,
160    source: TokenStream,
161    source_type: TokenStream,
162    debug_lhs: TokenStream,
163    debug_rhs: TokenStream,
164    debug_cmp: TokenStream,
165}
166
167impl AssertExpr {
168    fn code(&self, crate_name: &Path) -> Code {
169        match self {
170            AssertExpr::BoolExpr(Operand {
171                placeholder_id,
172                diagnostic_expr: expr,
173            }) => Code {
174                assert_expr: quote! { (#placeholder_id).0.0.0 },
175                source: quote! { #expr },
176                source_type: quote! { &'static ::core::primitive::str },
177                debug_lhs: quote! { () },
178                debug_rhs: quote! { () },
179                debug_cmp: quote! { #placeholder_id.0.0.0 },
180            },
181            AssertExpr::CmpExpr {
182                custom,
183                cmp:
184                    Operand {
185                        placeholder_id: cmp_placeholder_id,
186                        diagnostic_expr: _,
187                    },
188                left:
189                    Operand {
190                        placeholder_id: left_placeholder_id,
191                        diagnostic_expr: left_expr,
192                    },
193                right:
194                    Operand {
195                        placeholder_id: right_placeholder_id,
196                        diagnostic_expr: right_expr,
197                    },
198            } => {
199                let name = if *custom {
200                    quote! { CustomCmpExpr }
201                } else {
202                    quote! { CmpExpr }
203                };
204                Code {
205                    assert_expr: quote! {
206                        #crate_name::expr::#name {
207                            cmp: #cmp_placeholder_id,
208                            lhs: #left_placeholder_id,
209                            rhs: #right_placeholder_id,
210                        }
211                    },
212                    source: quote! {
213                        #crate_name::expr::#name {
214                            cmp: (),
215                            lhs: #left_expr,
216                            rhs: #right_expr,
217                        }
218                    },
219                    source_type: quote! {
220                        #crate_name::expr::#name<
221                            (),
222                            &'static ::core::primitive::str,
223                            &'static ::core::primitive::str,
224                        >
225                    },
226                    debug_lhs: quote! { (#left_placeholder_id).get_ptr() },
227                    debug_rhs: quote! { (#right_placeholder_id).get_ptr() },
228                    debug_cmp: if *custom {
229                        quote! { (&(#cmp_placeholder_id).0.0.0) as *const _ as *const () }
230                    } else {
231                        quote! { () }
232                    },
233                }
234            }
235            AssertExpr::AndExpr(inner) => {
236                let (left, right) = &**inner;
237                let Code {
238                    assert_expr: left_assert_expr,
239                    source: left_source,
240                    source_type: left_source_type,
241                    debug_lhs: left_debug_lhs,
242                    debug_rhs: left_debug_rhs,
243                    debug_cmp: left_debug_cmp,
244                } = left.code(crate_name);
245                let Code {
246                    assert_expr: right_assert_expr,
247                    source: right_source,
248                    source_type: right_source_type,
249                    debug_lhs: right_debug_lhs,
250                    debug_rhs: right_debug_rhs,
251                    debug_cmp: right_debug_cmp,
252                } = right.code(crate_name);
253                Code {
254                    assert_expr: quote! {
255                        #crate_name::expr::AndExpr {
256                            lhs: (#left_assert_expr),
257                            rhs: (#right_assert_expr),
258                        }
259                    },
260                    source: quote! {
261                        #crate_name::expr::AndExpr {
262                            lhs: (#left_source),
263                            rhs: (#right_source),
264                        }
265                    },
266                    source_type: quote! {
267                        #crate_name::expr::AndExpr<#left_source_type, #right_source_type>
268                    },
269                    debug_lhs: quote! {
270                        #crate_name::expr::AndExpr {
271                            lhs: (#left_debug_lhs),
272                            rhs: (#right_debug_lhs),
273                        }
274                    },
275                    debug_rhs: quote! {
276                        #crate_name::expr::AndExpr {
277                            lhs: (#left_debug_rhs),
278                            rhs: (#right_debug_rhs),
279                        }
280                    },
281                    debug_cmp: quote! {
282                        #crate_name::expr::AndExpr {
283                            lhs: (#left_debug_cmp),
284                            rhs: (#right_debug_cmp),
285                        }
286                    },
287                }
288            }
289            AssertExpr::OrExpr(inner) => {
290                let (left, right) = &**inner;
291                let Code {
292                    assert_expr: left_assert_expr,
293                    source: left_source,
294                    source_type: left_source_type,
295                    debug_lhs: left_debug_lhs,
296                    debug_rhs: left_debug_rhs,
297                    debug_cmp: left_debug_cmp,
298                } = left.code(crate_name);
299                let Code {
300                    assert_expr: right_assert_expr,
301                    source: right_source,
302                    source_type: right_source_type,
303                    debug_lhs: right_debug_lhs,
304                    debug_rhs: right_debug_rhs,
305                    debug_cmp: right_debug_cmp,
306                } = right.code(crate_name);
307                Code {
308                    assert_expr: quote! {
309                        #crate_name::expr::OrExpr {
310                            lhs: (#left_assert_expr),
311                            rhs: (#right_assert_expr),
312                        }
313                    },
314                    source: quote! {
315                        #crate_name::expr::OrExpr {
316                            lhs: (#left_source),
317                            rhs: (#right_source),
318                        }
319                    },
320                    source_type: quote! {
321                        #crate_name::expr::OrExpr<#left_source_type, #right_source_type>
322                    },
323                    debug_lhs: quote! {
324                        #crate_name::expr::OrExpr {
325                            lhs: (#left_debug_lhs),
326                            rhs: (#right_debug_lhs),
327                        }
328                    },
329                    debug_rhs: quote! {
330                        #crate_name::expr::OrExpr {
331                            lhs: (#left_debug_rhs),
332                            rhs: (#right_debug_rhs),
333                        }
334                    },
335                    debug_cmp: quote! {
336                        #crate_name::expr::OrExpr {
337                            lhs: (#left_debug_cmp),
338                            rhs: (#right_debug_cmp),
339                        }
340                    },
341                }
342            }
343        }
344    }
345}
346
347fn usize_to_ident(idx: usize) -> Ident {
348    Ident::new(&format!("__operand_{idx}"), Span::call_site())
349}
350
351fn cmp_usize_to_ident(idx: usize) -> Ident {
352    Ident::new(&format!("__cmp_{idx}"), Span::call_site())
353}
354
355fn handle_expr(
356    crate_name: &Path,
357    atomics: &mut Vec<Expr>,
358    cmp_atomics: &mut Vec<Expr>,
359    diagnostics: &mut Vec<TokenStream>,
360    mut placeholder_id: usize,
361    mut cmp_placeholder_id: usize,
362    expr: CustomExpr,
363) -> (AssertExpr, usize, usize) {
364    match expr {
365        CustomExpr::All {
366            all_token: _,
367            paren_token: _,
368            args,
369        } => {
370            let mut args = args.into_iter().collect::<Vec<_>>();
371            if args.is_empty() {
372                let expr = Expr::Lit(ExprLit {
373                    attrs: Vec::new(),
374                    lit: Lit::Bool(LitBool {
375                        value: true,
376                        span: Span::call_site(),
377                    }),
378                });
379                let diagnostic_expr = quote! { ::core::stringify!(#expr) };
380                atomics.push(expr);
381                (
382                    AssertExpr::BoolExpr(Operand {
383                        placeholder_id: usize_to_ident(placeholder_id),
384                        diagnostic_expr,
385                    }),
386                    placeholder_id + 1,
387                    cmp_placeholder_id,
388                )
389            } else {
390                let mut assert_expr;
391                let mut arg_expr;
392                (assert_expr, placeholder_id, cmp_placeholder_id) = handle_expr(
393                    crate_name,
394                    atomics,
395                    cmp_atomics,
396                    diagnostics,
397                    placeholder_id,
398                    cmp_placeholder_id,
399                    args.pop().unwrap(),
400                );
401                while let Some(arg) = args.pop() {
402                    (arg_expr, placeholder_id, cmp_placeholder_id) = handle_expr(
403                        crate_name,
404                        atomics,
405                        cmp_atomics,
406                        diagnostics,
407                        placeholder_id,
408                        cmp_placeholder_id,
409                        arg,
410                    );
411                    assert_expr = AssertExpr::AndExpr(Box::new((arg_expr, assert_expr)));
412                }
413                (assert_expr, placeholder_id, cmp_placeholder_id)
414            }
415        }
416        CustomExpr::Any {
417            any_token: _,
418            paren_token: _,
419            args,
420        } => {
421            let mut args = args.into_iter().collect::<Vec<_>>();
422            if args.is_empty() {
423                let expr = Expr::Lit(ExprLit {
424                    attrs: Vec::new(),
425                    lit: Lit::Bool(LitBool {
426                        value: false,
427                        span: Span::call_site(),
428                    }),
429                });
430                let diagnostic_expr = quote! { ::core::stringify!(#expr) };
431                atomics.push(expr);
432                (
433                    AssertExpr::BoolExpr(Operand {
434                        placeholder_id: usize_to_ident(placeholder_id),
435                        diagnostic_expr,
436                    }),
437                    placeholder_id + 1,
438                    cmp_placeholder_id,
439                )
440            } else {
441                let mut assert_expr;
442                let mut arg_expr;
443                (assert_expr, placeholder_id, cmp_placeholder_id) = handle_expr(
444                    crate_name,
445                    atomics,
446                    cmp_atomics,
447                    diagnostics,
448                    placeholder_id,
449                    cmp_placeholder_id,
450                    args.pop().unwrap(),
451                );
452                while let Some(arg) = args.pop() {
453                    (arg_expr, placeholder_id, cmp_placeholder_id) = handle_expr(
454                        crate_name,
455                        atomics,
456                        cmp_atomics,
457                        diagnostics,
458                        placeholder_id,
459                        cmp_placeholder_id,
460                        arg,
461                    );
462                    assert_expr = AssertExpr::OrExpr(Box::new((arg_expr, assert_expr)));
463                }
464                (assert_expr, placeholder_id, cmp_placeholder_id)
465            }
466        }
467        CustomExpr::Cmp {
468            left,
469            right,
470            op: CmpOp::Custom(_, cmp, _),
471        } => handle_cmp(
472            true,
473            crate_name,
474            atomics,
475            cmp_atomics,
476            diagnostics,
477            |crate_name, cmp, lhs, rhs| quote! { #crate_name::Cmp::test(#cmp, #lhs, #rhs) },
478            placeholder_id,
479            cmp_placeholder_id,
480            left,
481            right,
482            cmp,
483        ),
484        CustomExpr::Cmp {
485            left,
486            right,
487            op: CmpOp::Approx(op),
488        } => handle_cmp(
489            true,
490            crate_name,
491            atomics,
492            cmp_atomics,
493            diagnostics,
494            |crate_name, cmp, lhs, rhs| quote! { #crate_name::Cmp::test(#cmp, #lhs, #rhs) },
495            placeholder_id,
496            cmp_placeholder_id,
497            left,
498            right,
499            Expr::Path(ExprPath {
500                attrs: vec![],
501                qself: None,
502                path: Ident::new("approx_eq", op.spans[0]).into(),
503            }),
504        ),
505        CustomExpr::Cmp {
506            left,
507            right,
508            op: CmpOp::Eq(_),
509        } => handle_cmp(
510            false,
511            crate_name,
512            atomics,
513            cmp_atomics,
514            diagnostics,
515            |_, _, lhs, rhs| quote! { *(#lhs) == *(#rhs) },
516            placeholder_id,
517            cmp_placeholder_id,
518            left,
519            right,
520            make_cmp(crate_name, "Eq"),
521        ),
522        CustomExpr::Cmp {
523            left,
524            right,
525            op: CmpOp::Ne(_),
526        } => handle_cmp(
527            false,
528            crate_name,
529            atomics,
530            cmp_atomics,
531            diagnostics,
532            |_, _, lhs, rhs| quote! { *(#lhs) != *(#rhs) },
533            placeholder_id,
534            cmp_placeholder_id,
535            left,
536            right,
537            make_cmp(crate_name, "Ne"),
538        ),
539        CustomExpr::Cmp {
540            left,
541            right,
542            op: CmpOp::Lt(_),
543        } => handle_cmp(
544            false,
545            crate_name,
546            atomics,
547            cmp_atomics,
548            diagnostics,
549            |_, _, lhs, rhs| quote! { *(#lhs) < *(#rhs) },
550            placeholder_id,
551            cmp_placeholder_id,
552            left,
553            right,
554            make_cmp(crate_name, "Lt"),
555        ),
556        CustomExpr::Cmp {
557            left,
558            right,
559            op: CmpOp::Gt(_),
560        } => handle_cmp(
561            false,
562            crate_name,
563            atomics,
564            cmp_atomics,
565            diagnostics,
566            |_, _, lhs, rhs| quote! { *(#lhs) > *(#rhs) },
567            placeholder_id,
568            cmp_placeholder_id,
569            left,
570            right,
571            make_cmp(crate_name, "Gt"),
572        ),
573        CustomExpr::Cmp {
574            left,
575            right,
576            op: CmpOp::Le(_),
577        } => handle_cmp(
578            false,
579            crate_name,
580            atomics,
581            cmp_atomics,
582            diagnostics,
583            |_, _, lhs, rhs| quote! { *(#lhs) <= *(#rhs) },
584            placeholder_id,
585            cmp_placeholder_id,
586            left,
587            right,
588            make_cmp(crate_name, "Le"),
589        ),
590        CustomExpr::Cmp {
591            left,
592            right,
593            op: CmpOp::Ge(_),
594        } => handle_cmp(
595            false,
596            crate_name,
597            atomics,
598            cmp_atomics,
599            diagnostics,
600            |_, _, lhs, rhs| quote! { *(#lhs) >= *(#rhs) },
601            placeholder_id,
602            cmp_placeholder_id,
603            left,
604            right,
605            make_cmp(crate_name, "Ge"),
606        ),
607        CustomExpr::Boolean(expr) => (
608            AssertExpr::BoolExpr(Operand {
609                placeholder_id: usize_to_ident(placeholder_id),
610                diagnostic_expr: quote! { ::core::stringify!(#expr) },
611            }),
612            {
613                let val = usize_to_ident(placeholder_id);
614                diagnostics.push(quote! { *#val });
615                atomics.push(expr);
616                placeholder_id + 1
617            },
618            cmp_placeholder_id,
619        ),
620    }
621}
622
623fn make_cmp(crate_name: &Path, name: &str) -> Expr {
624    let span = crate_name.span();
625    let mut path = crate_name.clone();
626    path.segments.push_punct(Token![::](crate_name.span()));
627    path.segments.push_value(PathSegment {
628        ident: Ident::new(name, span),
629        arguments: PathArguments::None,
630    });
631    Expr::Path(ExprPath {
632        attrs: vec![],
633        qself: None,
634        path,
635    })
636}
637
638fn handle_cmp(
639    custom: bool,
640    crate_name: &Path,
641    atomics: &mut Vec<Expr>,
642    cmp_atomics: &mut Vec<Expr>,
643    diagnostics: &mut Vec<TokenStream>,
644    diagnose: fn(crate_name: &Path, cmp: Ident, lhs: Ident, rhs: Ident) -> TokenStream,
645    placeholder_id: usize,
646    cmp_placeholder_id: usize,
647    left: Expr,
648    right: Expr,
649    cmp: Expr,
650) -> (AssertExpr, usize, usize) {
651    (
652        AssertExpr::CmpExpr {
653            custom,
654            cmp: Operand {
655                placeholder_id: cmp_usize_to_ident(cmp_placeholder_id),
656                diagnostic_expr: quote! {},
657            },
658            left: Operand {
659                placeholder_id: usize_to_ident(placeholder_id),
660                diagnostic_expr: quote! { ::core::stringify!(#left) },
661            },
662            right: Operand {
663                placeholder_id: usize_to_ident(placeholder_id + 1),
664                diagnostic_expr: quote! { ::core::stringify!(#right) },
665            },
666        },
667        {
668            {
669                let cmp = cmp_usize_to_ident(cmp_placeholder_id);
670                let lhs = usize_to_ident(placeholder_id);
671                let rhs = usize_to_ident(placeholder_id + 1);
672                diagnostics.push(diagnose(crate_name, cmp, lhs, rhs));
673            }
674            cmp_atomics.push(cmp);
675            atomics.push(left);
676            atomics.push(right);
677            placeholder_id + 2
678        },
679        cmp_placeholder_id + 1,
680    )
681}
682
683type FormatArgs = syn::punctuated::Punctuated<syn::Expr, syn::token::Comma>;
684
685struct Args {
686    crate_name: Path,
687    expr: CustomExpr,
688    format_args: Option<FormatArgs>,
689}
690
691impl syn::parse::Parse for Args {
692    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
693        let crate_name = input.parse()?;
694        let _comma: syn::token::Comma = input.parse()?;
695        let expr = input.parse()?;
696        let format_args = if input.is_empty() {
697            FormatArgs::new()
698        } else {
699            input.parse::<syn::token::Comma>()?;
700            FormatArgs::parse_terminated(input)?
701        };
702
703        let format_args = Some(format_args).filter(|x| !x.is_empty());
704        Ok(Self {
705            crate_name,
706            expr,
707            format_args,
708        })
709    }
710}
711
712#[proc_macro]
713pub fn assert(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
714    let input = syn::parse_macro_input!(item as Args);
715
716    let crate_name = &input.crate_name;
717    let args = input.format_args;
718    let body = input.expr;
719
720    let mut atomics = Vec::new();
721    let mut cmp_atomics = Vec::new();
722    let mut diagnostics = Vec::new();
723    let assert_expr = handle_expr(
724        crate_name,
725        &mut atomics,
726        &mut cmp_atomics,
727        &mut diagnostics,
728        0,
729        0,
730        body.clone(),
731    )
732    .0;
733    let atomics = atomics;
734    let cmp_atomics = cmp_atomics;
735    let placeholders = &*atomics
736        .iter()
737        .enumerate()
738        .map(|(idx, _)| Ident::new(&format!("__operand_{idx}"), Span::call_site()))
739        .collect::<Vec<_>>();
740
741    let cmp_placeholders = &*cmp_atomics
742        .iter()
743        .enumerate()
744        .map(|(idx, _)| Ident::new(&format!("__cmp_{idx}"), Span::call_site()))
745        .collect::<Vec<_>>();
746
747    let Code {
748        assert_expr,
749        source,
750        source_type,
751        debug_cmp,
752        debug_lhs,
753        debug_rhs,
754    } = assert_expr.code(crate_name);
755
756    let message = match args {
757        Some(args) => quote! { #crate_name::Message(::core::format_args!(#args)) },
758        None => quote! { #crate_name::NoMessage },
759    };
760
761    let outer_block = {
762        quote! {
763            match (#(&(#atomics),)* #(&(#cmp_atomics),)*) {
764                (#(#placeholders,)* #(#cmp_placeholders,)*) => {
765                    if false {
766                        #(let _ = #diagnostics;)*
767                    }
768                    use #crate_name::spec::debug::TryDebugWrap;
769                    use #crate_name::spec::sized::TrySizedWrap;
770                    use #crate_name::spec::by_val::TryByValWrap;
771                    use #crate_name::traits::Expr;
772
773                    #(let #placeholders = (&&#crate_name::spec::Wrapper(#placeholders)).wrap_debug().do_wrap(#placeholders);)*
774                    #(let #placeholders = (&&#crate_name::spec::Wrapper(#placeholders)).wrap_sized().do_wrap(#placeholders);)*
775                    #(let #placeholders = (#placeholders).get();)*
776                    #(let #placeholders = (&&#crate_name::spec::Wrapper(#placeholders)).wrap_by_val().do_wrap(#placeholders);)*
777
778                    #(let #cmp_placeholders = #crate_name::spec::debug::CmpDebugWrapper(#cmp_placeholders);)*
779                    #(let #cmp_placeholders = #crate_name::spec::sized::CmpSizedWrapper(#cmp_placeholders);)*
780                    #(let #cmp_placeholders = #crate_name::spec::by_val::CmpByValWrapper(#cmp_placeholders).__wrap_ref();)*
781
782                    let __assert_expr = #crate_name::structures::Finalize {
783                        inner: #assert_expr,
784                    };
785
786                    if !(&&&__assert_expr).eval_expr() {
787                        struct Source<'a, V>(pub &'a V);
788                        impl<V: #crate_name::traits::DynInfoType> #crate_name::traits::DynInfoType for &Source<'_, V> {
789                            type VTable = #crate_name::structures::WithSource<#source_type, &'static V::VTable>;
790                            const NULL_VTABLE: &'static Self::VTable = &#crate_name::structures::WithSource {
791                                source: #source,
792                                file: ::core::file!(),
793                                line: ::core::line!(),
794                                col: ::core::column!(),
795                                vtable: V::NULL_VTABLE,
796                            };
797                        }
798                        impl<V: #crate_name::traits::DynInfo> #crate_name::traits::DynInfo for &Source<'_, V> {
799                            const VTABLE: &'static Self::VTable = &#crate_name::structures::WithSource {
800                                source: #source,
801                                file: ::core::file!(),
802                                line: ::core::line!(),
803                                col: ::core::column!(),
804                                vtable: V::VTABLE,
805                            };
806                        }
807                        impl<V> #crate_name::traits::DynInfoType for Source<'_, V> {
808                            type VTable = #crate_name::structures::WithSource<&'static str, &'static ()>;
809                            const NULL_VTABLE: &'static Self::VTable = &#crate_name::structures::WithSource {
810                                source: "",
811                                file: ::core::file!(),
812                                line: ::core::line!(),
813                                col: ::core::column!(),
814                                vtable: &(),
815                            };
816                        }
817                        impl<V> #crate_name::traits::DynInfo for Source<'_, V> {
818                            const VTABLE: &'static Self::VTable = <Self as #crate_name::traits::DynInfoType>::NULL_VTABLE;
819                        }
820
821                        #[allow(clippy::useless_transmute)]
822                        #crate_name::panic_failed_assert(
823                            (&&&__assert_expr).__marker(),
824                            unsafe { ::core::mem::transmute(#debug_lhs) },
825                            unsafe { ::core::mem::transmute(#debug_rhs) },
826                            unsafe { ::core::mem::transmute(#debug_cmp) },
827                            {
828                                use #crate_name::traits::DynInfo;
829                                (&&Source(&__assert_expr)).vtable()
830                            },
831                            #message,
832                        );
833                    }
834                }
835            }
836        }
837    };
838
839    outer_block.into()
840}