1 //! Macro definitions and the private runtime functions used in their generated
2 //! code.
3 
4 // Items used by macro-generated code.
5 pub use core::format_args;
6 pub use core::result::Result::Err;
7 
8 use super::{Error, OutOfMemory};
9 use core::fmt::{self, write};
10 use std_alloc::string::String;
11 
12 /// Construct an [`Error`] via string formatting or another error.
13 ///
14 /// Like `anyhow::format_err!` or `anyhow::anyhow!` but for
15 /// [`wasmtime::Error`](Error).
16 ///
17 /// # String Formatting
18 ///
19 /// When a string literal is the first argument, it is interpreted as a format
20 /// string template and the rest of the arguments are format arguments:
21 ///
22 /// ```
23 /// # use wasmtime_internal_core::error as wasmtime;
24 /// use wasmtime::{format_err, Error};
25 ///
26 /// let x = 42;
27 /// let error: Error = format_err!("x is {x}");
28 /// assert_eq!(error.to_string(), "x is 42");
29 ///
30 /// let error: Error = format_err!("x / 2 is {}", x / 2);
31 /// assert_eq!(error.to_string(), "x / 2 is 21");
32 ///
33 /// let error: Error = format_err!("x + 1 is {y}", y = x + 1);
34 /// assert_eq!(error.to_string(), "x + 1 is 43");
35 /// ```
36 ///
37 /// # From Another Error
38 ///
39 /// When a string literal is not the first argument, then it is treated as a
40 /// foreign error and is converted into an [`Error`]. The argument
41 /// must be of a type that can be passed to either [`Error::new`] or
42 /// [`Error::msg`].
43 ///
44 /// ```
45 /// # fn _foo() {
46 /// #![cfg(feature = "std")]
47 /// # use wasmtime_internal_core::error as wasmtime;
48 /// use std::fmt;
49 /// use wasmtime::{format_err, Error};
50 ///
51 /// #[derive(Debug)]
52 /// struct SomeOtherError(u32);
53 ///
54 /// impl fmt::Display for SomeOtherError {
55 ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 ///         write!(f, "some other error (code {})", self.0)
57 ///     }
58 /// }
59 ///
60 /// impl std::error::Error for SomeOtherError {}
61 ///
62 /// let error: Error = format_err!(SomeOtherError(36));
63 /// assert!(error.is::<SomeOtherError>());
64 /// assert_eq!(error.to_string(), "some other error (code 36)");
65 /// # }
66 /// ```
67 ///
68 /// # From an `anyhow::Error`
69 ///
70 /// The `format_err!` macro can always convert an `anyhow::Error` into a
71 /// `wasmtime::Error`, but when the `"anyhow"` cargo feature is enabled the
72 /// resulting error will also return true for
73 /// [`error.is::<anyhow::Error>()`](Error::is) invocations.
74 ///
75 /// ```
76 /// # fn _foo() {
77 /// #![cfg(feature = "anyhow")]
78 /// # use wasmtime_internal_core::error as wasmtime;
79 /// use wasmtime::format_err;
80 ///
81 /// let anyhow_error: anyhow::Error = anyhow::anyhow!("aw crap");
82 /// let wasmtime_error: wasmtime::Error = format_err!(anyhow_error);
83 /// assert!(wasmtime_error.is::<anyhow::Error>());
84 /// # }
85 /// ```
86 #[macro_export]
87 macro_rules! format_err {
88     // Format-style invocation without explicit format arguments.
89     ( $message:literal $(,)? ) => {
90         $crate::error::Error::from_format_args($crate::error::macros::format_args!($message))
91     };
92 
93     // Format-style invocation with explicit format arguments.
94     ( $message:literal , $( $args:tt )* ) => {
95         $crate::error::Error::from_format_args($crate::error::macros::format_args!($message , $( $args )* ))
96     };
97 
98     // Do either `Error::new($error)` or `Error::msg($error)` depending on
99     // whether `$error` implements `core::error::Error` or not.
100     ( $error:expr $(,)? ) => {{
101         use $crate::error::macros::ctor_specialization::*;
102         let error = $error;
103         (&&&error).wasmtime_error_choose_ctor().construct(error)
104     }};
105 }
106 
107 /// Identical to the [`format_err!`] macro.
108 ///
109 /// This is provided for API compatibility with the `anyhow` crate, but you
110 /// should prefer using `format_err!` instead.
111 #[macro_export]
112 #[deprecated = "Use `format_err!(...)` instead"]
113 macro_rules! anyhow {
114     ( $( $args:tt )* ) => {
115         $crate::error::format_err!( $( $args )* )
116     };
117 }
118 
119 /// Early exit from the current function with an error.
120 ///
121 /// This helper is equivalent to `return Err(format_err!(...))`.
122 ///
123 /// See the docs for the [`format_err!`] macro for details on
124 /// the kinds of errors that can be constructed.
125 ///
126 /// Like `anyhow::bail!` but for [`wasmtime::Error`](Error).
127 ///
128 /// # Example
129 ///
130 /// ```
131 /// # use wasmtime_internal_core::error as wasmtime;
132 /// use wasmtime::{bail, Result};
133 ///
134 /// fn error_on_none(option: Option<u32>) -> Result<u32> {
135 ///     match option {
136 ///         None => bail!("`error_on_none` got `None`!"),
137 ///         Some(x) => Ok(x),
138 ///     }
139 /// }
140 ///
141 /// let x = error_on_none(Some(42)).unwrap();
142 /// assert_eq!(x, 42);
143 ///
144 /// let error = error_on_none(None).unwrap_err();
145 /// assert_eq!(
146 ///     error.to_string(),
147 ///     "`error_on_none` got `None`!",
148 /// );
149 /// ```
150 #[macro_export]
151 macro_rules! bail {
152     ( $($args:tt)* ) => {{
153         return $crate::error::macros::Err($crate::error::format_err!( $( $args )* ));
154     }};
155 }
156 
157 /// Ensure that a condition holds true, or else early exit from the current
158 /// function with an error.
159 ///
160 /// `ensure!(condition, ...)` is equivalent to the following:
161 ///
162 /// ```ignore
163 /// if !condition {
164 ///     return Err(format_err!(...));
165 /// }
166 /// ```
167 ///
168 /// Like `anyhow::ensure!` but for [`wasmtime::Error`](Error).
169 ///
170 /// # Example
171 ///
172 /// ```rust
173 /// # use wasmtime_internal_core::error as wasmtime;
174 /// use wasmtime::{ensure, Result};
175 ///
176 /// fn checked_div(a: u32, b: u32) -> Result<u32> {
177 ///     ensure!(b != 0, "cannot divide by zero: {a} / {b}");
178 ///     Ok(a / b)
179 /// }
180 ///
181 /// let x = checked_div(6, 2).unwrap();
182 /// assert_eq!(x, 3);
183 ///
184 /// let error = checked_div(9, 0).unwrap_err();
185 /// assert_eq!(
186 ///     error.to_string(),
187 ///     "cannot divide by zero: 9 / 0",
188 /// );
189 /// ```
190 #[macro_export]
191 macro_rules! ensure {
192     ( $condition:expr ) => {{
193         $crate::error::ensure!($condition, concat!("Condition failed: `", stringify!($condition), "`"))
194     }};
195 
196     ( $condition:expr , $( $args:tt )* ) => {{
197         if $crate::error::macros::ensure::not($condition) {
198             $crate::error::bail!( $( $args )* );
199         }
200     }};
201 }
202 
203 /// We don't have specialization in stable Rust, so do a poor-person's
204 /// equivalent by hacking Rust's method name resolution and auto-deref. Given
205 /// that we have `n` versions of the "same" method, we do the following:
206 ///
207 /// * We define `n` different traits, which each define the same trait method
208 ///   name. The method need not have the same type across traits, but each must
209 ///   type-check when chosen by method resolution at a particular call site.
210 ///
211 /// * We implement each trait for an `i`-deep borrow of the type(s) we want to
212 ///   specialize the `i`th implementation on, for example:
213 ///
214 ///   ```ignore
215 ///   impl Specialization1 for &MyType { ... }
216 ///   impl Specialization2 for &&OtherType { ... }
217 ///   impl Specialization3 for &&&AnotherType { ... }
218 ///   ```
219 ///
220 /// * Call sites must have all specialization traits in scope and must borrow
221 ///   the receiver `n` times before calling the method. Rust's method name
222 ///   resolution will choose the method with the least number of references that
223 ///   is well-typed. Therefore, specialization implementations for lower numbers
224 ///   of borrows are preferred over those with higher numbers of borrows when
225 ///   specializations overlap. For example, if both `<&&&T as
226 ///   Specialization3>::method` and `<&T as Specialization1>::method` are
227 ///   well-typed at the trait method call site `(&&&&&t).method()`, then
228 ///   `Specialization1` will be prioritized over `Specialization3`.
229 ///
230 /// In our specific case here of choosing an `Error` constructor, we have
231 /// three specializations:
232 ///
233 /// 1. For `anyhow::Error`, we want to use the `Error::from_anyhow` constructor.
234 ///
235 /// 2. When the type implements `core::error::Error`, we want to use the
236 ///    `Error::new` constructor, which will preserve
237 ///    `core::error::Error::source` chains.
238 ///
239 /// 3. Otherwise, we want to use the `Error::msg` constructor.
240 ///
241 /// The `*CtorTrait`s are our `n` specialization traits. Their
242 /// `wasmtime_error_choose_ctor` methods will return different types, each of
243 /// which is a dispatcher to their associated constructor. Those dispatchers
244 /// each have a constructor signature that is syntactically identical, but only
245 /// guaranteed to be well-typed based on the specialization that we did by
246 /// getting the dispatcher in the first place.
247 pub mod ctor_specialization {
248     use super::*;
249 
250     #[cfg(feature = "anyhow")]
251     pub use anyhow::*;
252     #[cfg(feature = "anyhow")]
253     mod anyhow {
254         use super::*;
255 
256         pub trait AnyhowCtorTrait {
257             #[inline]
wasmtime_error_choose_ctor(&self) -> AnyhowCtor258             fn wasmtime_error_choose_ctor(&self) -> AnyhowCtor {
259                 AnyhowCtor
260             }
261         }
262 
263         impl AnyhowCtorTrait for &anyhow::Error {}
264 
265         pub struct AnyhowCtor;
266 
267         impl AnyhowCtor {
268             #[inline]
construct(&self, anyhow_error: ::anyhow::Error) -> Error269             pub fn construct(&self, anyhow_error: ::anyhow::Error) -> Error {
270                 Error::from_anyhow(anyhow_error)
271             }
272         }
273     }
274 
275     pub trait NewCtorTrait {
276         #[inline]
wasmtime_error_choose_ctor(&self) -> NewCtor277         fn wasmtime_error_choose_ctor(&self) -> NewCtor {
278             NewCtor
279         }
280     }
281 
282     impl<E: core::error::Error + Send + Sync + 'static> NewCtorTrait for &&E {}
283 
284     pub struct NewCtor;
285 
286     impl NewCtor {
287         #[inline]
construct<E>(&self, error: E) -> Error where E: core::error::Error + Send + Sync + 'static,288         pub fn construct<E>(&self, error: E) -> Error
289         where
290             E: core::error::Error + Send + Sync + 'static,
291         {
292             Error::new(error)
293         }
294     }
295 
296     pub trait MsgCtorTrait {
297         #[inline]
wasmtime_error_choose_ctor(&self) -> MsgCtor298         fn wasmtime_error_choose_ctor(&self) -> MsgCtor {
299             MsgCtor
300         }
301     }
302 
303     impl<M: fmt::Debug + fmt::Display + Send + Sync + 'static> MsgCtorTrait for &&&M {}
304 
305     pub struct MsgCtor;
306 
307     impl MsgCtor {
308         #[inline]
construct<M>(&self, message: M) -> Error where M: fmt::Debug + fmt::Display + Send + Sync + 'static,309         pub fn construct<M>(&self, message: M) -> Error
310         where
311             M: fmt::Debug + fmt::Display + Send + Sync + 'static,
312         {
313             Error::msg(message)
314         }
315     }
316 }
317 
318 /// Runtime code for creating an `Error` from format arguments, handling OOM in
319 /// the process.
320 pub mod formatting {
321     use super::*;
322 
323     #[derive(Default)]
324     struct Formatter {
325         message: String,
326         oom: Option<OutOfMemory>,
327     }
328 
329     impl fmt::Write for Formatter {
write_str(&mut self, s: &str) -> fmt::Result330         fn write_str(&mut self, s: &str) -> fmt::Result {
331             match self.message.try_reserve(s.len()) {
332                 Ok(()) => {
333                     self.message.push_str(s);
334                     Ok(())
335                 }
336                 Err(_) => {
337                     self.oom = Some(OutOfMemory::new(self.message.len() + s.len()));
338                     Err(fmt::Error)
339                 }
340             }
341         }
342     }
343 
344     impl Error {
345         /// Construct an `Error` from format arguments.
346         ///
347         /// Only for use by the `format_err!` macro.
348         #[doc(hidden)]
from_format_args(args: fmt::Arguments<'_>) -> Self349         pub fn from_format_args(args: fmt::Arguments<'_>) -> Self {
350             if let Some(s) = args.as_str() {
351                 return Self::msg(s);
352             }
353 
354             let mut f = Formatter::default();
355             match write(&mut f, args) {
356                 Ok(()) => {
357                     debug_assert!(f.oom.is_none());
358                     Error::msg(f.message)
359                 }
360                 Err(fmt_error) => match f.oom {
361                     Some(oom) => Error::new(oom),
362                     None => Error::new(fmt_error),
363                 },
364             }
365         }
366     }
367 }
368 
369 pub mod ensure {
370     /// Convenience trait to enable `ensure!(cond, ...)` to work when `cond` is of
371     /// type `&bool`, not just `bool`. Saves useless rewrite-to-`*cond` busywork and
372     /// matches `anyhow`'s behavior.
373     pub trait ToBool {
to_bool(self) -> bool374         fn to_bool(self) -> bool;
375     }
376 
377     impl ToBool for bool {
378         #[inline]
to_bool(self) -> bool379         fn to_bool(self) -> bool {
380             self
381         }
382     }
383 
384     impl ToBool for &bool {
385         #[inline]
to_bool(self) -> bool386         fn to_bool(self) -> bool {
387             *self
388         }
389     }
390 
391     #[inline]
not(b: impl ToBool) -> bool392     pub fn not(b: impl ToBool) -> bool {
393         !b.to_bool()
394     }
395 }
396