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