1#![no_std]
2
3use core::fmt::{Debug, Formatter, Result};
4use core::marker::PhantomData;
5
6#[doc(hidden)]
7pub use equator_macro::assert as __assert_impl;
8
9#[macro_export]
10macro_rules! assert {
11 ($($tokens: tt)*) => {
12 $crate::__assert_impl!($crate, $($tokens)*)
13 };
14}
15
16#[macro_export]
17macro_rules! debug_assert {
18 ($($tokens: tt)*) => {
19 if cfg!(debug_assertions) {
20 $crate::__assert_impl!($crate, $($tokens)*)
21 }
22 };
23}
24
25#[derive(Copy, Clone)]
26#[doc(hidden)]
27pub struct Finalize<E, Line, Col, File> {
28 pub expr: E,
29 pub line: Line,
30 pub col: Col,
31 pub file: File,
32}
33
34#[doc(hidden)]
35pub mod atomic {
36 #[derive(Copy, Clone)]
37 pub struct EqExpr<Lhs, Rhs> {
38 pub lhs: Lhs,
39 pub rhs: Rhs,
40 }
41
42 #[derive(Copy, Clone)]
43 pub struct NeExpr<Lhs, Rhs> {
44 pub lhs: Lhs,
45 pub rhs: Rhs,
46 }
47
48 #[derive(Copy, Clone)]
49 pub struct LtExpr<Lhs, Rhs> {
50 pub lhs: Lhs,
51 pub rhs: Rhs,
52 }
53
54 #[derive(Copy, Clone)]
55 pub struct LeExpr<Lhs, Rhs> {
56 pub lhs: Lhs,
57 pub rhs: Rhs,
58 }
59
60 #[derive(Copy, Clone)]
61 pub struct GtExpr<Lhs, Rhs> {
62 pub lhs: Lhs,
63 pub rhs: Rhs,
64 }
65
66 #[derive(Copy, Clone)]
67 pub struct GeExpr<Lhs, Rhs> {
68 pub lhs: Lhs,
69 pub rhs: Rhs,
70 }
71}
72
73#[doc(hidden)]
74#[repr(transparent)]
75pub struct DebugWrapper<T>(T);
76#[doc(hidden)]
77#[repr(transparent)]
78pub struct NoDebugWrapper<T>(T);
79
80impl<Lhs: PartialEq<Rhs>, Rhs> PartialEq<DebugWrapper<Rhs>> for DebugWrapper<Lhs> {
81 #[inline(always)]
82 fn eq(&self, other: &DebugWrapper<Rhs>) -> bool {
83 self.0 == other.0
84 }
85}
86impl<Lhs: PartialEq<Rhs>, Rhs> PartialEq<DebugWrapper<Rhs>> for NoDebugWrapper<Lhs> {
87 #[inline(always)]
88 fn eq(&self, other: &DebugWrapper<Rhs>) -> bool {
89 self.0 == other.0
90 }
91}
92impl<Lhs: PartialEq<Rhs>, Rhs> PartialEq<NoDebugWrapper<Rhs>> for DebugWrapper<Lhs> {
93 #[inline(always)]
94 fn eq(&self, other: &NoDebugWrapper<Rhs>) -> bool {
95 self.0 == other.0
96 }
97}
98impl<Lhs: PartialEq<Rhs>, Rhs> PartialEq<NoDebugWrapper<Rhs>> for NoDebugWrapper<Lhs> {
99 #[inline(always)]
100 fn eq(&self, other: &NoDebugWrapper<Rhs>) -> bool {
101 self.0 == other.0
102 }
103}
104
105impl<Lhs: PartialOrd<Rhs>, Rhs> PartialOrd<DebugWrapper<Rhs>> for DebugWrapper<Lhs> {
106 #[inline(always)]
107 fn partial_cmp(&self, other: &DebugWrapper<Rhs>) -> Option<core::cmp::Ordering> {
108 self.0.partial_cmp(&other.0)
109 }
110}
111impl<Lhs: PartialOrd<Rhs>, Rhs> PartialOrd<DebugWrapper<Rhs>> for NoDebugWrapper<Lhs> {
112 #[inline(always)]
113 fn partial_cmp(&self, other: &DebugWrapper<Rhs>) -> Option<core::cmp::Ordering> {
114 self.0.partial_cmp(&other.0)
115 }
116}
117impl<Lhs: PartialOrd<Rhs>, Rhs> PartialOrd<NoDebugWrapper<Rhs>> for DebugWrapper<Lhs> {
118 #[inline(always)]
119 fn partial_cmp(&self, other: &NoDebugWrapper<Rhs>) -> Option<core::cmp::Ordering> {
120 self.0.partial_cmp(&other.0)
121 }
122}
123impl<Lhs: PartialOrd<Rhs>, Rhs> PartialOrd<NoDebugWrapper<Rhs>> for NoDebugWrapper<Lhs> {
124 #[inline(always)]
125 fn partial_cmp(&self, other: &NoDebugWrapper<Rhs>) -> Option<core::cmp::Ordering> {
126 self.0.partial_cmp(&other.0)
127 }
128}
129
130impl<T: Debug> Debug for DebugWrapper<T> {
131 #[inline(always)]
132 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
133 self.0.fmt(f)
134 }
135}
136impl<T> Debug for NoDebugWrapper<T> {
137 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
138 write!(
139 f,
140 "<object of type \"{}\" at address {:?}>",
141 core::any::type_name::<T>(),
142 self as *const _ as *const ()
143 )
144 }
145}
146
147#[doc(hidden)]
148pub struct DebugWrap;
149#[doc(hidden)]
150pub struct NoDebugWrap;
151
152impl DebugWrap {
153 #[inline(always)]
154 pub fn do_wrap<T: Debug>(self, value: &T) -> &DebugWrapper<T> {
155 unsafe { &*(value as *const T as *const _) }
156 }
157}
158impl NoDebugWrap {
159 #[inline(always)]
160 pub fn do_wrap<T>(self, value: &T) -> &NoDebugWrapper<T> {
161 unsafe { &*(value as *const T as *const _) }
162 }
163}
164
165#[doc(hidden)]
166pub struct Wrapper<T>(pub T);
167
168impl<T: Debug> TryDebugWrap for &Wrapper<T> {
169 type Wrap = DebugWrap;
170
171 #[inline]
172 fn wrap(&self) -> Self::Wrap {
173 DebugWrap
174 }
175}
176impl<T> TryDebugWrap for Wrapper<T> {
177 type Wrap = NoDebugWrap;
178
179 #[inline]
180 fn wrap(&self) -> Self::Wrap {
181 NoDebugWrap
182 }
183}
184
185#[doc(hidden)]
186pub trait TryDebugWrap {
187 type Wrap;
188 fn wrap(&self) -> Self::Wrap;
189}
190
191#[doc(hidden)]
192pub mod expr {
193 #[derive(Copy, Clone)]
194 pub struct AndExpr<Lhs, Rhs> {
195 pub lhs: Lhs,
196 pub rhs: Rhs,
197 }
198
199 #[derive(Copy, Clone)]
200 pub struct OrExpr<Lhs, Rhs> {
201 pub lhs: Lhs,
202 pub rhs: Rhs,
203 }
204}
205
206use atomic::*;
207use expr::*;
208
209#[doc(hidden)]
210pub type PtrToDebug = for<'a> unsafe fn(*const ()) -> &'static dyn Debug;
211
212unsafe fn as_debug_vptr_impl<T: Debug>(ptr: *const ()) -> &'static dyn Debug {
213 core::mem::transmute::<&'_ dyn Debug, &'static dyn Debug>((&*(ptr as *const T)) as &dyn Debug)
214}
215
216#[doc(hidden)]
217#[inline(always)]
218pub const fn as_debug_vptr<T: Debug>() -> for<'a> unsafe fn(*const ()) -> &'static dyn Debug {
219 as_debug_vptr_impl::<T>
220}
221
222#[doc(hidden)]
223pub trait FromParts<'a> {
224 type Result;
225 type Source;
226 type VTable;
227 type Debug;
228 fn from_parts(
229 result: Self::Result,
230 source: &'a Self::Source,
231 vtable: &'a Self::VTable,
232 debug: &'a Self::Debug,
233 message: core::fmt::Arguments<'a>,
234 ) -> Self;
235}
236impl<'a, Result, Source, Debug, VTable> FromParts<'a>
237 for DebugMessage<'a, Result, Source, VTable, Debug>
238{
239 type Result = Result;
240 type Source = Source;
241 type Debug = Debug;
242 type VTable = VTable;
243 #[inline(always)]
244 fn from_parts(
245 result: Result,
246 source: &'a Source,
247 vtable: &'a VTable,
248 debug: &'a Debug,
249 message: core::fmt::Arguments<'a>,
250 ) -> Self {
251 Self {
252 result,
253 source,
254 debug,
255 vtable,
256 message,
257 }
258 }
259}
260
261#[doc(hidden)]
262pub struct DebugMessage<'a, Result, Source, VTable, Debug> {
263 pub result: Result,
264 pub source: &'a Source,
265 pub debug: &'a Debug,
266 pub vtable: &'a VTable,
267 pub message: core::fmt::Arguments<'a>,
268}
269
270impl Debug for DebugMessage<'_, bool, &'static str, (), bool> {
271 fn fmt(&self, f: &mut Formatter) -> Result {
272 let source = &self.source;
273 let debug = &self.debug;
274 write!(f, "Assertion failed: {source}\n")?;
275 write!(f, "- {source} = {debug:#?}")
276 }
277}
278
279impl Debug
280 for DebugMessage<
281 '_,
282 bool,
283 EqExpr<&'static str, &'static str>,
284 (PtrToDebug, PtrToDebug),
285 EqExpr<*const (), *const ()>,
286 >
287{
288 fn fmt(&self, f: &mut Formatter) -> Result {
289 let lhs_source = &self.source.lhs;
290 let rhs_source = &self.source.rhs;
291 let lhs = unsafe { self.vtable.0(self.debug.lhs) };
292 let rhs = unsafe { self.vtable.1(self.debug.rhs) };
293 write!(f, "Assertion failed: {lhs_source} == {rhs_source}\n")?;
294 write!(f, "- {lhs_source} = {lhs:#?}\n")?;
295 write!(f, "- {rhs_source} = {rhs:#?}")
296 }
297}
298impl Debug
299 for DebugMessage<
300 '_,
301 bool,
302 NeExpr<&'static str, &'static str>,
303 (PtrToDebug, PtrToDebug),
304 NeExpr<*const (), *const ()>,
305 >
306{
307 fn fmt(&self, f: &mut Formatter) -> Result {
308 let lhs_source = &self.source.lhs;
309 let rhs_source = &self.source.rhs;
310 let lhs = unsafe { self.vtable.0(self.debug.lhs) };
311 let rhs = unsafe { self.vtable.1(self.debug.rhs) };
312 write!(f, "Assertion failed: {lhs_source} != {rhs_source}\n")?;
313 write!(f, "- {lhs_source} = {lhs:#?}\n")?;
314 write!(f, "- {rhs_source} = {rhs:#?}")
315 }
316}
317impl Debug
318 for DebugMessage<
319 '_,
320 bool,
321 LtExpr<&'static str, &'static str>,
322 (PtrToDebug, PtrToDebug),
323 LtExpr<*const (), *const ()>,
324 >
325{
326 fn fmt(&self, f: &mut Formatter) -> Result {
327 let lhs_source = &self.source.lhs;
328 let rhs_source = &self.source.rhs;
329 let lhs = unsafe { self.vtable.0(self.debug.lhs) };
330 let rhs = unsafe { self.vtable.1(self.debug.rhs) };
331 write!(f, "Assertion failed: {lhs_source} < {rhs_source}\n")?;
332 write!(f, "- {lhs_source} = {lhs:#?}\n")?;
333 write!(f, "- {rhs_source} = {rhs:#?}")
334 }
335}
336impl Debug
337 for DebugMessage<
338 '_,
339 bool,
340 LeExpr<&'static str, &'static str>,
341 (PtrToDebug, PtrToDebug),
342 LeExpr<*const (), *const ()>,
343 >
344{
345 fn fmt(&self, f: &mut Formatter) -> Result {
346 let lhs_source = &self.source.lhs;
347 let rhs_source = &self.source.rhs;
348 let lhs = unsafe { self.vtable.0(self.debug.lhs) };
349 let rhs = unsafe { self.vtable.1(self.debug.rhs) };
350 write!(f, "Assertion failed: {lhs_source} <= {rhs_source}\n")?;
351 write!(f, "- {lhs_source} = {lhs:#?}\n")?;
352 write!(f, "- {rhs_source} = {rhs:#?}")
353 }
354}
355impl Debug
356 for DebugMessage<
357 '_,
358 bool,
359 GtExpr<&'static str, &'static str>,
360 (PtrToDebug, PtrToDebug),
361 GtExpr<*const (), *const ()>,
362 >
363{
364 fn fmt(&self, f: &mut Formatter) -> Result {
365 let lhs_source = &self.source.lhs;
366 let rhs_source = &self.source.rhs;
367 let lhs = unsafe { self.vtable.0(self.debug.lhs) };
368 let rhs = unsafe { self.vtable.1(self.debug.rhs) };
369 write!(f, "Assertion failed: {lhs_source} > {rhs_source}\n")?;
370 write!(f, "- {lhs_source} = {lhs:#?}\n")?;
371 write!(f, "- {rhs_source} = {rhs:#?}")
372 }
373}
374impl Debug
375 for DebugMessage<
376 '_,
377 bool,
378 GeExpr<&'static str, &'static str>,
379 (PtrToDebug, PtrToDebug),
380 GeExpr<*const (), *const ()>,
381 >
382{
383 fn fmt(&self, f: &mut Formatter) -> Result {
384 let lhs_source = &self.source.lhs;
385 let rhs_source = &self.source.rhs;
386 let lhs = unsafe { self.vtable.0(self.debug.lhs) };
387 let rhs = unsafe { self.vtable.1(self.debug.rhs) };
388 write!(f, "Assertion failed: {lhs_source} >= {rhs_source}\n")?;
389 write!(f, "- {lhs_source} = {lhs:#?}\n")?;
390 write!(f, "- {rhs_source} = {rhs:#?}")
391 }
392}
393
394impl<
395 'a,
396 LhsResult: Eval,
397 RhsResult: Eval,
398 LhsSource,
399 RhsSource,
400 LhsVTable,
401 RhsVTable,
402 LhsDebug,
403 RhsDebug,
404 > Debug
405 for DebugMessage<
406 'a,
407 AndExpr<LhsResult, RhsResult>,
408 AndExpr<LhsSource, RhsSource>,
409 (&'static LhsVTable, &'static RhsVTable),
410 AndExpr<LhsDebug, RhsDebug>,
411 >
412where
413 DebugMessage<'a, LhsResult, LhsSource, LhsVTable, LhsDebug>: Debug,
414 DebugMessage<'a, RhsResult, RhsSource, RhsVTable, RhsDebug>: Debug,
415{
416 fn fmt(&self, f: &mut Formatter) -> Result {
417 let lhs = DebugMessage {
418 result: self.result.lhs,
419 source: &self.source.lhs,
420 vtable: self.vtable.0,
421 debug: &self.debug.lhs,
422 message: core::format_args!(""),
423 };
424 let rhs = DebugMessage {
425 result: self.result.rhs,
426 source: &self.source.rhs,
427 vtable: self.vtable.1,
428 debug: &self.debug.rhs,
429 message: core::format_args!(""),
430 };
431
432 let lhs_eval = lhs.result.eval();
433 let rhs_eval = rhs.result.eval();
434 if !(lhs_eval && rhs_eval) {
435 if !lhs_eval {
436 lhs.fmt(f)?;
437 if !rhs_eval {
438 f.write_str("\n")?;
439 }
440 }
441 if !rhs_eval {
442 rhs.fmt(f)?;
443 }
444 }
445 Ok(())
446 }
447}
448
449impl<
450 'a,
451 LhsResult: Eval,
452 RhsResult: Eval,
453 LhsSource,
454 RhsSource,
455 LhsVTable,
456 RhsVTable,
457 LhsDebug,
458 RhsDebug,
459 > Debug
460 for DebugMessage<
461 'a,
462 OrExpr<LhsResult, RhsResult>,
463 OrExpr<LhsSource, RhsSource>,
464 (&'static LhsVTable, &'static RhsVTable),
465 OrExpr<LhsDebug, RhsDebug>,
466 >
467where
468 DebugMessage<'a, LhsResult, LhsSource, LhsVTable, LhsDebug>: Debug,
469 DebugMessage<'a, RhsResult, RhsSource, RhsVTable, RhsDebug>: Debug,
470{
471 fn fmt(&self, f: &mut Formatter) -> Result {
472 let lhs = DebugMessage {
473 result: self.result.lhs,
474 source: &self.source.lhs,
475 vtable: self.vtable.0,
476 debug: &self.debug.lhs,
477 message: core::format_args!(""),
478 };
479 let rhs = DebugMessage {
480 result: self.result.rhs,
481 source: &self.source.rhs,
482 vtable: self.vtable.1,
483 debug: &self.debug.rhs,
484 message: core::format_args!(""),
485 };
486
487 let lhs_eval = lhs.result.eval();
488 let rhs_eval = rhs.result.eval();
489 if !(lhs_eval || rhs_eval) {
490 if !lhs_eval {
491 lhs.fmt(f)?;
492 if !rhs_eval {
493 f.write_str("\n")?;
494 }
495 }
496 if !rhs_eval {
497 rhs.fmt(f)?;
498 }
499 }
500 Ok(())
501 }
502}
503
504impl<'a, Result: Copy, Source, VTable, Debug> core::fmt::Debug
505 for DebugMessage<
506 'a,
507 Result,
508 Finalize<Source, u32, u32, &'static str>,
509 VTable,
510 Finalize<Debug, (), (), ()>,
511 >
512where
513 DebugMessage<'a, Result, Source, VTable, Debug>: core::fmt::Debug,
514{
515 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
516 let inner = DebugMessage {
517 result: self.result,
518 source: &self.source.expr,
519 debug: &self.debug.expr,
520 vtable: self.vtable,
521 message: format_args!(""),
522 };
523 let message = self.message;
524 write!(
525 f,
526 "Assertion failed at {}:{}:{}\n",
527 self.source.file, self.source.line, self.source.col
528 )?;
529 match message.as_str() {
530 Some(s) if s.len() == 0 => {}
531 _ => write!(f, "{message:#?}\n")?,
532 }
533 inner.fmt(f)
534 }
535}
536
537#[doc(hidden)]
538pub trait Eval: Copy {
539 fn eval(&self) -> bool;
540}
541
542impl Eval for bool {
543 #[inline(always)]
544 fn eval(&self) -> bool {
545 *self
546 }
547}
548impl<Lhs: Eval, Rhs: Eval> Eval for AndExpr<Lhs, Rhs> {
549 #[inline(always)]
550 fn eval(&self) -> bool {
551 self.lhs.eval() && self.rhs.eval()
552 }
553}
554impl<Lhs: Eval, Rhs: Eval> Eval for OrExpr<Lhs, Rhs> {
555 #[inline(always)]
556 fn eval(&self) -> bool {
557 self.lhs.eval() || self.rhs.eval()
558 }
559}
560
561#[doc(hidden)]
562pub trait DynDebug {
563 type VTable: Copy + 'static;
564 const VTABLE: &'static Self::VTable;
565}
566
567impl DynDebug for bool {
568 type VTable = ();
569 const VTABLE: &'static Self::VTable = &();
570}
571impl<Lhs: Debug, Rhs: Debug> DynDebug for EqExpr<&Lhs, &Rhs> {
572 type VTable = (PtrToDebug, PtrToDebug);
573 const VTABLE: &'static Self::VTable = &(as_debug_vptr::<Lhs>(), as_debug_vptr::<Rhs>());
574}
575impl<Lhs: Debug, Rhs: Debug> DynDebug for NeExpr<&Lhs, &Rhs> {
576 type VTable = (PtrToDebug, PtrToDebug);
577 const VTABLE: &'static Self::VTable = &(as_debug_vptr::<Lhs>(), as_debug_vptr::<Rhs>());
578}
579impl<Lhs: Debug, Rhs: Debug> DynDebug for LtExpr<&Lhs, &Rhs> {
580 type VTable = (PtrToDebug, PtrToDebug);
581 const VTABLE: &'static Self::VTable = &(as_debug_vptr::<Lhs>(), as_debug_vptr::<Rhs>());
582}
583impl<Lhs: Debug, Rhs: Debug> DynDebug for LeExpr<&Lhs, &Rhs> {
584 type VTable = (PtrToDebug, PtrToDebug);
585 const VTABLE: &'static Self::VTable = &(as_debug_vptr::<Lhs>(), as_debug_vptr::<Rhs>());
586}
587impl<Lhs: Debug, Rhs: Debug> DynDebug for GeExpr<&Lhs, &Rhs> {
588 type VTable = (PtrToDebug, PtrToDebug);
589 const VTABLE: &'static Self::VTable = &(as_debug_vptr::<Lhs>(), as_debug_vptr::<Rhs>());
590}
591impl<Lhs: Debug, Rhs: Debug> DynDebug for GtExpr<&Lhs, &Rhs> {
592 type VTable = (PtrToDebug, PtrToDebug);
593 const VTABLE: &'static Self::VTable = &(as_debug_vptr::<Lhs>(), as_debug_vptr::<Rhs>());
594}
595impl<Lhs: DynDebug, Rhs: DynDebug> DynDebug for AndExpr<Lhs, Rhs> {
596 type VTable = (&'static Lhs::VTable, &'static Rhs::VTable);
597 const VTABLE: &'static Self::VTable = &(Lhs::VTABLE, Rhs::VTABLE);
598}
599impl<Lhs: DynDebug, Rhs: DynDebug> DynDebug for OrExpr<Lhs, Rhs> {
600 type VTable = (&'static Lhs::VTable, &'static Rhs::VTable);
601 const VTABLE: &'static Self::VTable = &(Lhs::VTABLE, Rhs::VTABLE);
602}
603impl<E: DynDebug> DynDebug for Finalize<E, (), (), ()> {
604 type VTable = E::VTable;
605 const VTABLE: &'static Self::VTable = E::VTABLE;
606}
607
608#[doc(hidden)]
609pub trait Expr {
610 type Result: Eval;
611
612 fn eval_expr(&self) -> bool;
613 fn result(&self) -> Self::Result;
614}
615
616impl Expr for bool {
617 type Result = bool;
618
619 #[inline(always)]
620 fn eval_expr(&self) -> bool {
621 *self
622 }
623
624 #[inline(always)]
625 fn result(&self) -> Self::Result {
626 *self
627 }
628}
629
630impl<Lhs: PartialEq<Rhs>, Rhs> Expr for EqExpr<Lhs, Rhs> {
631 type Result = bool;
632
633 #[inline(always)]
634 fn eval_expr(&self) -> bool {
635 self.result()
636 }
637
638 #[inline(always)]
639 fn result(&self) -> Self::Result {
640 self.lhs == self.rhs
641 }
642}
643
644impl<Lhs: PartialEq<Rhs>, Rhs> Expr for NeExpr<Lhs, Rhs> {
645 type Result = bool;
646
647 #[inline(always)]
648 fn eval_expr(&self) -> bool {
649 self.result()
650 }
651
652 #[inline(always)]
653 fn result(&self) -> Self::Result {
654 self.lhs != self.rhs
655 }
656}
657
658impl<Lhs: PartialOrd<Rhs>, Rhs> Expr for LtExpr<Lhs, Rhs> {
659 type Result = bool;
660
661 #[inline(always)]
662 fn eval_expr(&self) -> bool {
663 self.result()
664 }
665
666 #[inline(always)]
667 fn result(&self) -> Self::Result {
668 self.lhs < self.rhs
669 }
670}
671
672impl<Lhs: PartialOrd<Rhs>, Rhs> Expr for LeExpr<Lhs, Rhs> {
673 type Result = bool;
674
675 #[inline(always)]
676 fn eval_expr(&self) -> bool {
677 self.result()
678 }
679
680 #[inline(always)]
681 fn result(&self) -> Self::Result {
682 self.lhs <= self.rhs
683 }
684}
685
686impl<Lhs: PartialOrd<Rhs>, Rhs> Expr for GtExpr<Lhs, Rhs> {
687 type Result = bool;
688
689 #[inline(always)]
690 fn eval_expr(&self) -> bool {
691 self.result()
692 }
693
694 #[inline(always)]
695 fn result(&self) -> Self::Result {
696 self.lhs > self.rhs
697 }
698}
699
700impl<Lhs: PartialOrd<Rhs>, Rhs> Expr for GeExpr<Lhs, Rhs> {
701 type Result = bool;
702
703 #[inline(always)]
704 fn eval_expr(&self) -> bool {
705 self.result()
706 }
707
708 #[inline(always)]
709 fn result(&self) -> Self::Result {
710 self.lhs >= self.rhs
711 }
712}
713
714#[inline(always)]
715#[doc(hidden)]
716pub fn marker<T>(_: &T) -> PhantomData<T> {
717 PhantomData
718}
719
720impl<Lhs: Expr, Rhs: Expr> Expr for AndExpr<Lhs, Rhs> {
721 type Result = AndExpr<Lhs::Result, Rhs::Result>;
722
723 #[inline(always)]
724 fn eval_expr(&self) -> bool {
725 self.lhs.eval_expr() && self.rhs.eval_expr()
726 }
727
728 #[inline(always)]
729 fn result(&self) -> Self::Result {
730 AndExpr {
731 lhs: self.lhs.result(),
732 rhs: self.rhs.result(),
733 }
734 }
735}
736
737impl<Lhs: Expr, Rhs: Expr> Expr for OrExpr<Lhs, Rhs> {
738 type Result = OrExpr<Lhs::Result, Rhs::Result>;
739
740 #[inline(always)]
741 fn eval_expr(&self) -> bool {
742 self.lhs.eval_expr() || self.rhs.eval_expr()
743 }
744
745 #[inline(always)]
746 fn result(&self) -> Self::Result {
747 OrExpr {
748 lhs: self.lhs.result(),
749 rhs: self.rhs.result(),
750 }
751 }
752}
753
754impl<E: Expr> Expr for Finalize<E, (), (), ()> {
755 type Result = E::Result;
756
757 #[inline(always)]
758 fn eval_expr(&self) -> bool {
759 self.expr.eval_expr()
760 }
761
762 #[inline(always)]
763 fn result(&self) -> Self::Result {
764 self.expr.result()
765 }
766}
767
768impl<E> Expr for &Finalize<E, (), (), ()> {
769 type Result = bool;
770
771 #[inline(always)]
772 fn eval_expr(&self) -> bool {
773 unimplemented!()
774 }
775
776 #[inline(always)]
777 fn result(&self) -> Self::Result {
778 unimplemented!()
779 }
780}
781
782impl<E: Expr> Expr for &&Finalize<E, (), (), ()> {
783 type Result = E::Result;
784
785 #[inline(always)]
786 fn eval_expr(&self) -> bool {
787 self.expr.eval_expr()
788 }
789
790 #[inline(always)]
791 fn result(&self) -> Self::Result {
792 self.expr.result()
793 }
794}
795
796#[inline(always)]
797#[doc(hidden)]
798pub const fn vtable_for<T: DynDebug>(_: &T) -> &'static T::VTable {
799 T::VTABLE
800}
801
802#[cold]
803#[inline(never)]
804#[doc(hidden)]
805#[track_caller]
806pub fn panic_failed_assert<'a, M: core::fmt::Debug + FromParts<'a>>(
807 __marker: PhantomData<M>,
808 result: M::Result,
809 source: &'a M::Source,
810 vtable: &'a M::VTable,
811 debug: &'a M::Debug,
812) -> ! {
813 panic!(
814 "{:#?}",
815 M::from_parts(result, source, vtable, debug, core::format_args!(""))
816 )
817}
818
819#[cold]
820#[inline(never)]
821#[doc(hidden)]
822#[track_caller]
823pub fn panic_failed_assert_with_message<'a, M: core::fmt::Debug + FromParts<'a>>(
824 __marker: PhantomData<M>,
825 message: core::fmt::Arguments<'a>,
826 result: M::Result,
827 source: &'a M::Source,
828 vtable: &'a M::VTable,
829 debug: &'a M::Debug,
830) -> ! {
831 panic!(
832 "{:#?}",
833 M::from_parts(result, source, vtable, debug, message)
834 )
835}
836
837#[cfg(test)]
838mod tests {
839 use super::*;
840
841 macro_rules! test_expr {
842 ($e: expr, $debug: expr, $source: expr $(,)?) => {{
843 let e = $e;
844 if !e.eval_expr() {
845 let message = $crate::DebugMessage {
846 result: e.result(),
847 source: $source,
848 vtable: vtable_for(&e),
849 debug: $debug,
850 message: format_args!(""),
851 };
852 let __marker = $crate::marker(&message);
853 $crate::panic_failed_assert(
854 __marker,
855 message.result,
856 message.source,
857 message.vtable,
858 message.debug,
859 );
860 }
861 }};
862 }
863
864 #[test]
865 #[should_panic]
866 fn test_bool_expr() {
867 test_expr!(false, &false, &"oops");
868 }
869
870 #[test]
871 #[should_panic]
872 fn test_eq_expr() {
873 test_expr!(
874 EqExpr {
875 lhs: &0i32,
876 rhs: &1i32,
877 },
878 &EqExpr {
879 lhs: (&0i32) as *const _ as *const (),
880 rhs: (&1i32) as *const _ as *const (),
881 },
882 &EqExpr { lhs: "a", rhs: "b" },
883 );
884 }
885
886 #[test]
887 #[should_panic]
888 fn test_and_expr() {
889 test_expr!(
890 AndExpr {
891 lhs: false,
892 rhs: OrExpr {
893 lhs: EqExpr { lhs: &4, rhs: &4 },
894 rhs: EqExpr {
895 lhs: &0i32,
896 rhs: &1i32,
897 },
898 },
899 },
900 &AndExpr {
901 lhs: false,
902 rhs: OrExpr {
903 lhs: EqExpr {
904 lhs: (&4i32) as *const _ as _,
905 rhs: (&4i32) as *const _ as _,
906 },
907 rhs: EqExpr {
908 lhs: (&0i32) as *const _ as _,
909 rhs: (&1i32) as *const _ as _,
910 },
911 },
912 },
913 &AndExpr {
914 lhs: "some_bool",
915 rhs: OrExpr {
916 lhs: EqExpr { lhs: "c", rhs: "d" },
917 rhs: EqExpr { lhs: "a", rhs: "b" },
918 },
919 },
920 );
921 }
922
923 mod macro_export {
924 use super::*;
925
926 #[test]
927 #[should_panic]
928 fn test_assert() {
929 assert!(false);
930 }
931
932 #[cfg(not(debug_assertions))]
933 #[test]
934 fn test_debug_assert() {
935 debug_assert!(false);
936 }
937
938 #[cfg(debug_assertions)]
939 #[test]
940 #[should_panic]
941 fn test_debug_assert() {
942 debug_assert!(false);
943 }
944 }
945}