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));
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}