Skip to main content

conjure_cp_core/
bug.rs

1use std::fmt::Display;
2
3/// Triggers a panic with a detailed bug report message, while ensuring the panic is ignored in coverage reports.
4///
5/// This macro is useful in situations where an unreachable code path is hit or when a bug occurs.
6///
7/// # Parameters
8///
9/// - `msg`: A string expression describing the cause of the panic or bug.
10///
11/// ```
12#[macro_export]
13macro_rules! bug {
14    ($msg:expr)=> {
15        $crate::bug!($msg,)
16    };
17
18    ($msg:expr, $($arg:tt)*) => {{
19        let formatted_msg = format!($msg, $($arg)*);
20        let full_message = format!(
21            r#"
22This should never happen, sorry!
23
24However, it did happen, so it must be a bug. Please report it to us!
25
26Conjure Oxide is actively developed and maintained. We will get back to you as soon as possible.
27
28You can help us by providing a minimal failing example.
29
30Issue tracker: http://github.com/conjure-cp/conjure-oxide/issues
31
32version: {}
33location: {}:{}:{}
34
35{}
36"#, git_version::git_version!(),file!(),module_path!(),line!(), &formatted_msg);
37
38        panic!("{}", full_message);
39    }};
40}
41
42/// Like [assert!], but formats the error message using [bug!]
43#[macro_export]
44macro_rules! bug_assert {
45    ($cond:expr, $msg:expr, $($arg:tt)*) => {
46        if !$cond {
47            let formatted_msg = format!($msg, $($arg)*);
48            $crate::bug!("assertion failed: {}\n{}", stringify!($cond), formatted_msg);
49        }
50    };
51
52    ($cond:expr, $msg:expr) => {
53        if !$cond {
54            $crate::bug!("assertion failed: {}\n{}", stringify!($cond), $msg);
55        }
56    };
57
58    ($cond:expr) => {
59        if !$cond {
60            $crate::bug!("assertion failed: {}", stringify!($cond));
61        }
62    };
63}
64
65/// Like [assert_eq!], but formats the error message using [bug!]
66#[macro_export]
67macro_rules! bug_assert_eq {
68    ($left:expr, $right:expr, $msg:expr, $($arg:tt)*) => {
69        if &$left != &$right {
70            let formatted_msg = format!($msg, $($arg)*);
71            $crate::bug!(
72                "assertion failed: {} != {}\n{}",
73                stringify!($left),
74                stringify!($right),
75                formatted_msg
76            );
77        }
78    };
79
80    ($left:expr, $right:expr, $msg:expr) => {
81        $crate::bug_assert_eq!($left, $right, $msg,);
82    };
83
84    ($left:expr, $right:expr) => {
85        if &$left != &$right {
86            $crate::bug!(
87                "assertion failed: {} != {}",
88                stringify!($left),
89                stringify!($right)
90            );
91        }
92    };
93}
94
95pub trait UnwrapOrBug {
96    type Output;
97    fn unwrap_or_bug(self) -> Self::Output;
98}
99
100impl<T, E: Display> UnwrapOrBug for Result<T, E> {
101    type Output = T;
102    fn unwrap_or_bug(self) -> Self::Output {
103        self.unwrap_or_else(|e| bug!("error: {}", e))
104    }
105}
106
107impl<T> UnwrapOrBug for Option<T> {
108    type Output = T;
109    fn unwrap_or_bug(self) -> Self::Output {
110        self.unwrap_or_else(|| bug!("expected a value, but got None"))
111    }
112}