hax_frontend_exporter/utils/
error_macros.rs1macro_rules! format_with_context {
2 ($format_str:expr $(,$arg:expr)* $(; {$($x:expr),*})?) => {
3 format!(
4 concat!(
5 $format_str
6 $(, "\n\nContext:\n", $(concat!(" - ", stringify!($x), ": "), "{:#?}", "\n",)*)?
7 ),
8 $($arg,)*
9 $($($x,)*)?
10 )
11 };
12 ($($tt:tt)*) => {format!($($tt)*)};
13}
14
15mod internal_helpers {
16 macro_rules! _verb {
17 (fatal, $o:expr, $message:expr) => {
18 $o.struct_fatal($message)
19 };
20 (error, $o:expr, $message:expr) => {
21 $o.struct_err($message)
22 };
23 (warn, $o:expr, $message:expr) => {
24 $o.struct_warn($message)
25 };
26 }
27 macro_rules! _span_verb_base {
28 ($verb:ident, $s:ident, $span:expr, $message:expr) => {{
29 let backtrace = std::backtrace::Backtrace::capture();
30 eprintln!("{}", backtrace);
31 let mut builder = $crate::utils::_verb!($verb, $s.base().tcx.dcx(), $message);
32 if let Some(span) = $span {
33 builder.span(span.clone());
34 }
35 builder.code(rustc_errors::codes::ErrCode::MAX);
36 builder.note(
37 "⚠️ This is a bug in Hax's frontend.
38Please report this error to https://github.com/hacspec/hax/issues with some context (e.g. the current crate)!",
39 );
40 builder.emit()
41 }};
42 }
43
44 pub(crate) use _span_verb_base;
45 pub(crate) use _verb;
46}
47
48macro_rules! report {
49 ($verb:ident, $s:ident [$span:expr], $($tt:tt)*) => {
50 $crate::utils::_span_verb_base!($verb, $s, Some($span), $crate::utils::format_with_context!($($tt)*))
51 };
52 ($verb:ident, $s:ident, $($tt:tt)*) => {
53 $crate::utils::_span_verb_base!(
54 $verb,
55 $s,
56 $s.base().opt_def_id.map(|did| $s.base().tcx.def_span(did)),
57 $crate::utils::format_with_context!($($tt)*)
58 )
59 };
60}
61
62macro_rules! error { ($($tt:tt)*) => {$crate::utils::report!(error, $($tt)*)} }
63#[allow(unused_macros)]
64macro_rules! warning { ($($tt:tt)*) => {$crate::utils::report!(warn, $($tt)*)} }
65macro_rules! fatal { ($($tt:tt)*) => {$crate::utils::report!(fatal, $($tt)*)} }
66
67pub(crate) use format_with_context;
68pub(crate) use internal_helpers::_span_verb_base;
69pub(crate) use internal_helpers::_verb;
70pub(crate) use report;
71
72macro_rules! supposely_unreachable_message {
73 ($label:literal) => {
74 concat!(
75 "Supposely unreachable place in the Rust AST. The label is ",
76 stringify!($label),
77 ".\nThis error report happend because some assumption about the Rust AST was broken."
78 )
79 };
80}
81
82macro_rules! supposely_unreachable {
83 ($s:ident $([$span:expr])?, $label:literal $($tt:tt)*) => {
84 {
85 $crate::utils::error!($s$([$span])?, $crate::utils::supposely_unreachable_message!($label) $($tt)+)
86 }
87 };
88}
89macro_rules! supposely_unreachable_fatal {
90 ($s:ident $([$span:expr])?, $label:literal $($tt:tt)*) => {
91 $crate::utils::fatal!($s$([$span])?, $crate::utils::supposely_unreachable_message!($label) $($tt)+)
92 };
93}
94
95pub(crate) use error;
96pub(crate) use fatal;
97pub(crate) use supposely_unreachable;
98pub(crate) use supposely_unreachable_fatal;
99pub(crate) use supposely_unreachable_message;
100#[allow(unused_imports)]
101pub(crate) use warning;
102
103pub trait SExpect: Sized {
104 type Output;
105 fn s_expect<'tcx, S: crate::BaseState<'tcx>>(self, s: &S, message: &str) -> Self::Output;
106
107 fn s_unwrap<'tcx, S: crate::BaseState<'tcx>>(self, s: &S) -> Self::Output {
108 self.s_expect(s, "")
109 }
110}
111
112mod s_expect_impls {
113 use super::*;
114 struct Dummy;
115 impl std::fmt::Debug for Dummy {
116 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
117 write!(f, "...")
118 }
119 }
120
121 fn s_expect_error<'tcx>(
122 s: &impl crate::BaseState<'tcx>,
123 expected: impl std::fmt::Debug,
124 got: impl std::fmt::Debug,
125 message: &str,
126 ) -> ! {
127 fatal!(
128 s,
129 "s_expect: expected {:?}, got {:?}. {}",
130 expected,
131 got,
132 message
133 )
134 }
135
136 impl<T: std::fmt::Debug> SExpect for Option<T> {
137 type Output = T;
138 fn s_expect<'tcx, S: crate::BaseState<'tcx>>(self, s: &S, message: &str) -> Self::Output {
139 self.unwrap_or_else(|| s_expect_error(s, Some(Dummy), None::<()>, message))
140 }
141 }
142
143 impl<T: std::fmt::Debug, E: std::fmt::Debug> SExpect for Result<T, E> {
144 type Output = T;
145 fn s_expect<'tcx, S: crate::BaseState<'tcx>>(self, s: &S, message: &str) -> Self::Output {
146 self.unwrap_or_else(|e| s_expect_error(s, Ok::<_, ()>(Dummy), Err::<(), _>(e), message))
147 }
148 }
149}
150
151macro_rules! s_assert {
152 ($s:ident, $assertion:expr) => {{
153 if !($assertion) {
154 fatal!($s, "assertion failed: {}", stringify!($assertion))
155 }
156 }};
157}
158pub(crate) use s_assert;