diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:44:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:44:51 +0000 |
commit | 9e3c08db40b8916968b9f30096c7be3f00ce9647 (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/rust/anyhow/src | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/anyhow/src')
-rw-r--r-- | third_party/rust/anyhow/src/backtrace.rs | 401 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/chain.rs | 102 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/context.rs | 193 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/ensure.rs | 834 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/error.rs | 992 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/fmt.rs | 155 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/kind.rs | 116 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/lib.rs | 680 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/macros.rs | 231 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/ptr.rs | 199 | ||||
-rw-r--r-- | third_party/rust/anyhow/src/wrapper.rs | 81 |
11 files changed, 3984 insertions, 0 deletions
diff --git a/third_party/rust/anyhow/src/backtrace.rs b/third_party/rust/anyhow/src/backtrace.rs new file mode 100644 index 0000000000..23c0c85ce2 --- /dev/null +++ b/third_party/rust/anyhow/src/backtrace.rs @@ -0,0 +1,401 @@ +#[cfg(backtrace)] +pub(crate) use std::backtrace::{Backtrace, BacktraceStatus}; + +#[cfg(all(not(backtrace), feature = "backtrace"))] +pub(crate) use self::capture::{Backtrace, BacktraceStatus}; + +#[cfg(not(any(backtrace, feature = "backtrace")))] +pub(crate) enum Backtrace {} + +#[cfg(backtrace)] +macro_rules! impl_backtrace { + () => { + std::backtrace::Backtrace + }; +} + +#[cfg(all(not(backtrace), feature = "backtrace"))] +macro_rules! impl_backtrace { + () => { + impl core::fmt::Debug + core::fmt::Display + }; +} + +#[cfg(any(backtrace, feature = "backtrace"))] +macro_rules! backtrace { + () => { + Some(crate::backtrace::Backtrace::capture()) + }; +} + +#[cfg(not(any(backtrace, feature = "backtrace")))] +macro_rules! backtrace { + () => { + None + }; +} + +#[cfg(backtrace)] +macro_rules! backtrace_if_absent { + ($err:expr) => { + match ($err as &dyn std::error::Error).request_ref::<std::backtrace::Backtrace>() { + Some(_) => None, + None => backtrace!(), + } + }; +} + +#[cfg(all(feature = "std", not(backtrace), feature = "backtrace"))] +macro_rules! backtrace_if_absent { + ($err:expr) => { + backtrace!() + }; +} + +#[cfg(all(feature = "std", not(backtrace), not(feature = "backtrace")))] +macro_rules! backtrace_if_absent { + ($err:expr) => { + None + }; +} + +#[cfg(all(not(backtrace), feature = "backtrace"))] +mod capture { + use backtrace::{BacktraceFmt, BytesOrWideString, Frame, PrintFmt, SymbolName}; + use core::cell::UnsafeCell; + use core::fmt::{self, Debug, Display}; + use core::sync::atomic::{AtomicUsize, Ordering}; + use std::borrow::Cow; + use std::env; + use std::path::{self, Path, PathBuf}; + use std::sync::Once; + + pub(crate) struct Backtrace { + inner: Inner, + } + + pub(crate) enum BacktraceStatus { + Unsupported, + Disabled, + Captured, + } + + enum Inner { + Unsupported, + Disabled, + Captured(LazilyResolvedCapture), + } + + struct Capture { + actual_start: usize, + resolved: bool, + frames: Vec<BacktraceFrame>, + } + + struct BacktraceFrame { + frame: Frame, + symbols: Vec<BacktraceSymbol>, + } + + struct BacktraceSymbol { + name: Option<Vec<u8>>, + filename: Option<BytesOrWide>, + lineno: Option<u32>, + colno: Option<u32>, + } + + enum BytesOrWide { + Bytes(Vec<u8>), + Wide(Vec<u16>), + } + + impl Debug for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let capture = match &self.inner { + Inner::Unsupported => return fmt.write_str("<unsupported>"), + Inner::Disabled => return fmt.write_str("<disabled>"), + Inner::Captured(c) => c.force(), + }; + + let frames = &capture.frames[capture.actual_start..]; + + write!(fmt, "Backtrace ")?; + + let mut dbg = fmt.debug_list(); + + for frame in frames { + if frame.frame.ip().is_null() { + continue; + } + + dbg.entries(&frame.symbols); + } + + dbg.finish() + } + } + + impl Debug for BacktraceFrame { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut dbg = fmt.debug_list(); + dbg.entries(&self.symbols); + dbg.finish() + } + } + + impl Debug for BacktraceSymbol { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{{ ")?; + + if let Some(fn_name) = self.name.as_ref().map(|b| SymbolName::new(b)) { + write!(fmt, "fn: \"{:#}\"", fn_name)?; + } else { + write!(fmt, "fn: <unknown>")?; + } + + if let Some(fname) = self.filename.as_ref() { + write!(fmt, ", file: \"{:?}\"", fname)?; + } + + if let Some(line) = self.lineno { + write!(fmt, ", line: {:?}", line)?; + } + + write!(fmt, " }}") + } + } + + impl Debug for BytesOrWide { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + output_filename( + fmt, + match self { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }, + PrintFmt::Short, + env::current_dir().as_ref().ok(), + ) + } + } + + impl Backtrace { + fn enabled() -> bool { + static ENABLED: AtomicUsize = AtomicUsize::new(0); + match ENABLED.load(Ordering::Relaxed) { + 0 => {} + 1 => return false, + _ => return true, + } + let enabled = match env::var_os("RUST_LIB_BACKTRACE") { + Some(s) => s != "0", + None => match env::var_os("RUST_BACKTRACE") { + Some(s) => s != "0", + None => false, + }, + }; + ENABLED.store(enabled as usize + 1, Ordering::Relaxed); + enabled + } + + #[inline(never)] // want to make sure there's a frame here to remove + pub(crate) fn capture() -> Backtrace { + if Backtrace::enabled() { + Backtrace::create(Backtrace::capture as usize) + } else { + let inner = Inner::Disabled; + Backtrace { inner } + } + } + + // Capture a backtrace which starts just before the function addressed + // by `ip` + fn create(ip: usize) -> Backtrace { + let mut frames = Vec::new(); + let mut actual_start = None; + backtrace::trace(|frame| { + frames.push(BacktraceFrame { + frame: frame.clone(), + symbols: Vec::new(), + }); + if frame.symbol_address() as usize == ip && actual_start.is_none() { + actual_start = Some(frames.len() + 1); + } + true + }); + + // If no frames came out assume that this is an unsupported platform + // since `backtrace` doesn't provide a way of learning this right + // now, and this should be a good enough approximation. + let inner = if frames.is_empty() { + Inner::Unsupported + } else { + Inner::Captured(LazilyResolvedCapture::new(Capture { + actual_start: actual_start.unwrap_or(0), + frames, + resolved: false, + })) + }; + + Backtrace { inner } + } + + pub(crate) fn status(&self) -> BacktraceStatus { + match self.inner { + Inner::Unsupported => BacktraceStatus::Unsupported, + Inner::Disabled => BacktraceStatus::Disabled, + Inner::Captured(_) => BacktraceStatus::Captured, + } + } + } + + impl Display for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let capture = match &self.inner { + Inner::Unsupported => return fmt.write_str("unsupported backtrace"), + Inner::Disabled => return fmt.write_str("disabled backtrace"), + Inner::Captured(c) => c.force(), + }; + + let full = fmt.alternate(); + let (frames, style) = if full { + (&capture.frames[..], PrintFmt::Full) + } else { + (&capture.frames[capture.actual_start..], PrintFmt::Short) + }; + + // When printing paths we try to strip the cwd if it exists, + // otherwise we just print the path as-is. Note that we also only do + // this for the short format, because if it's full we presumably + // want to print everything. + let cwd = env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter, path: BytesOrWideString| { + output_filename(fmt, path, style, cwd.as_ref().ok()) + }; + + let mut f = BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + for frame in frames { + let mut f = f.frame(); + if frame.symbols.is_empty() { + f.print_raw(frame.frame.ip(), None, None, None)?; + } else { + for symbol in frame.symbols.iter() { + f.print_raw_with_column( + frame.frame.ip(), + symbol.name.as_ref().map(|b| SymbolName::new(b)), + symbol.filename.as_ref().map(|b| match b { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }), + symbol.lineno, + symbol.colno, + )?; + } + } + } + f.finish()?; + Ok(()) + } + } + + struct LazilyResolvedCapture { + sync: Once, + capture: UnsafeCell<Capture>, + } + + impl LazilyResolvedCapture { + fn new(capture: Capture) -> Self { + LazilyResolvedCapture { + sync: Once::new(), + capture: UnsafeCell::new(capture), + } + } + + fn force(&self) -> &Capture { + self.sync.call_once(|| { + // Safety: This exclusive reference can't overlap with any + // others. `Once` guarantees callers will block until this + // closure returns. `Once` also guarantees only a single caller + // will enter this closure. + unsafe { &mut *self.capture.get() }.resolve(); + }); + + // Safety: This shared reference can't overlap with the exclusive + // reference above. + unsafe { &*self.capture.get() } + } + } + + // Safety: Access to the inner value is synchronized using a thread-safe + // `Once`. So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too + unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {} + + impl Capture { + fn resolve(&mut self) { + // If we're already resolved, nothing to do! + if self.resolved { + return; + } + self.resolved = true; + + for frame in self.frames.iter_mut() { + let symbols = &mut frame.symbols; + let frame = &frame.frame; + backtrace::resolve_frame(frame, |symbol| { + symbols.push(BacktraceSymbol { + name: symbol.name().map(|m| m.as_bytes().to_vec()), + filename: symbol.filename_raw().map(|b| match b { + BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()), + BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()), + }), + lineno: symbol.lineno(), + colno: symbol.colno(), + }); + }); + } + } + } + + // Prints the filename of the backtrace frame. + fn output_filename( + fmt: &mut fmt::Formatter, + bows: BytesOrWideString, + print_fmt: PrintFmt, + cwd: Option<&PathBuf>, + ) -> fmt::Result { + let file: Cow<Path> = match bows { + #[cfg(unix)] + BytesOrWideString::Bytes(bytes) => { + use std::os::unix::ffi::OsStrExt; + Path::new(std::ffi::OsStr::from_bytes(bytes)).into() + } + #[cfg(not(unix))] + BytesOrWideString::Bytes(bytes) => { + Path::new(std::str::from_utf8(bytes).unwrap_or("<unknown>")).into() + } + #[cfg(windows)] + BytesOrWideString::Wide(wide) => { + use std::os::windows::ffi::OsStringExt; + Cow::Owned(std::ffi::OsString::from_wide(wide).into()) + } + #[cfg(not(windows))] + BytesOrWideString::Wide(_wide) => Path::new("<unknown>").into(), + }; + if print_fmt == PrintFmt::Short && file.is_absolute() { + if let Some(cwd) = cwd { + if let Ok(stripped) = file.strip_prefix(&cwd) { + if let Some(s) = stripped.to_str() { + return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s); + } + } + } + } + Display::fmt(&file.display(), fmt) + } +} + +fn _assert_send_sync() { + fn _assert<T: Send + Sync>() {} + _assert::<Backtrace>(); +} diff --git a/third_party/rust/anyhow/src/chain.rs b/third_party/rust/anyhow/src/chain.rs new file mode 100644 index 0000000000..f7baff29f1 --- /dev/null +++ b/third_party/rust/anyhow/src/chain.rs @@ -0,0 +1,102 @@ +use self::ChainState::*; +use crate::StdError; + +#[cfg(feature = "std")] +use std::vec; + +#[cfg(feature = "std")] +pub(crate) use crate::Chain; + +#[cfg(not(feature = "std"))] +pub(crate) struct Chain<'a> { + state: ChainState<'a>, +} + +#[derive(Clone)] +pub(crate) enum ChainState<'a> { + Linked { + next: Option<&'a (dyn StdError + 'static)>, + }, + #[cfg(feature = "std")] + Buffered { + rest: vec::IntoIter<&'a (dyn StdError + 'static)>, + }, +} + +impl<'a> Chain<'a> { + #[cold] + pub fn new(head: &'a (dyn StdError + 'static)) -> Self { + Chain { + state: ChainState::Linked { next: Some(head) }, + } + } +} + +impl<'a> Iterator for Chain<'a> { + type Item = &'a (dyn StdError + 'static); + + fn next(&mut self) -> Option<Self::Item> { + match &mut self.state { + Linked { next } => { + let error = (*next)?; + *next = error.source(); + Some(error) + } + #[cfg(feature = "std")] + Buffered { rest } => rest.next(), + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.len(); + (len, Some(len)) + } +} + +#[cfg(feature = "std")] +impl DoubleEndedIterator for Chain<'_> { + fn next_back(&mut self) -> Option<Self::Item> { + match &mut self.state { + Linked { mut next } => { + let mut rest = Vec::new(); + while let Some(cause) = next { + next = cause.source(); + rest.push(cause); + } + let mut rest = rest.into_iter(); + let last = rest.next_back(); + self.state = Buffered { rest }; + last + } + Buffered { rest } => rest.next_back(), + } + } +} + +impl ExactSizeIterator for Chain<'_> { + fn len(&self) -> usize { + match &self.state { + Linked { mut next } => { + let mut len = 0; + while let Some(cause) = next { + next = cause.source(); + len += 1; + } + len + } + #[cfg(feature = "std")] + Buffered { rest } => rest.len(), + } + } +} + +#[cfg(feature = "std")] +impl Default for Chain<'_> { + fn default() -> Self { + Chain { + state: ChainState::Buffered { + rest: Vec::new().into_iter(), + }, + } + } +} diff --git a/third_party/rust/anyhow/src/context.rs b/third_party/rust/anyhow/src/context.rs new file mode 100644 index 0000000000..9df86937bd --- /dev/null +++ b/third_party/rust/anyhow/src/context.rs @@ -0,0 +1,193 @@ +use crate::error::ContextError; +use crate::{Context, Error, StdError}; +use core::convert::Infallible; +use core::fmt::{self, Debug, Display, Write}; + +#[cfg(backtrace)] +use std::any::{Demand, Provider}; + +mod ext { + use super::*; + + pub trait StdError { + fn ext_context<C>(self, context: C) -> Error + where + C: Display + Send + Sync + 'static; + } + + #[cfg(feature = "std")] + impl<E> StdError for E + where + E: std::error::Error + Send + Sync + 'static, + { + fn ext_context<C>(self, context: C) -> Error + where + C: Display + Send + Sync + 'static, + { + let backtrace = backtrace_if_absent!(&self); + Error::from_context(context, self, backtrace) + } + } + + impl StdError for Error { + fn ext_context<C>(self, context: C) -> Error + where + C: Display + Send + Sync + 'static, + { + self.context(context) + } + } +} + +impl<T, E> Context<T, E> for Result<T, E> +where + E: ext::StdError + Send + Sync + 'static, +{ + fn context<C>(self, context: C) -> Result<T, Error> + where + C: Display + Send + Sync + 'static, + { + // Not using map_err to save 2 useless frames off the captured backtrace + // in ext_context. + match self { + Ok(ok) => Ok(ok), + Err(error) => Err(error.ext_context(context)), + } + } + + fn with_context<C, F>(self, context: F) -> Result<T, Error> + where + C: Display + Send + Sync + 'static, + F: FnOnce() -> C, + { + match self { + Ok(ok) => Ok(ok), + Err(error) => Err(error.ext_context(context())), + } + } +} + +/// ``` +/// # type T = (); +/// # +/// use anyhow::{Context, Result}; +/// +/// fn maybe_get() -> Option<T> { +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unimplemented!() +/// } +/// +/// fn demo() -> Result<()> { +/// let t = maybe_get().context("there is no T")?; +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unimplemented!() +/// } +/// ``` +impl<T> Context<T, Infallible> for Option<T> { + fn context<C>(self, context: C) -> Result<T, Error> + where + C: Display + Send + Sync + 'static, + { + // Not using ok_or_else to save 2 useless frames off the captured + // backtrace. + match self { + Some(ok) => Ok(ok), + None => Err(Error::from_display(context, backtrace!())), + } + } + + fn with_context<C, F>(self, context: F) -> Result<T, Error> + where + C: Display + Send + Sync + 'static, + F: FnOnce() -> C, + { + match self { + Some(ok) => Ok(ok), + None => Err(Error::from_display(context(), backtrace!())), + } + } +} + +impl<C, E> Debug for ContextError<C, E> +where + C: Display, + E: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Error") + .field("context", &Quoted(&self.context)) + .field("source", &self.error) + .finish() + } +} + +impl<C, E> Display for ContextError<C, E> +where + C: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.context, f) + } +} + +impl<C, E> StdError for ContextError<C, E> +where + C: Display, + E: StdError + 'static, +{ + fn source(&self) -> Option<&(dyn StdError + 'static)> { + Some(&self.error) + } + + #[cfg(backtrace)] + fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + StdError::provide(&self.error, demand); + } +} + +impl<C> StdError for ContextError<C, Error> +where + C: Display, +{ + fn source(&self) -> Option<&(dyn StdError + 'static)> { + Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) + } + + #[cfg(backtrace)] + fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + Provider::provide(&self.error, demand); + } +} + +struct Quoted<C>(C); + +impl<C> Debug for Quoted<C> +where + C: Display, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_char('"')?; + Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?; + formatter.write_char('"')?; + Ok(()) + } +} + +impl Write for Quoted<&mut fmt::Formatter<'_>> { + fn write_str(&mut self, s: &str) -> fmt::Result { + Display::fmt(&s.escape_debug(), self.0) + } +} + +pub(crate) mod private { + use super::*; + + pub trait Sealed {} + + impl<T, E> Sealed for Result<T, E> where E: ext::StdError {} + impl<T> Sealed for Option<T> {} +} diff --git a/third_party/rust/anyhow/src/ensure.rs b/third_party/rust/anyhow/src/ensure.rs new file mode 100644 index 0000000000..0ab4471231 --- /dev/null +++ b/third_party/rust/anyhow/src/ensure.rs @@ -0,0 +1,834 @@ +use crate::Error; +use alloc::string::String; +use core::fmt::{self, Debug, Write}; +use core::mem::MaybeUninit; +use core::ptr; +use core::slice; +use core::str; + +#[doc(hidden)] +pub trait BothDebug { + fn __dispatch_ensure(self, msg: &'static str) -> Error; +} + +impl<A, B> BothDebug for (A, B) +where + A: Debug, + B: Debug, +{ + fn __dispatch_ensure(self, msg: &'static str) -> Error { + render(msg, &self.0, &self.1) + } +} + +#[doc(hidden)] +pub trait NotBothDebug { + fn __dispatch_ensure(self, msg: &'static str) -> Error; +} + +impl<A, B> NotBothDebug for &(A, B) { + fn __dispatch_ensure(self, msg: &'static str) -> Error { + Error::msg(msg) + } +} + +struct Buf { + bytes: [MaybeUninit<u8>; 40], + written: usize, +} + +impl Buf { + fn new() -> Self { + Buf { + bytes: [MaybeUninit::uninit(); 40], + written: 0, + } + } + + fn as_str(&self) -> &str { + unsafe { + str::from_utf8_unchecked(slice::from_raw_parts( + self.bytes.as_ptr().cast::<u8>(), + self.written, + )) + } + } +} + +impl Write for Buf { + fn write_str(&mut self, s: &str) -> fmt::Result { + if s.bytes().any(|b| b == b' ' || b == b'\n') { + return Err(fmt::Error); + } + + let remaining = self.bytes.len() - self.written; + if s.len() > remaining { + return Err(fmt::Error); + } + + unsafe { + ptr::copy_nonoverlapping( + s.as_ptr(), + self.bytes.as_mut_ptr().add(self.written).cast::<u8>(), + s.len(), + ); + } + self.written += s.len(); + Ok(()) + } +} + +fn render(msg: &'static str, lhs: &dyn Debug, rhs: &dyn Debug) -> Error { + let mut lhs_buf = Buf::new(); + if fmt::write(&mut lhs_buf, format_args!("{:?}", lhs)).is_ok() { + let mut rhs_buf = Buf::new(); + if fmt::write(&mut rhs_buf, format_args!("{:?}", rhs)).is_ok() { + let lhs_str = lhs_buf.as_str(); + let rhs_str = rhs_buf.as_str(); + // "{msg} ({lhs} vs {rhs})" + let len = msg.len() + 2 + lhs_str.len() + 4 + rhs_str.len() + 1; + let mut string = String::with_capacity(len); + string.push_str(msg); + string.push_str(" ("); + string.push_str(lhs_str); + string.push_str(" vs "); + string.push_str(rhs_str); + string.push(')'); + return Error::msg(string); + } + } + Error::msg(msg) +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __parse_ensure { + (atom () $bail:tt $fuel:tt {($($rhs:tt)+) ($($lhs:tt)+) $op:tt} $dup:tt $(,)?) => { + $crate::__fancy_ensure!($($lhs)+, $op, $($rhs)+) + }; + + // low precedence control flow constructs + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt return $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt break $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt continue $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt yield $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + (0 $stack:tt ($($bail:tt)*) $fuel:tt $parse:tt $dup:tt move $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; + + // unary operators + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($deref:tt $($dup:tt)*) * $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $deref) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($not:tt $($dup:tt)*) ! $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $not) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($neg:tt $($dup:tt)*) - $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $neg) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($let:tt $($dup:tt)*) let $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $let) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($life:tt $colon:tt $($dup:tt)*) $label:lifetime : $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $life $colon) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) &mut $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $mut:tt $($dup:tt)*) &&mut $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $andand $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $($dup:tt)*) && $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $andand) $($parse)*} ($($rest)*) $($rest)*) + }; + + // control flow constructs + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($if:tt $($dup:tt)*) if $($rest:tt)*) => { + $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $if) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($match:tt $($dup:tt)*) match $($rest:tt)*) => { + $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $match) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($while:tt $($dup:tt)*) while $($rest:tt)*) => { + $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $while) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($for:tt $($dup:tt)*) for $($rest:tt)*) => { + $crate::__parse_ensure!(pat (cond $stack) $bail ($($fuel)*) {($($buf)* $for) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom (cond $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(cond $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (cond $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($else:tt $if:tt $($dup:tt)*) else if $($rest:tt)*) => { + $crate::__parse_ensure!(0 (cond $stack) $bail ($($fuel)*) {($($buf)* $else $if) $($parse)*} ($($rest)*) $($rest)*) + }; + + (cond $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($else:tt $brace:tt $($dup:tt)*) else {$($block:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $else $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (cond $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + // atomic expressions + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($array:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($loop:tt $block:tt $($dup:tt)*) loop {$($body:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $loop $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($async:tt $block:tt $($dup:tt)*) async {$($body:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $async $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($async:tt $move:tt $block:tt $($dup:tt)*) async move {$($body:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $async $move $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($unsafe:tt $block:tt $($dup:tt)*) unsafe {$($body:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $unsafe $block) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $lit) $($parse)*} ($($rest)*) $($rest)*) + }; + + // path expressions + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath (atom $stack) $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath (atom $stack) $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (epath (atom $stack))) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $langle:tt $($dup:tt)*) :: < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: << $($rest:tt)*) => { + $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons <) $($parse)*} (< $($rest)*) < $($rest)*) + }; + + (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: <- $($rest:tt)*) => { + $crate::__parse_ensure!(generic (epath $stack) $bail ($($fuel)*) {($($buf)* $colons <) $($parse)*} (- $($rest)*) - $($rest)*) + }; + + (epath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! ($($mac:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! [$($mac:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! {$($mac:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (epath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + // trailer expressions + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($call:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($index:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($init:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($question:tt $($dup:tt)*) ? $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $question) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $langle:tt $($dup:tt)*) . $i:ident :: < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $($dup:tt)*) . $i:ident :: << $($rest:tt)*) => { + $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons <) $($parse)*} (< $($rest)*) < $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $ident:tt $colons:tt $($dup:tt)*) . $i:ident :: <- $($rest:tt)*) => { + $crate::__parse_ensure!(generic (atom $stack) $bail ($($fuel)*) {($($buf)* $dot $ident $colons <) $($parse)*} (- $($rest)*) - $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $($dup:tt)*) . $field:ident $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $dot $field) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dot:tt $index:tt $($dup:tt)*) . $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $dot $index) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($as:tt $($dup:tt)*) as $($rest:tt)*) => { + $crate::__parse_ensure!(type (atom $stack) $bail ($($fuel)*) {($($buf)* $as) $($parse)*} ($($rest)*) $($rest)*) + }; + + // types + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($content:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($star:tt $const:tt $($dup:tt)*) *const $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $star $const) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($star:tt $mut:tt $($dup:tt)*) *mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $star $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $life:lifetime $mut:tt $($dup:tt)*) & $l:lifetime mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $life $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) & mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $life:lifetime $($dup:tt)*) & $l:lifetime $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $life) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $life:lifetime $mut:tt $($dup:tt)*) && $l:lifetime mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $life $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $mut:tt $($dup:tt)*) && mut $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $life:lifetime $($dup:tt)*) && $l:lifetime $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and $life) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) && $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($unsafe:tt $(extern $($abi:literal)?)? fn $($dup:tt)*) unsafe $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $unsafe) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($extern:tt $abi:literal fn $($dup:tt)*) extern $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $extern $abi) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($extern:tt fn $($dup:tt)*) extern $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $extern) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($fn:tt $paren:tt $arrow:tt $($dup:tt)*) fn ($($args:tt)*) -> $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $fn $paren $arrow) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($fn:tt $paren:tt $($dup:tt)*) fn ($($args:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $fn $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($impl:tt $($dup:tt)*) impl $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $impl) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($dyn:tt $($dup:tt)*) dyn $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $dyn) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($wild:tt $($dup:tt)*) _ $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $wild) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($never:tt $($dup:tt)*) ! $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $never) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($for:tt $langle:tt $($dup:tt)*) for < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (type $stack) $bail ($($fuel)*) {($($buf)* $for $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + // path types + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (type $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (tpath $stack)) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt << $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* <) $($parse)*} (< $($rest)*) < $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt <- $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* <) $($parse)*} (- $($rest)*) - $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $langle:tt $($dup:tt)*) :: < $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: << $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons <) $($parse)*} (< $($rest)*) < $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: <- $($rest:tt)*) => { + $crate::__parse_ensure!(generic (tpath $stack) $bail ($($fuel)*) {($($buf)* $colons <) $($parse)*} (- $($rest)*) - $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath $stack $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $arrow:tt $($dup:tt)*) ($($args:tt)*) -> $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $paren $arrow) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($args:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(object $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $paren:tt $arrow:tt $($dup:tt)*) :: ($($args:tt)*) -> $($rest:tt)*) => { + $crate::__parse_ensure!(type $stack $bail ($($fuel)*) {($($buf)* $colons $paren $arrow) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $paren:tt $($dup:tt)*) :: ($($args:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(object $stack $bail ($($fuel)*) {($($buf)* $colons $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! ($($mac:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! [$($mac:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bang:tt $args:tt $($dup:tt)*) ! {$($mac:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $bang $args) $($parse)*} ($($rest)*) $($rest)*) + }; + + (tpath $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!(object $stack $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + // qualified paths + + (qpath ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $colons:tt $($dup:tt)*) > :: $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (qpath $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($as:tt $($dup:tt)*) as $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath $stack) $bail ($($fuel)*) {($($buf)* $as) $($parse)*} ($($rest)*) $($rest)*) + }; + + // trait objects + + (object (arglist $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($plus:tt $colons:tt $($dup:tt)*) + :: $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath (arglist $stack) $bail ($($fuel)*) {($($buf)* $plus $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (object (arglist $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($plus:tt $($dup:tt)*) + $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(tpath (arglist $stack) $bail ($($fuel)*) {($($buf)* $plus $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (object ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + // angle bracketed generic arguments + + (generic ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) > $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt >> $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* >) $($parse)*} (> $($rest)*) > $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $lit) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($block:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $life:lifetime $($rest:tt)*) => { + $crate::__parse_ensure!(arglist $stack $bail ($($fuel)*) {($($buf)* $life) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($assoc:ident $eq:tt $($dup:tt)*) $ident:ident = $($rest:tt)*) => { + $crate::__parse_ensure!(type (arglist $stack) $bail ($($fuel)*) {($($buf)* $assoc $eq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (generic $stack:tt $bail:tt (~$($fuel:tt)*) $parse:tt $dup:tt $($rest:tt)*) => { + $crate::__parse_ensure!(type (arglist $stack) $bail ($($fuel)*) $parse $dup $($rest)*) + }; + + (arglist $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($comma:tt $($dup:tt)*) , $($rest:tt)*) => { + $crate::__parse_ensure!(generic $stack $bail ($($fuel)*) {($($buf)* $comma) $($parse)*} ($($rest)*) $($rest)*) + }; + + (arglist ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rangle:tt $($dup:tt)*) > $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* $rangle) $($parse)*} ($($rest)*) $($rest)*) + }; + + (arglist ($pop:ident $stack:tt) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt >> $($rest:tt)*) => { + $crate::__parse_ensure!($pop $stack $bail ($($fuel)*) {($($buf)* >) $($parse)*} (> $($rest)*) > $($rest)*) + }; + + // patterns + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($pipe:tt $($dup:tt)*) | $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $pipe) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($eq:tt $($dup:tt)*) = $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $eq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($in:tt $($dup:tt)*) in $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $in) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ref:tt $($dup:tt)*) ref $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $ref) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($mut:tt $($dup:tt)*) mut $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $mut) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($at:tt $($dup:tt)*) @ $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $at) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $lit:literal $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $lit) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($range:tt $($dup:tt)*) .. $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $range) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($range:tt $($dup:tt)*) ..= $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $range) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) & $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($andand:tt $($dup:tt)*) && $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $andand) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($paren:tt $($dup:tt)*) ($($content:tt)*) $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $paren) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bracket:tt $($dup:tt)*) [$($content:tt)*] $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $bracket) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($brace:tt $($dup:tt)*) {$($content:tt)*} $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $brace) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($wild:tt $($dup:tt)*) _ $($rest:tt)*) => { + $crate::__parse_ensure!(pat $stack $bail ($($fuel)*) {($($buf)* $wild) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($colons:tt $($dup:tt)*) :: $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath (pat $stack) $bail ($($fuel)*) {($($buf)* $colons $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $ident:ident $($rest:tt)*) => { + $crate::__parse_ensure!(epath (pat $stack) $bail ($($fuel)*) {($($buf)* $ident) $($parse)*} ($($rest)*) $($rest)*) + }; + + (pat $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($langle:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(type (qpath (epath (pat $stack))) $bail ($($fuel)*) {($($buf)* $langle) $($parse)*} ($($rest)*) $($rest)*) + }; + + // high precedence binary operators + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($add:tt $($dup:tt)*) + $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $add) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($sub:tt $($dup:tt)*) - $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $sub) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($mul:tt $($dup:tt)*) * $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $mul) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($div:tt $($dup:tt)*) / $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $div) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($rem:tt $($dup:tt)*) % $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $rem) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitxor:tt $($dup:tt)*) ^ $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitxor) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitand:tt $($dup:tt)*) & $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitand) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitor:tt $($dup:tt)*) | $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $bitor) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shl:tt $($dup:tt)*) << $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $shl) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shr:tt $($dup:tt)*) >> $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $shr) $($parse)*} ($($rest)*) $($rest)*) + }; + + // comparison binary operators + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($eq:tt $($dup:tt)*) == $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $eq} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($eq:tt $($dup:tt)*) == $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $eq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($le:tt $($dup:tt)*) <= $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $le} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($le:tt $($dup:tt)*) <= $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $le) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($lt:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $lt} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($lt:tt $($dup:tt)*) < $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $lt) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ne:tt $($dup:tt)*) != $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $ne} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($ne:tt $($dup:tt)*) != $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $ne) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($ge:tt $($dup:tt)*) >= $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $ge} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($ge:tt $($dup:tt)*) >= $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $ge) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom () $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($gt:tt $($dup:tt)*) > $($rest:tt)*) => { + $crate::__parse_ensure!(0 () $bail ($($fuel)*) {() $($parse)* ($($buf)*) $gt} ($($rest)*) $($rest)*) + }; + + (atom $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)+) $($parse:tt)*} ($gt:tt $($dup:tt)*) > $($rest:tt)*) => { + $crate::__parse_ensure!(0 $stack $bail ($($fuel)*) {($($buf)* $gt) $($parse)*} ($($rest)*) $($rest)*) + }; + + // low precedence binary operators + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($and:tt $($dup:tt)*) && $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $and) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($or:tt $($dup:tt)*) || $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $or) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($assign:tt $($dup:tt)*) = $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $assign) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($addeq:tt $($dup:tt)*) += $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $addeq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($subeq:tt $($dup:tt)*) -= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $subeq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($muleq:tt $($dup:tt)*) *= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $muleq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($diveq:tt $($dup:tt)*) /= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $diveq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($remeq:tt $($dup:tt)*) %= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $remeq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitxoreq:tt $($dup:tt)*) ^= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitxoreq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitandeq:tt $($dup:tt)*) &= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitandeq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($bitoreq:tt $($dup:tt)*) |= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $bitoreq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shleq:tt $($dup:tt)*) <<= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $shleq) $($parse)*} ($($rest)*) $($rest)*) + }; + + (atom ($($stack:tt)+) $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($shreq:tt $($dup:tt)*) >>= $($rest:tt)*) => { + $crate::__parse_ensure!(0 ($($stack)*) $bail ($($fuel)*) {($($buf)* $shreq) $($parse)*} ($($rest)*) $($rest)*) + }; + + // unrecognized expression + + ($state:tt $stack:tt ($($bail:tt)*) $($rest:tt)*) => { + $crate::__fallback_ensure!($($bail)*) + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __fancy_ensure { + ($lhs:expr, $op:tt, $rhs:expr) => { + match (&$lhs, &$rhs) { + (lhs, rhs) => { + if !(lhs $op rhs) { + #[allow(unused_imports)] + use $crate::__private::{BothDebug, NotBothDebug}; + return Err((lhs, rhs).__dispatch_ensure( + $crate::__private::concat!( + "Condition failed: `", + $crate::__private::stringify!($lhs), + " ", + $crate::__private::stringify!($op), + " ", + $crate::__private::stringify!($rhs), + "`", + ), + )); + } + } + } + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __fallback_ensure { + ($cond:expr $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::Error::msg( + $crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`") + )); + } + }; + ($cond:expr, $msg:literal $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($msg)); + } + }; + ($cond:expr, $err:expr $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($err)); + } + }; + ($cond:expr, $fmt:expr, $($arg:tt)*) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*)); + } + }; +} diff --git a/third_party/rust/anyhow/src/error.rs b/third_party/rust/anyhow/src/error.rs new file mode 100644 index 0000000000..9f6ce8c10b --- /dev/null +++ b/third_party/rust/anyhow/src/error.rs @@ -0,0 +1,992 @@ +use crate::backtrace::Backtrace; +use crate::chain::Chain; +#[cfg(any(feature = "std", anyhow_no_ptr_addr_of))] +use crate::ptr::Mut; +use crate::ptr::{Own, Ref}; +use crate::{Error, StdError}; +use alloc::boxed::Box; +#[cfg(backtrace)] +use core::any::Demand; +use core::any::TypeId; +use core::fmt::{self, Debug, Display}; +use core::mem::ManuallyDrop; +#[cfg(not(anyhow_no_ptr_addr_of))] +use core::ptr; +use core::ptr::NonNull; + +#[cfg(feature = "std")] +use core::ops::{Deref, DerefMut}; + +impl Error { + /// Create a new error object from any error type. + /// + /// The error type must be threadsafe and `'static`, so that the `Error` + /// will be as well. + /// + /// If the error type does not provide a backtrace, a backtrace will be + /// created here to ensure that a backtrace exists. + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cold] + #[must_use] + pub fn new<E>(error: E) -> Self + where + E: StdError + Send + Sync + 'static, + { + let backtrace = backtrace_if_absent!(&error); + Error::from_std(error, backtrace) + } + + /// Create a new error object from a printable error message. + /// + /// If the argument implements std::error::Error, prefer `Error::new` + /// instead which preserves the underlying error's cause chain and + /// backtrace. If the argument may or may not implement std::error::Error + /// now or in the future, use `anyhow!(err)` which handles either way + /// correctly. + /// + /// `Error::msg("...")` is equivalent to `anyhow!("...")` but occasionally + /// convenient in places where a function is preferable over a macro, such + /// as iterator or stream combinators: + /// + /// ``` + /// # mod ffi { + /// # pub struct Input; + /// # pub struct Output; + /// # pub async fn do_some_work(_: Input) -> Result<Output, &'static str> { + /// # unimplemented!() + /// # } + /// # } + /// # + /// # use ffi::{Input, Output}; + /// # + /// use anyhow::{Error, Result}; + /// use futures::stream::{Stream, StreamExt, TryStreamExt}; + /// + /// async fn demo<S>(stream: S) -> Result<Vec<Output>> + /// where + /// S: Stream<Item = Input>, + /// { + /// stream + /// .then(ffi::do_some_work) // returns Result<Output, &str> + /// .map_err(Error::msg) + /// .try_collect() + /// .await + /// } + /// ``` + #[cold] + #[must_use] + pub fn msg<M>(message: M) -> Self + where + M: Display + Debug + Send + Sync + 'static, + { + Error::from_adhoc(message, backtrace!()) + } + + #[cfg(feature = "std")] + #[cold] + pub(crate) fn from_std<E>(error: E, backtrace: Option<Backtrace>) -> Self + where + E: StdError + Send + Sync + 'static, + { + let vtable = &ErrorVTable { + object_drop: object_drop::<E>, + object_ref: object_ref::<E>, + #[cfg(anyhow_no_ptr_addr_of)] + object_mut: object_mut::<E>, + object_boxed: object_boxed::<E>, + object_downcast: object_downcast::<E>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::<E>, + object_drop_rest: object_drop_front::<E>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, + }; + + // Safety: passing vtable that operates on the right type E. + unsafe { Error::construct(error, vtable, backtrace) } + } + + #[cold] + pub(crate) fn from_adhoc<M>(message: M, backtrace: Option<Backtrace>) -> Self + where + M: Display + Debug + Send + Sync + 'static, + { + use crate::wrapper::MessageError; + let error: MessageError<M> = MessageError(message); + let vtable = &ErrorVTable { + object_drop: object_drop::<MessageError<M>>, + object_ref: object_ref::<MessageError<M>>, + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] + object_mut: object_mut::<MessageError<M>>, + object_boxed: object_boxed::<MessageError<M>>, + object_downcast: object_downcast::<M>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::<M>, + object_drop_rest: object_drop_front::<M>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, + }; + + // Safety: MessageError is repr(transparent) so it is okay for the + // vtable to allow casting the MessageError<M> to M. + unsafe { Error::construct(error, vtable, backtrace) } + } + + #[cold] + pub(crate) fn from_display<M>(message: M, backtrace: Option<Backtrace>) -> Self + where + M: Display + Send + Sync + 'static, + { + use crate::wrapper::DisplayError; + let error: DisplayError<M> = DisplayError(message); + let vtable = &ErrorVTable { + object_drop: object_drop::<DisplayError<M>>, + object_ref: object_ref::<DisplayError<M>>, + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] + object_mut: object_mut::<DisplayError<M>>, + object_boxed: object_boxed::<DisplayError<M>>, + object_downcast: object_downcast::<M>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::<M>, + object_drop_rest: object_drop_front::<M>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, + }; + + // Safety: DisplayError is repr(transparent) so it is okay for the + // vtable to allow casting the DisplayError<M> to M. + unsafe { Error::construct(error, vtable, backtrace) } + } + + #[cfg(feature = "std")] + #[cold] + pub(crate) fn from_context<C, E>(context: C, error: E, backtrace: Option<Backtrace>) -> Self + where + C: Display + Send + Sync + 'static, + E: StdError + Send + Sync + 'static, + { + let error: ContextError<C, E> = ContextError { context, error }; + + let vtable = &ErrorVTable { + object_drop: object_drop::<ContextError<C, E>>, + object_ref: object_ref::<ContextError<C, E>>, + #[cfg(anyhow_no_ptr_addr_of)] + object_mut: object_mut::<ContextError<C, E>>, + object_boxed: object_boxed::<ContextError<C, E>>, + object_downcast: context_downcast::<C, E>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: context_downcast_mut::<C, E>, + object_drop_rest: context_drop_rest::<C, E>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, + }; + + // Safety: passing vtable that operates on the right type. + unsafe { Error::construct(error, vtable, backtrace) } + } + + #[cfg(feature = "std")] + #[cold] + pub(crate) fn from_boxed( + error: Box<dyn StdError + Send + Sync>, + backtrace: Option<Backtrace>, + ) -> Self { + use crate::wrapper::BoxedError; + let error = BoxedError(error); + let vtable = &ErrorVTable { + object_drop: object_drop::<BoxedError>, + object_ref: object_ref::<BoxedError>, + #[cfg(anyhow_no_ptr_addr_of)] + object_mut: object_mut::<BoxedError>, + object_boxed: object_boxed::<BoxedError>, + object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::<Box<dyn StdError + Send + Sync>>, + object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, + }; + + // Safety: BoxedError is repr(transparent) so it is okay for the vtable + // to allow casting to Box<dyn StdError + Send + Sync>. + unsafe { Error::construct(error, vtable, backtrace) } + } + + // Takes backtrace as argument rather than capturing it here so that the + // user sees one fewer layer of wrapping noise in the backtrace. + // + // Unsafe because the given vtable must have sensible behavior on the error + // value of type E. + #[cold] + unsafe fn construct<E>( + error: E, + vtable: &'static ErrorVTable, + backtrace: Option<Backtrace>, + ) -> Self + where + E: StdError + Send + Sync + 'static, + { + let inner: Box<ErrorImpl<E>> = Box::new(ErrorImpl { + vtable, + backtrace, + _object: error, + }); + // Erase the concrete type of E from the compile-time type system. This + // is equivalent to the safe unsize coercion from Box<ErrorImpl<E>> to + // Box<ErrorImpl<dyn StdError + Send + Sync + 'static>> except that the + // result is a thin pointer. The necessary behavior for manipulating the + // underlying ErrorImpl<E> is preserved in the vtable provided by the + // caller rather than a builtin fat pointer vtable. + let inner = Own::new(inner).cast::<ErrorImpl>(); + Error { inner } + } + + /// Wrap the error value with additional context. + /// + /// For attaching context to a `Result` as it is propagated, the + /// [`Context`][crate::Context] extension trait may be more convenient than + /// this function. + /// + /// The primary reason to use `error.context(...)` instead of + /// `result.context(...)` via the `Context` trait would be if the context + /// needs to depend on some data held by the underlying error: + /// + /// ``` + /// # use std::fmt::{self, Debug, Display}; + /// # + /// # type T = (); + /// # + /// # impl std::error::Error for ParseError {} + /// # impl Debug for ParseError { + /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// # unimplemented!() + /// # } + /// # } + /// # impl Display for ParseError { + /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// # unimplemented!() + /// # } + /// # } + /// # + /// use anyhow::Result; + /// use std::fs::File; + /// use std::path::Path; + /// + /// struct ParseError { + /// line: usize, + /// column: usize, + /// } + /// + /// fn parse_impl(file: File) -> Result<T, ParseError> { + /// # const IGNORE: &str = stringify! { + /// ... + /// # }; + /// # unimplemented!() + /// } + /// + /// pub fn parse(path: impl AsRef<Path>) -> Result<T> { + /// let file = File::open(&path)?; + /// parse_impl(file).map_err(|error| { + /// let context = format!( + /// "only the first {} lines of {} are valid", + /// error.line, path.as_ref().display(), + /// ); + /// anyhow::Error::new(error).context(context) + /// }) + /// } + /// ``` + #[cold] + #[must_use] + pub fn context<C>(self, context: C) -> Self + where + C: Display + Send + Sync + 'static, + { + let error: ContextError<C, Error> = ContextError { + context, + error: self, + }; + + let vtable = &ErrorVTable { + object_drop: object_drop::<ContextError<C, Error>>, + object_ref: object_ref::<ContextError<C, Error>>, + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] + object_mut: object_mut::<ContextError<C, Error>>, + object_boxed: object_boxed::<ContextError<C, Error>>, + object_downcast: context_chain_downcast::<C>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: context_chain_downcast_mut::<C>, + object_drop_rest: context_chain_drop_rest::<C>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: context_backtrace::<C>, + }; + + // As the cause is anyhow::Error, we already have a backtrace for it. + let backtrace = None; + + // Safety: passing vtable that operates on the right type. + unsafe { Error::construct(error, vtable, backtrace) } + } + + /// Get the backtrace for this Error. + /// + /// In order for the backtrace to be meaningful, one of the two environment + /// variables `RUST_LIB_BACKTRACE=1` or `RUST_BACKTRACE=1` must be defined + /// and `RUST_LIB_BACKTRACE` must not be `0`. Backtraces are somewhat + /// expensive to capture in Rust, so we don't necessarily want to be + /// capturing them all over the place all the time. + /// + /// - If you want panics and errors to both have backtraces, set + /// `RUST_BACKTRACE=1`; + /// - If you want only errors to have backtraces, set + /// `RUST_LIB_BACKTRACE=1`; + /// - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and + /// `RUST_LIB_BACKTRACE=0`. + /// + /// # Stability + /// + /// Standard library backtraces are only available on the nightly channel. + /// Tracking issue: [rust-lang/rust#53487][tracking]. + /// + /// On stable compilers, this function is only available if the crate's + /// "backtrace" feature is enabled, and will use the `backtrace` crate as + /// the underlying backtrace implementation. + /// + /// ```toml + /// [dependencies] + /// anyhow = { version = "1.0", features = ["backtrace"] } + /// ``` + /// + /// [tracking]: https://github.com/rust-lang/rust/issues/53487 + #[cfg(any(backtrace, feature = "backtrace"))] + #[cfg_attr(doc_cfg, doc(cfg(any(nightly, feature = "backtrace"))))] + pub fn backtrace(&self) -> &impl_backtrace!() { + unsafe { ErrorImpl::backtrace(self.inner.by_ref()) } + } + + /// An iterator of the chain of source errors contained by this Error. + /// + /// This iterator will visit every error in the cause chain of this error + /// object, beginning with the error that this error object was created + /// from. + /// + /// # Example + /// + /// ``` + /// use anyhow::Error; + /// use std::io; + /// + /// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> { + /// for cause in error.chain() { + /// if let Some(io_error) = cause.downcast_ref::<io::Error>() { + /// return Some(io_error.kind()); + /// } + /// } + /// None + /// } + /// ``` + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + #[cold] + pub fn chain(&self) -> Chain { + unsafe { ErrorImpl::chain(self.inner.by_ref()) } + } + + /// The lowest level cause of this error — this error's cause's + /// cause's cause etc. + /// + /// The root cause is the last error in the iterator produced by + /// [`chain()`][Error::chain]. + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + pub fn root_cause(&self) -> &(dyn StdError + 'static) { + self.chain().last().unwrap() + } + + /// Returns true if `E` is the type held by this error object. + /// + /// For errors with context, this method returns true if `E` matches the + /// type of the context `C` **or** the type of the error on which the + /// context has been attached. For details about the interaction between + /// context and downcasting, [see here]. + /// + /// [see here]: trait.Context.html#effect-on-downcasting + pub fn is<E>(&self) -> bool + where + E: Display + Debug + Send + Sync + 'static, + { + self.downcast_ref::<E>().is_some() + } + + /// Attempt to downcast the error object to a concrete type. + pub fn downcast<E>(mut self) -> Result<E, Self> + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::<E>(); + let inner = self.inner.by_mut(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + #[cfg(not(anyhow_no_ptr_addr_of))] + let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) { + Some(addr) => addr.by_mut().extend(), + None => return Err(self), + }; + #[cfg(anyhow_no_ptr_addr_of)] + let addr = match (vtable(inner.ptr).object_downcast_mut)(inner, target) { + Some(addr) => addr.extend(), + None => return Err(self), + }; + + // Prepare to read E out of the data structure. We'll drop the rest + // of the data structure separately so that E is not dropped. + let outer = ManuallyDrop::new(self); + + // Read E from where the vtable found it. + let error = addr.cast::<E>().read(); + + // Drop rest of the data structure outside of E. + (vtable(outer.inner.ptr).object_drop_rest)(outer.inner, target); + + Ok(error) + } + } + + /// Downcast this error object by reference. + /// + /// # Example + /// + /// ``` + /// # use anyhow::anyhow; + /// # use std::fmt::{self, Display}; + /// # use std::task::Poll; + /// # + /// # #[derive(Debug)] + /// # enum DataStoreError { + /// # Censored(()), + /// # } + /// # + /// # impl Display for DataStoreError { + /// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// # unimplemented!() + /// # } + /// # } + /// # + /// # impl std::error::Error for DataStoreError {} + /// # + /// # const REDACTED_CONTENT: () = (); + /// # + /// # let error = anyhow!("..."); + /// # let root_cause = &error; + /// # + /// # let ret = + /// // If the error was caused by redaction, then return a tombstone instead + /// // of the content. + /// match root_cause.downcast_ref::<DataStoreError>() { + /// Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), + /// None => Err(error), + /// } + /// # ; + /// ``` + pub fn downcast_ref<E>(&self) -> Option<&E> + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::<E>(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + let addr = (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?; + Some(addr.cast::<E>().deref()) + } + } + + /// Downcast this error object by mutable reference. + pub fn downcast_mut<E>(&mut self) -> Option<&mut E> + where + E: Display + Debug + Send + Sync + 'static, + { + let target = TypeId::of::<E>(); + unsafe { + // Use vtable to find NonNull<()> which points to a value of type E + // somewhere inside the data structure. + + #[cfg(not(anyhow_no_ptr_addr_of))] + let addr = + (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut(); + + #[cfg(anyhow_no_ptr_addr_of)] + let addr = (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target)?; + + Some(addr.cast::<E>().deref_mut()) + } + } +} + +#[cfg(backtrace)] +impl std::any::Provider for Error { + // Called by thiserror when you have `#[source] anyhow::Error`. This provide + // implementation includes the anyhow::Error's Backtrace if any, unlike + // deref'ing to dyn Error where the provide implementation would include + // only the original error's Backtrace from before it got wrapped into an + // anyhow::Error. + fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + unsafe { ErrorImpl::provide(self.inner.by_ref(), demand) } + } +} + +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +impl<E> From<E> for Error +where + E: StdError + Send + Sync + 'static, +{ + #[cold] + fn from(error: E) -> Self { + let backtrace = backtrace_if_absent!(&error); + Error::from_std(error, backtrace) + } +} + +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +impl Deref for Error { + type Target = dyn StdError + Send + Sync + 'static; + + fn deref(&self) -> &Self::Target { + unsafe { ErrorImpl::error(self.inner.by_ref()) } + } +} + +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +impl DerefMut for Error { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { ErrorImpl::error_mut(self.inner.by_mut()) } + } +} + +impl Display for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + unsafe { ErrorImpl::display(self.inner.by_ref(), formatter) } + } +} + +impl Debug for Error { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + unsafe { ErrorImpl::debug(self.inner.by_ref(), formatter) } + } +} + +impl Drop for Error { + fn drop(&mut self) { + unsafe { + // Invoke the vtable's drop behavior. + (vtable(self.inner.ptr).object_drop)(self.inner); + } + } +} + +struct ErrorVTable { + object_drop: unsafe fn(Own<ErrorImpl>), + object_ref: unsafe fn(Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static>, + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] + object_mut: unsafe fn(Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static), + object_boxed: unsafe fn(Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>, + object_downcast: unsafe fn(Ref<ErrorImpl>, TypeId) -> Option<Ref<()>>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: unsafe fn(Mut<ErrorImpl>, TypeId) -> Option<Mut<()>>, + object_drop_rest: unsafe fn(Own<ErrorImpl>, TypeId), + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: unsafe fn(Ref<ErrorImpl>) -> Option<&Backtrace>, +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_drop<E>(e: Own<ErrorImpl>) { + // Cast back to ErrorImpl<E> so that the allocator receives the correct + // Layout to deallocate the Box's memory. + let unerased = e.cast::<ErrorImpl<E>>().boxed(); + drop(unerased); +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_drop_front<E>(e: Own<ErrorImpl>, target: TypeId) { + // Drop the fields of ErrorImpl other than E as well as the Box allocation, + // without dropping E itself. This is used by downcast after doing a + // ptr::read to take ownership of the E. + let _ = target; + let unerased = e.cast::<ErrorImpl<ManuallyDrop<E>>>().boxed(); + drop(unerased); +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_ref<E>(e: Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static> +where + E: StdError + Send + Sync + 'static, +{ + // Attach E's native StdError vtable onto a pointer to self._object. + + let unerased = e.cast::<ErrorImpl<E>>(); + + #[cfg(not(anyhow_no_ptr_addr_of))] + return Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )); + + #[cfg(anyhow_no_ptr_addr_of)] + return Ref::new(&unerased.deref()._object); +} + +// Safety: requires layout of *e to match ErrorImpl<E>, and for `e` to be derived +// from a `&mut` +#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] +unsafe fn object_mut<E>(e: Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static) +where + E: StdError + Send + Sync + 'static, +{ + // Attach E's native StdError vtable onto a pointer to self._object. + &mut e.cast::<ErrorImpl<E>>().deref_mut()._object +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_boxed<E>(e: Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static> +where + E: StdError + Send + Sync + 'static, +{ + // Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below. + e.cast::<ErrorImpl<E>>().boxed() +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +unsafe fn object_downcast<E>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>> +where + E: 'static, +{ + if TypeId::of::<E>() == target { + // Caller is looking for an E pointer and e is ErrorImpl<E>, take a + // pointer to its E field. + + let unerased = e.cast::<ErrorImpl<E>>(); + + #[cfg(not(anyhow_no_ptr_addr_of))] + return Some( + Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )) + .cast::<()>(), + ); + + #[cfg(anyhow_no_ptr_addr_of)] + return Some(Ref::new(&unerased.deref()._object).cast::<()>()); + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl<E>. +#[cfg(anyhow_no_ptr_addr_of)] +unsafe fn object_downcast_mut<E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> +where + E: 'static, +{ + if TypeId::of::<E>() == target { + // Caller is looking for an E pointer and e is ErrorImpl<E>, take a + // pointer to its E field. + let unerased = e.cast::<ErrorImpl<E>>().deref_mut(); + Some(Mut::new(&mut unerased._object).cast::<()>()) + } else { + None + } +} + +#[cfg(all(not(backtrace), feature = "backtrace"))] +fn no_backtrace(e: Ref<ErrorImpl>) -> Option<&Backtrace> { + let _ = e; + None +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>. +#[cfg(feature = "std")] +unsafe fn context_downcast<C, E>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>> +where + C: 'static, + E: 'static, +{ + if TypeId::of::<C>() == target { + let unerased = e.cast::<ErrorImpl<ContextError<C, E>>>().deref(); + Some(Ref::new(&unerased._object.context).cast::<()>()) + } else if TypeId::of::<E>() == target { + let unerased = e.cast::<ErrorImpl<ContextError<C, E>>>().deref(); + Some(Ref::new(&unerased._object.error).cast::<()>()) + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>. +#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] +unsafe fn context_downcast_mut<C, E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> +where + C: 'static, + E: 'static, +{ + if TypeId::of::<C>() == target { + let unerased = e.cast::<ErrorImpl<ContextError<C, E>>>().deref_mut(); + Some(Mut::new(&mut unerased._object.context).cast::<()>()) + } else if TypeId::of::<E>() == target { + let unerased = e.cast::<ErrorImpl<ContextError<C, E>>>().deref_mut(); + Some(Mut::new(&mut unerased._object.error).cast::<()>()) + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>. +#[cfg(feature = "std")] +unsafe fn context_drop_rest<C, E>(e: Own<ErrorImpl>, target: TypeId) +where + C: 'static, + E: 'static, +{ + // Called after downcasting by value to either the C or the E and doing a + // ptr::read to take ownership of that value. + if TypeId::of::<C>() == target { + let unerased = e + .cast::<ErrorImpl<ContextError<ManuallyDrop<C>, E>>>() + .boxed(); + drop(unerased); + } else { + let unerased = e + .cast::<ErrorImpl<ContextError<C, ManuallyDrop<E>>>>() + .boxed(); + drop(unerased); + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. +unsafe fn context_chain_downcast<C>(e: Ref<ErrorImpl>, target: TypeId) -> Option<Ref<()>> +where + C: 'static, +{ + let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref(); + if TypeId::of::<C>() == target { + Some(Ref::new(&unerased._object.context).cast::<()>()) + } else { + // Recurse down the context chain per the inner error's vtable. + let source = &unerased._object.error; + (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target) + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. +#[cfg(anyhow_no_ptr_addr_of)] +unsafe fn context_chain_downcast_mut<C>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>> +where + C: 'static, +{ + let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref_mut(); + if TypeId::of::<C>() == target { + Some(Mut::new(&mut unerased._object.context).cast::<()>()) + } else { + // Recurse down the context chain per the inner error's vtable. + let source = &mut unerased._object.error; + (vtable(source.inner.ptr).object_downcast_mut)(source.inner.by_mut(), target) + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. +unsafe fn context_chain_drop_rest<C>(e: Own<ErrorImpl>, target: TypeId) +where + C: 'static, +{ + // Called after downcasting by value to either the C or one of the causes + // and doing a ptr::read to take ownership of that value. + if TypeId::of::<C>() == target { + let unerased = e + .cast::<ErrorImpl<ContextError<ManuallyDrop<C>, Error>>>() + .boxed(); + // Drop the entire rest of the data structure rooted in the next Error. + drop(unerased); + } else { + let unerased = e + .cast::<ErrorImpl<ContextError<C, ManuallyDrop<Error>>>>() + .boxed(); + // Read the Own<ErrorImpl> from the next error. + let inner = unerased._object.error.inner; + drop(unerased); + let vtable = vtable(inner.ptr); + // Recursively drop the next error using the same target typeid. + (vtable.object_drop_rest)(inner, target); + } +} + +// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>. +#[cfg(all(not(backtrace), feature = "backtrace"))] +#[allow(clippy::unnecessary_wraps)] +unsafe fn context_backtrace<C>(e: Ref<ErrorImpl>) -> Option<&Backtrace> +where + C: 'static, +{ + let unerased = e.cast::<ErrorImpl<ContextError<C, Error>>>().deref(); + let backtrace = ErrorImpl::backtrace(unerased._object.error.inner.by_ref()); + Some(backtrace) +} + +// NOTE: If working with `ErrorImpl<()>`, references should be avoided in favor +// of raw pointers and `NonNull`. +// repr C to ensure that E remains in the final position. +#[repr(C)] +pub(crate) struct ErrorImpl<E = ()> { + vtable: &'static ErrorVTable, + backtrace: Option<Backtrace>, + // NOTE: Don't use directly. Use only through vtable. Erased type may have + // different alignment. + _object: E, +} + +// Reads the vtable out of `p`. This is the same as `p.as_ref().vtable`, but +// avoids converting `p` into a reference. +unsafe fn vtable(p: NonNull<ErrorImpl>) -> &'static ErrorVTable { + // NOTE: This assumes that `ErrorVTable` is the first field of ErrorImpl. + *(p.as_ptr() as *const &'static ErrorVTable) +} + +// repr C to ensure that ContextError<C, E> has the same layout as +// ContextError<ManuallyDrop<C>, E> and ContextError<C, ManuallyDrop<E>>. +#[repr(C)] +pub(crate) struct ContextError<C, E> { + pub context: C, + pub error: E, +} + +impl<E> ErrorImpl<E> { + fn erase(&self) -> Ref<ErrorImpl> { + // Erase the concrete type of E but preserve the vtable in self.vtable + // for manipulating the resulting thin pointer. This is analogous to an + // unsize coercion. + Ref::new(self).cast::<ErrorImpl>() + } +} + +impl ErrorImpl { + pub(crate) unsafe fn error(this: Ref<Self>) -> &(dyn StdError + Send + Sync + 'static) { + // Use vtable to attach E's native StdError vtable for the right + // original type E. + (vtable(this.ptr).object_ref)(this).deref() + } + + #[cfg(feature = "std")] + pub(crate) unsafe fn error_mut(this: Mut<Self>) -> &mut (dyn StdError + Send + Sync + 'static) { + // Use vtable to attach E's native StdError vtable for the right + // original type E. + + #[cfg(not(anyhow_no_ptr_addr_of))] + return (vtable(this.ptr).object_ref)(this.by_ref()) + .by_mut() + .deref_mut(); + + #[cfg(anyhow_no_ptr_addr_of)] + return (vtable(this.ptr).object_mut)(this); + } + + #[cfg(any(backtrace, feature = "backtrace"))] + pub(crate) unsafe fn backtrace(this: Ref<Self>) -> &Backtrace { + // This unwrap can only panic if the underlying error's backtrace method + // is nondeterministic, which would only happen in maliciously + // constructed code. + this.deref() + .backtrace + .as_ref() + .or_else(|| { + #[cfg(backtrace)] + return Self::error(this).request_ref::<Backtrace>(); + #[cfg(not(backtrace))] + return (vtable(this.ptr).object_backtrace)(this); + }) + .expect("backtrace capture failed") + } + + #[cfg(backtrace)] + unsafe fn provide<'a>(this: Ref<'a, Self>, demand: &mut Demand<'a>) { + if let Some(backtrace) = &this.deref().backtrace { + demand.provide_ref(backtrace); + } + Self::error(this).provide(demand); + } + + #[cold] + pub(crate) unsafe fn chain(this: Ref<Self>) -> Chain { + Chain::new(Self::error(this)) + } +} + +impl<E> StdError for ErrorImpl<E> +where + E: StdError, +{ + fn source(&self) -> Option<&(dyn StdError + 'static)> { + unsafe { ErrorImpl::error(self.erase()).source() } + } + + #[cfg(backtrace)] + fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + unsafe { ErrorImpl::provide(self.erase(), demand) } + } +} + +impl<E> Debug for ErrorImpl<E> +where + E: Debug, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + unsafe { ErrorImpl::debug(self.erase(), formatter) } + } +} + +impl<E> Display for ErrorImpl<E> +where + E: Display, +{ + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + unsafe { Display::fmt(ErrorImpl::error(self.erase()), formatter) } + } +} + +impl From<Error> for Box<dyn StdError + Send + Sync + 'static> { + #[cold] + fn from(error: Error) -> Self { + let outer = ManuallyDrop::new(error); + unsafe { + // Use vtable to attach ErrorImpl<E>'s native StdError vtable for + // the right original type E. + (vtable(outer.inner.ptr).object_boxed)(outer.inner) + } + } +} + +impl From<Error> for Box<dyn StdError + Send + 'static> { + fn from(error: Error) -> Self { + Box::<dyn StdError + Send + Sync>::from(error) + } +} + +impl From<Error> for Box<dyn StdError + 'static> { + fn from(error: Error) -> Self { + Box::<dyn StdError + Send + Sync>::from(error) + } +} + +#[cfg(feature = "std")] +impl AsRef<dyn StdError + Send + Sync> for Error { + fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) { + &**self + } +} + +#[cfg(feature = "std")] +impl AsRef<dyn StdError> for Error { + fn as_ref(&self) -> &(dyn StdError + 'static) { + &**self + } +} diff --git a/third_party/rust/anyhow/src/fmt.rs b/third_party/rust/anyhow/src/fmt.rs new file mode 100644 index 0000000000..03d8fd3940 --- /dev/null +++ b/third_party/rust/anyhow/src/fmt.rs @@ -0,0 +1,155 @@ +use crate::chain::Chain; +use crate::error::ErrorImpl; +use crate::ptr::Ref; +use core::fmt::{self, Debug, Write}; + +impl ErrorImpl { + pub(crate) unsafe fn display(this: Ref<Self>, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", Self::error(this))?; + + if f.alternate() { + for cause in Self::chain(this).skip(1) { + write!(f, ": {}", cause)?; + } + } + + Ok(()) + } + + pub(crate) unsafe fn debug(this: Ref<Self>, f: &mut fmt::Formatter) -> fmt::Result { + let error = Self::error(this); + + if f.alternate() { + return Debug::fmt(error, f); + } + + write!(f, "{}", error)?; + + if let Some(cause) = error.source() { + write!(f, "\n\nCaused by:")?; + let multiple = cause.source().is_some(); + for (n, error) in Chain::new(cause).enumerate() { + writeln!(f)?; + let mut indented = Indented { + inner: f, + number: if multiple { Some(n) } else { None }, + started: false, + }; + write!(indented, "{}", error)?; + } + } + + #[cfg(any(backtrace, feature = "backtrace"))] + { + use crate::backtrace::BacktraceStatus; + + let backtrace = Self::backtrace(this); + if let BacktraceStatus::Captured = backtrace.status() { + let mut backtrace = backtrace.to_string(); + write!(f, "\n\n")?; + if backtrace.starts_with("stack backtrace:") { + // Capitalize to match "Caused by:" + backtrace.replace_range(0..1, "S"); + } else { + // "stack backtrace:" prefix was removed in + // https://github.com/rust-lang/backtrace-rs/pull/286 + writeln!(f, "Stack backtrace:")?; + } + backtrace.truncate(backtrace.trim_end().len()); + write!(f, "{}", backtrace)?; + } + } + + Ok(()) + } +} + +struct Indented<'a, D> { + inner: &'a mut D, + number: Option<usize>, + started: bool, +} + +impl<T> Write for Indented<'_, T> +where + T: Write, +{ + fn write_str(&mut self, s: &str) -> fmt::Result { + for (i, line) in s.split('\n').enumerate() { + if !self.started { + self.started = true; + match self.number { + Some(number) => write!(self.inner, "{: >5}: ", number)?, + None => self.inner.write_str(" ")?, + } + } else if i > 0 { + self.inner.write_char('\n')?; + if self.number.is_some() { + self.inner.write_str(" ")?; + } else { + self.inner.write_str(" ")?; + } + } + + self.inner.write_str(line)?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn one_digit() { + let input = "verify\nthis"; + let expected = " 2: verify\n this"; + let mut output = String::new(); + + Indented { + inner: &mut output, + number: Some(2), + started: false, + } + .write_str(input) + .unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn two_digits() { + let input = "verify\nthis"; + let expected = " 12: verify\n this"; + let mut output = String::new(); + + Indented { + inner: &mut output, + number: Some(12), + started: false, + } + .write_str(input) + .unwrap(); + + assert_eq!(expected, output); + } + + #[test] + fn no_digits() { + let input = "verify\nthis"; + let expected = " verify\n this"; + let mut output = String::new(); + + Indented { + inner: &mut output, + number: None, + started: false, + } + .write_str(input) + .unwrap(); + + assert_eq!(expected, output); + } +} diff --git a/third_party/rust/anyhow/src/kind.rs b/third_party/rust/anyhow/src/kind.rs new file mode 100644 index 0000000000..f47fe44ba2 --- /dev/null +++ b/third_party/rust/anyhow/src/kind.rs @@ -0,0 +1,116 @@ +// Tagged dispatch mechanism for resolving the behavior of `anyhow!($expr)`. +// +// When anyhow! is given a single expr argument to turn into anyhow::Error, we +// want the resulting Error to pick up the input's implementation of source() +// and backtrace() if it has a std::error::Error impl, otherwise require nothing +// more than Display and Debug. +// +// Expressed in terms of specialization, we want something like: +// +// trait AnyhowNew { +// fn new(self) -> Error; +// } +// +// impl<T> AnyhowNew for T +// where +// T: Display + Debug + Send + Sync + 'static, +// { +// default fn new(self) -> Error { +// /* no std error impl */ +// } +// } +// +// impl<T> AnyhowNew for T +// where +// T: std::error::Error + Send + Sync + 'static, +// { +// fn new(self) -> Error { +// /* use std error's source() and backtrace() */ +// } +// } +// +// Since specialization is not stable yet, instead we rely on autoref behavior +// of method resolution to perform tagged dispatch. Here we have two traits +// AdhocKind and TraitKind that both have an anyhow_kind() method. AdhocKind is +// implemented whether or not the caller's type has a std error impl, while +// TraitKind is implemented only when a std error impl does exist. The ambiguity +// is resolved by AdhocKind requiring an extra autoref so that it has lower +// precedence. +// +// The anyhow! macro will set up the call in this form: +// +// #[allow(unused_imports)] +// use $crate::__private::{AdhocKind, TraitKind}; +// let error = $msg; +// (&error).anyhow_kind().new(error) + +use crate::Error; +use core::fmt::{Debug, Display}; + +#[cfg(feature = "std")] +use crate::StdError; + +pub struct Adhoc; + +pub trait AdhocKind: Sized { + #[inline] + fn anyhow_kind(&self) -> Adhoc { + Adhoc + } +} + +impl<T> AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {} + +impl Adhoc { + #[cold] + pub fn new<M>(self, message: M) -> Error + where + M: Display + Debug + Send + Sync + 'static, + { + Error::from_adhoc(message, backtrace!()) + } +} + +pub struct Trait; + +pub trait TraitKind: Sized { + #[inline] + fn anyhow_kind(&self) -> Trait { + Trait + } +} + +impl<E> TraitKind for E where E: Into<Error> {} + +impl Trait { + #[cold] + pub fn new<E>(self, error: E) -> Error + where + E: Into<Error>, + { + error.into() + } +} + +#[cfg(feature = "std")] +pub struct Boxed; + +#[cfg(feature = "std")] +pub trait BoxedKind: Sized { + #[inline] + fn anyhow_kind(&self) -> Boxed { + Boxed + } +} + +#[cfg(feature = "std")] +impl BoxedKind for Box<dyn StdError + Send + Sync> {} + +#[cfg(feature = "std")] +impl Boxed { + #[cold] + pub fn new(self, error: Box<dyn StdError + Send + Sync>) -> Error { + let backtrace = backtrace_if_absent!(&*error); + Error::from_boxed(error, backtrace) + } +} diff --git a/third_party/rust/anyhow/src/lib.rs b/third_party/rust/anyhow/src/lib.rs new file mode 100644 index 0000000000..e570d6e9e3 --- /dev/null +++ b/third_party/rust/anyhow/src/lib.rs @@ -0,0 +1,680 @@ +//! [![github]](https://github.com/dtolnay/anyhow) [![crates-io]](https://crates.io/crates/anyhow) [![docs-rs]](https://docs.rs/anyhow) +//! +//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github +//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs +//! +//! <br> +//! +//! This library provides [`anyhow::Error`][Error], a trait object based error +//! type for easy idiomatic error handling in Rust applications. +//! +//! <br> +//! +//! # Details +//! +//! - Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as +//! the return type of any fallible function. +//! +//! Within the function, use `?` to easily propagate any error that implements +//! the `std::error::Error` trait. +//! +//! ``` +//! # pub trait Deserialize {} +//! # +//! # mod serde_json { +//! # use super::Deserialize; +//! # use std::io; +//! # +//! # pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> { +//! # unimplemented!() +//! # } +//! # } +//! # +//! # struct ClusterMap; +//! # +//! # impl Deserialize for ClusterMap {} +//! # +//! use anyhow::Result; +//! +//! fn get_cluster_info() -> Result<ClusterMap> { +//! let config = std::fs::read_to_string("cluster.json")?; +//! let map: ClusterMap = serde_json::from_str(&config)?; +//! Ok(map) +//! } +//! # +//! # fn main() {} +//! ``` +//! +//! - Attach context to help the person troubleshooting the error understand +//! where things went wrong. A low-level error like "No such file or +//! directory" can be annoying to debug without more context about what higher +//! level step the application was in the middle of. +//! +//! ``` +//! # struct It; +//! # +//! # impl It { +//! # fn detach(&self) -> Result<()> { +//! # unimplemented!() +//! # } +//! # } +//! # +//! use anyhow::{Context, Result}; +//! +//! fn main() -> Result<()> { +//! # return Ok(()); +//! # +//! # const _: &str = stringify! { +//! ... +//! # }; +//! # +//! # let it = It; +//! # let path = "./path/to/instrs.json"; +//! # +//! it.detach().context("Failed to detach the important thing")?; +//! +//! let content = std::fs::read(path) +//! .with_context(|| format!("Failed to read instrs from {}", path))?; +//! # +//! # const _: &str = stringify! { +//! ... +//! # }; +//! # +//! # Ok(()) +//! } +//! ``` +//! +//! ```console +//! Error: Failed to read instrs from ./path/to/instrs.json +//! +//! Caused by: +//! No such file or directory (os error 2) +//! ``` +//! +//! - Downcasting is supported and can be by value, by shared reference, or by +//! mutable reference as needed. +//! +//! ``` +//! # use anyhow::anyhow; +//! # use std::fmt::{self, Display}; +//! # use std::task::Poll; +//! # +//! # #[derive(Debug)] +//! # enum DataStoreError { +//! # Censored(()), +//! # } +//! # +//! # impl Display for DataStoreError { +//! # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +//! # unimplemented!() +//! # } +//! # } +//! # +//! # impl std::error::Error for DataStoreError {} +//! # +//! # const REDACTED_CONTENT: () = (); +//! # +//! # let error = anyhow!("..."); +//! # let root_cause = &error; +//! # +//! # let ret = +//! // If the error was caused by redaction, then return a +//! // tombstone instead of the content. +//! match root_cause.downcast_ref::<DataStoreError>() { +//! Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)), +//! None => Err(error), +//! } +//! # ; +//! ``` +//! +//! - If using the nightly channel, or stable with `features = ["backtrace"]`, a +//! backtrace is captured and printed with the error if the underlying error +//! type does not already provide its own. In order to see backtraces, they +//! must be enabled through the environment variables described in +//! [`std::backtrace`]: +//! +//! - If you want panics and errors to both have backtraces, set +//! `RUST_BACKTRACE=1`; +//! - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`; +//! - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and +//! `RUST_LIB_BACKTRACE=0`. +//! +//! The tracking issue for this feature is [rust-lang/rust#53487]. +//! +//! [`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables +//! [rust-lang/rust#53487]: https://github.com/rust-lang/rust/issues/53487 +//! +//! - Anyhow works with any error type that has an impl of `std::error::Error`, +//! including ones defined in your crate. We do not bundle a `derive(Error)` +//! macro but you can write the impls yourself or use a standalone macro like +//! [thiserror]. +//! +//! [thiserror]: https://github.com/dtolnay/thiserror +//! +//! ``` +//! use thiserror::Error; +//! +//! #[derive(Error, Debug)] +//! pub enum FormatError { +//! #[error("Invalid header (expected {expected:?}, got {found:?})")] +//! InvalidHeader { +//! expected: String, +//! found: String, +//! }, +//! #[error("Missing attribute: {0}")] +//! MissingAttribute(String), +//! } +//! ``` +//! +//! - One-off error messages can be constructed using the `anyhow!` macro, which +//! supports string interpolation and produces an `anyhow::Error`. +//! +//! ``` +//! # use anyhow::{anyhow, Result}; +//! # +//! # fn demo() -> Result<()> { +//! # let missing = "..."; +//! return Err(anyhow!("Missing attribute: {}", missing)); +//! # Ok(()) +//! # } +//! ``` +//! +//! A `bail!` macro is provided as a shorthand for the same early return. +//! +//! ``` +//! # use anyhow::{bail, Result}; +//! # +//! # fn demo() -> Result<()> { +//! # let missing = "..."; +//! bail!("Missing attribute: {}", missing); +//! # Ok(()) +//! # } +//! ``` +//! +//! <br> +//! +//! # No-std support +//! +//! In no_std mode, the same API is almost all available and works the same way. +//! To depend on Anyhow in no_std mode, disable our default enabled "std" +//! feature in Cargo.toml. A global allocator is required. +//! +//! ```toml +//! [dependencies] +//! anyhow = { version = "1.0", default-features = false } +//! ``` +//! +//! Since the `?`-based error conversions would normally rely on the +//! `std::error::Error` trait which is only available through std, no_std mode +//! will require an explicit `.map_err(Error::msg)` when working with a +//! non-Anyhow error type inside a function that returns Anyhow's error type. + +#![doc(html_root_url = "https://docs.rs/anyhow/1.0.69")] +#![cfg_attr(backtrace, feature(error_generic_member_access, provide_any))] +#![cfg_attr(doc_cfg, feature(doc_cfg))] +#![cfg_attr(not(feature = "std"), no_std)] +#![deny(dead_code, unused_imports, unused_mut)] +#![allow( + clippy::doc_markdown, + clippy::enum_glob_use, + clippy::explicit_auto_deref, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::module_name_repetitions, + clippy::must_use_candidate, + clippy::needless_doctest_main, + clippy::new_ret_no_self, + clippy::redundant_else, + clippy::return_self_not_must_use, + clippy::unused_self, + clippy::used_underscore_binding, + clippy::wildcard_imports, + clippy::wrong_self_convention +)] + +extern crate alloc; + +#[macro_use] +mod backtrace; +mod chain; +mod context; +mod ensure; +mod error; +mod fmt; +mod kind; +mod macros; +mod ptr; +mod wrapper; + +use crate::error::ErrorImpl; +use crate::ptr::Own; +use core::fmt::Display; + +#[cfg(not(feature = "std"))] +use core::fmt::Debug; + +#[cfg(feature = "std")] +use std::error::Error as StdError; + +#[cfg(not(feature = "std"))] +trait StdError: Debug + Display { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + None + } +} + +pub use anyhow as format_err; + +/// The `Error` type, a wrapper around a dynamic error type. +/// +/// `Error` works a lot like `Box<dyn std::error::Error>`, but with these +/// differences: +/// +/// - `Error` requires that the error is `Send`, `Sync`, and `'static`. +/// - `Error` guarantees that a backtrace is available, even if the underlying +/// error type does not provide one. +/// - `Error` is represented as a narrow pointer — exactly one word in +/// size instead of two. +/// +/// <br> +/// +/// # Display representations +/// +/// When you print an error object using "{}" or to_string(), only the outermost +/// underlying error or context is printed, not any of the lower level causes. +/// This is exactly as if you had called the Display impl of the error from +/// which you constructed your anyhow::Error. +/// +/// ```console +/// Failed to read instrs from ./path/to/instrs.json +/// ``` +/// +/// To print causes as well using anyhow's default formatting of causes, use the +/// alternate selector "{:#}". +/// +/// ```console +/// Failed to read instrs from ./path/to/instrs.json: No such file or directory (os error 2) +/// ``` +/// +/// The Debug format "{:?}" includes your backtrace if one was captured. Note +/// that this is the representation you get by default if you return an error +/// from `fn main` instead of printing it explicitly yourself. +/// +/// ```console +/// Error: Failed to read instrs from ./path/to/instrs.json +/// +/// Caused by: +/// No such file or directory (os error 2) +/// ``` +/// +/// and if there is a backtrace available: +/// +/// ```console +/// Error: Failed to read instrs from ./path/to/instrs.json +/// +/// Caused by: +/// No such file or directory (os error 2) +/// +/// Stack backtrace: +/// 0: <E as anyhow::context::ext::StdError>::ext_context +/// at /git/anyhow/src/backtrace.rs:26 +/// 1: core::result::Result<T,E>::map_err +/// at /git/rustc/src/libcore/result.rs:596 +/// 2: anyhow::context::<impl anyhow::Context<T,E> for core::result::Result<T,E>>::with_context +/// at /git/anyhow/src/context.rs:58 +/// 3: testing::main +/// at src/main.rs:5 +/// 4: std::rt::lang_start +/// at /git/rustc/src/libstd/rt.rs:61 +/// 5: main +/// 6: __libc_start_main +/// 7: _start +/// ``` +/// +/// To see a conventional struct-style Debug representation, use "{:#?}". +/// +/// ```console +/// Error { +/// context: "Failed to read instrs from ./path/to/instrs.json", +/// source: Os { +/// code: 2, +/// kind: NotFound, +/// message: "No such file or directory", +/// }, +/// } +/// ``` +/// +/// If none of the built-in representations are appropriate and you would prefer +/// to render the error and its cause chain yourself, it can be done something +/// like this: +/// +/// ``` +/// use anyhow::{Context, Result}; +/// +/// fn main() { +/// if let Err(err) = try_main() { +/// eprintln!("ERROR: {}", err); +/// err.chain().skip(1).for_each(|cause| eprintln!("because: {}", cause)); +/// std::process::exit(1); +/// } +/// } +/// +/// fn try_main() -> Result<()> { +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # Ok(()) +/// } +/// ``` +#[cfg_attr(not(doc), repr(transparent))] +pub struct Error { + inner: Own<ErrorImpl>, +} + +/// Iterator of a chain of source errors. +/// +/// This type is the iterator returned by [`Error::chain`]. +/// +/// # Example +/// +/// ``` +/// use anyhow::Error; +/// use std::io; +/// +/// pub fn underlying_io_error_kind(error: &Error) -> Option<io::ErrorKind> { +/// for cause in error.chain() { +/// if let Some(io_error) = cause.downcast_ref::<io::Error>() { +/// return Some(io_error.kind()); +/// } +/// } +/// None +/// } +/// ``` +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +#[derive(Clone)] +pub struct Chain<'a> { + state: crate::chain::ChainState<'a>, +} + +/// `Result<T, Error>` +/// +/// This is a reasonable return type to use throughout your application but also +/// for `fn main`; if you do, failures will be printed along with any +/// [context][Context] and a backtrace if one was captured. +/// +/// `anyhow::Result` may be used with one *or* two type parameters. +/// +/// ```rust +/// use anyhow::Result; +/// +/// # const IGNORE: &str = stringify! { +/// fn demo1() -> Result<T> {...} +/// // ^ equivalent to std::result::Result<T, anyhow::Error> +/// +/// fn demo2() -> Result<T, OtherError> {...} +/// // ^ equivalent to std::result::Result<T, OtherError> +/// # }; +/// ``` +/// +/// # Example +/// +/// ``` +/// # pub trait Deserialize {} +/// # +/// # mod serde_json { +/// # use super::Deserialize; +/// # use std::io; +/// # +/// # pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> { +/// # unimplemented!() +/// # } +/// # } +/// # +/// # #[derive(Debug)] +/// # struct ClusterMap; +/// # +/// # impl Deserialize for ClusterMap {} +/// # +/// use anyhow::Result; +/// +/// fn main() -> Result<()> { +/// # return Ok(()); +/// let config = std::fs::read_to_string("cluster.json")?; +/// let map: ClusterMap = serde_json::from_str(&config)?; +/// println!("cluster info: {:#?}", map); +/// Ok(()) +/// } +/// ``` +pub type Result<T, E = Error> = core::result::Result<T, E>; + +/// Provides the `context` method for `Result`. +/// +/// This trait is sealed and cannot be implemented for types outside of +/// `anyhow`. +/// +/// <br> +/// +/// # Example +/// +/// ``` +/// use anyhow::{Context, Result}; +/// use std::fs; +/// use std::path::PathBuf; +/// +/// pub struct ImportantThing { +/// path: PathBuf, +/// } +/// +/// impl ImportantThing { +/// # const IGNORE: &'static str = stringify! { +/// pub fn detach(&mut self) -> Result<()> {...} +/// # }; +/// # fn detach(&mut self) -> Result<()> { +/// # unimplemented!() +/// # } +/// } +/// +/// pub fn do_it(mut it: ImportantThing) -> Result<Vec<u8>> { +/// it.detach().context("Failed to detach the important thing")?; +/// +/// let path = &it.path; +/// let content = fs::read(path) +/// .with_context(|| format!("Failed to read instrs from {}", path.display()))?; +/// +/// Ok(content) +/// } +/// ``` +/// +/// When printed, the outermost context would be printed first and the lower +/// level underlying causes would be enumerated below. +/// +/// ```console +/// Error: Failed to read instrs from ./path/to/instrs.json +/// +/// Caused by: +/// No such file or directory (os error 2) +/// ``` +/// +/// Refer to the [Display representations] documentation for other forms in +/// which this context chain can be rendered. +/// +/// [Display representations]: Error#display-representations +/// +/// <br> +/// +/// # Effect on downcasting +/// +/// After attaching context of type `C` onto an error of type `E`, the resulting +/// `anyhow::Error` may be downcast to `C` **or** to `E`. +/// +/// That is, in codebases that rely on downcasting, Anyhow's context supports +/// both of the following use cases: +/// +/// - **Attaching context whose type is insignificant onto errors whose type +/// is used in downcasts.** +/// +/// In other error libraries whose context is not designed this way, it can +/// be risky to introduce context to existing code because new context might +/// break existing working downcasts. In Anyhow, any downcast that worked +/// before adding context will continue to work after you add a context, so +/// you should freely add human-readable context to errors wherever it would +/// be helpful. +/// +/// ``` +/// # use anyhow::bail; +/// # use thiserror::Error; +/// # +/// # #[derive(Error, Debug)] +/// # #[error("???")] +/// # struct SuspiciousError; +/// # +/// # fn helper() -> Result<()> { +/// # bail!(SuspiciousError); +/// # } +/// # +/// use anyhow::{Context, Result}; +/// +/// fn do_it() -> Result<()> { +/// helper().context("Failed to complete the work")?; +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unreachable!() +/// } +/// +/// fn main() { +/// let err = do_it().unwrap_err(); +/// if let Some(e) = err.downcast_ref::<SuspiciousError>() { +/// // If helper() returned SuspiciousError, this downcast will +/// // correctly succeed even with the context in between. +/// # return; +/// } +/// # panic!("expected downcast to succeed"); +/// } +/// ``` +/// +/// - **Attaching context whose type is used in downcasts onto errors whose +/// type is insignificant.** +/// +/// Some codebases prefer to use machine-readable context to categorize +/// lower level errors in a way that will be actionable to higher levels of +/// the application. +/// +/// ``` +/// # use anyhow::bail; +/// # use thiserror::Error; +/// # +/// # #[derive(Error, Debug)] +/// # #[error("???")] +/// # struct HelperFailed; +/// # +/// # fn helper() -> Result<()> { +/// # bail!("no such file or directory"); +/// # } +/// # +/// use anyhow::{Context, Result}; +/// +/// fn do_it() -> Result<()> { +/// helper().context(HelperFailed)?; +/// # const IGNORE: &str = stringify! { +/// ... +/// # }; +/// # unreachable!() +/// } +/// +/// fn main() { +/// let err = do_it().unwrap_err(); +/// if let Some(e) = err.downcast_ref::<HelperFailed>() { +/// // If helper failed, this downcast will succeed because +/// // HelperFailed is the context that has been attached to +/// // that error. +/// # return; +/// } +/// # panic!("expected downcast to succeed"); +/// } +/// ``` +pub trait Context<T, E>: context::private::Sealed { + /// Wrap the error value with additional context. + fn context<C>(self, context: C) -> Result<T, Error> + where + C: Display + Send + Sync + 'static; + + /// Wrap the error value with additional context that is evaluated lazily + /// only once an error does occur. + fn with_context<C, F>(self, f: F) -> Result<T, Error> + where + C: Display + Send + Sync + 'static, + F: FnOnce() -> C; +} + +/// Equivalent to Ok::<_, anyhow::Error>(value). +/// +/// This simplifies creation of an anyhow::Result in places where type inference +/// cannot deduce the `E` type of the result — without needing to write +/// `Ok::<_, anyhow::Error>(value)`. +/// +/// One might think that `anyhow::Result::Ok(value)` would work in such cases +/// but it does not. +/// +/// ```console +/// error[E0282]: type annotations needed for `std::result::Result<i32, E>` +/// --> src/main.rs:11:13 +/// | +/// 11 | let _ = anyhow::Result::Ok(1); +/// | - ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `E` declared on the enum `Result` +/// | | +/// | consider giving this pattern the explicit type `std::result::Result<i32, E>`, where the type parameter `E` is specified +/// ``` +#[allow(non_snake_case)] +pub fn Ok<T>(t: T) -> Result<T> { + Result::Ok(t) +} + +// Not public API. Referenced by macro-generated code. +#[doc(hidden)] +pub mod __private { + use crate::Error; + use alloc::fmt; + use core::fmt::Arguments; + + pub use crate::ensure::{BothDebug, NotBothDebug}; + pub use alloc::format; + pub use core::result::Result::Err; + pub use core::{concat, format_args, stringify}; + + #[doc(hidden)] + pub mod kind { + pub use crate::kind::{AdhocKind, TraitKind}; + + #[cfg(feature = "std")] + pub use crate::kind::BoxedKind; + } + + #[doc(hidden)] + #[inline] + #[cold] + pub fn format_err(args: Arguments) -> Error { + #[cfg(anyhow_no_fmt_arguments_as_str)] + let fmt_arguments_as_str = None::<&str>; + #[cfg(not(anyhow_no_fmt_arguments_as_str))] + let fmt_arguments_as_str = args.as_str(); + + if let Some(message) = fmt_arguments_as_str { + // anyhow!("literal"), can downcast to &'static str + Error::msg(message) + } else { + // anyhow!("interpolate {var}"), can downcast to String + Error::msg(fmt::format(args)) + } + } + + #[doc(hidden)] + #[inline] + #[cold] + #[must_use] + pub fn must_use(error: Error) -> Error { + error + } +} diff --git a/third_party/rust/anyhow/src/macros.rs b/third_party/rust/anyhow/src/macros.rs new file mode 100644 index 0000000000..6dd22743b7 --- /dev/null +++ b/third_party/rust/anyhow/src/macros.rs @@ -0,0 +1,231 @@ +/// Return early with an error. +/// +/// This macro is equivalent to `return Err(`[`anyhow!($args...)`][anyhow!]`)`. +/// +/// The surrounding function's or closure's return value is required to be +/// `Result<_,`[`anyhow::Error`][crate::Error]`>`. +/// +/// [anyhow!]: crate::anyhow +/// +/// # Example +/// +/// ``` +/// # use anyhow::{bail, Result}; +/// # +/// # fn has_permission(user: usize, resource: usize) -> bool { +/// # true +/// # } +/// # +/// # fn main() -> Result<()> { +/// # let user = 0; +/// # let resource = 0; +/// # +/// if !has_permission(user, resource) { +/// bail!("permission denied for accessing {}", resource); +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// # use anyhow::{bail, Result}; +/// # use thiserror::Error; +/// # +/// # const MAX_DEPTH: usize = 1; +/// # +/// #[derive(Error, Debug)] +/// enum ScienceError { +/// #[error("recursion limit exceeded")] +/// RecursionLimitExceeded, +/// # #[error("...")] +/// # More = (stringify! { +/// ... +/// # }, 1).1, +/// } +/// +/// # fn main() -> Result<()> { +/// # let depth = 0; +/// # +/// if depth > MAX_DEPTH { +/// bail!(ScienceError::RecursionLimitExceeded); +/// } +/// # Ok(()) +/// # } +/// ``` +#[macro_export] +macro_rules! bail { + ($msg:literal $(,)?) => { + return $crate::__private::Err($crate::__anyhow!($msg)) + }; + ($err:expr $(,)?) => { + return $crate::__private::Err($crate::__anyhow!($err)) + }; + ($fmt:expr, $($arg:tt)*) => { + return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*)) + }; +} + +/// Return early with an error if a condition is not satisfied. +/// +/// This macro is equivalent to `if !$cond { return +/// Err(`[`anyhow!($args...)`][anyhow!]`); }`. +/// +/// The surrounding function's or closure's return value is required to be +/// `Result<_,`[`anyhow::Error`][crate::Error]`>`. +/// +/// Analogously to `assert!`, `ensure!` takes a condition and exits the function +/// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error` +/// rather than panicking. +/// +/// [anyhow!]: crate::anyhow +/// +/// # Example +/// +/// ``` +/// # use anyhow::{ensure, Result}; +/// # +/// # fn main() -> Result<()> { +/// # let user = 0; +/// # +/// ensure!(user == 0, "only user 0 is allowed"); +/// # Ok(()) +/// # } +/// ``` +/// +/// ``` +/// # use anyhow::{ensure, Result}; +/// # use thiserror::Error; +/// # +/// # const MAX_DEPTH: usize = 1; +/// # +/// #[derive(Error, Debug)] +/// enum ScienceError { +/// #[error("recursion limit exceeded")] +/// RecursionLimitExceeded, +/// # #[error("...")] +/// # More = (stringify! { +/// ... +/// # }, 1).1, +/// } +/// +/// # fn main() -> Result<()> { +/// # let depth = 0; +/// # +/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded); +/// # Ok(()) +/// # } +/// ``` +#[cfg(doc)] +#[macro_export] +macro_rules! ensure { + ($cond:expr $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::Error::msg( + $crate::__private::concat!("Condition failed: `", $crate::__private::stringify!($cond), "`") + )); + } + }; + ($cond:expr, $msg:literal $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($msg)); + } + }; + ($cond:expr, $err:expr $(,)?) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($err)); + } + }; + ($cond:expr, $fmt:expr, $($arg:tt)*) => { + if !$cond { + return $crate::__private::Err($crate::__anyhow!($fmt, $($arg)*)); + } + }; +} + +#[cfg(not(doc))] +#[macro_export] +macro_rules! ensure { + ($($tt:tt)*) => { + $crate::__parse_ensure!( + /* state */ 0 + /* stack */ () + /* bail */ ($($tt)*) + /* fuel */ (~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~) + /* parse */ {()} + /* dup */ ($($tt)*) + /* rest */ $($tt)* + ) + }; +} + +/// Construct an ad-hoc error from a string or existing non-`anyhow` error +/// value. +/// +/// This evaluates to an [`Error`][crate::Error]. It can take either just a +/// string, or a format string with arguments. It also can take any custom type +/// which implements `Debug` and `Display`. +/// +/// If called with a single argument whose type implements `std::error::Error` +/// (in addition to `Debug` and `Display`, which are always required), then that +/// Error impl's `source` is preserved as the `source` of the resulting +/// `anyhow::Error`. +/// +/// # Example +/// +/// ``` +/// # type V = (); +/// # +/// use anyhow::{anyhow, Result}; +/// +/// fn lookup(key: &str) -> Result<V> { +/// if key.len() != 16 { +/// return Err(anyhow!("key length must be 16 characters, got {:?}", key)); +/// } +/// +/// // ... +/// # Ok(()) +/// } +/// ``` +#[macro_export] +macro_rules! anyhow { + ($msg:literal $(,)?) => { + $crate::__private::must_use({ + let error = $crate::__private::format_err($crate::__private::format_args!($msg)); + error + }) + }; + ($err:expr $(,)?) => { + $crate::__private::must_use({ + use $crate::__private::kind::*; + let error = match $err { + error => (&error).anyhow_kind().new(error), + }; + error + }) + }; + ($fmt:expr, $($arg:tt)*) => { + $crate::Error::msg($crate::__private::format!($fmt, $($arg)*)) + }; +} + +// Not public API. This is used in the implementation of some of the other +// macros, in which the must_use call is not needed because the value is known +// to be used. +#[doc(hidden)] +#[macro_export] +macro_rules! __anyhow { + ($msg:literal $(,)?) => ({ + let error = $crate::__private::format_err($crate::__private::format_args!($msg)); + error + }); + ($err:expr $(,)?) => ({ + use $crate::__private::kind::*; + let error = match $err { + error => (&error).anyhow_kind().new(error), + }; + error + }); + ($fmt:expr, $($arg:tt)*) => { + $crate::Error::msg($crate::__private::format!($fmt, $($arg)*)) + }; +} diff --git a/third_party/rust/anyhow/src/ptr.rs b/third_party/rust/anyhow/src/ptr.rs new file mode 100644 index 0000000000..c7fe488b6f --- /dev/null +++ b/third_party/rust/anyhow/src/ptr.rs @@ -0,0 +1,199 @@ +use alloc::boxed::Box; +use core::marker::PhantomData; +use core::ptr::NonNull; + +#[repr(transparent)] +pub struct Own<T> +where + T: ?Sized, +{ + pub ptr: NonNull<T>, +} + +unsafe impl<T> Send for Own<T> where T: ?Sized {} + +unsafe impl<T> Sync for Own<T> where T: ?Sized {} + +impl<T> Copy for Own<T> where T: ?Sized {} + +impl<T> Clone for Own<T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<T> Own<T> +where + T: ?Sized, +{ + pub fn new(ptr: Box<T>) -> Self { + Own { + ptr: unsafe { NonNull::new_unchecked(Box::into_raw(ptr)) }, + } + } + + pub fn cast<U: CastTo>(self) -> Own<U::Target> { + Own { + ptr: self.ptr.cast(), + } + } + + pub unsafe fn boxed(self) -> Box<T> { + Box::from_raw(self.ptr.as_ptr()) + } + + pub fn by_ref(&self) -> Ref<T> { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub fn by_mut(&mut self) -> Mut<T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } +} + +#[repr(transparent)] +pub struct Ref<'a, T> +where + T: ?Sized, +{ + pub ptr: NonNull<T>, + lifetime: PhantomData<&'a T>, +} + +impl<'a, T> Copy for Ref<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Ref<'a, T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Ref<'a, T> +where + T: ?Sized, +{ + pub fn new(ptr: &'a T) -> Self { + Ref { + ptr: NonNull::from(ptr), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn from_raw(ptr: NonNull<T>) -> Self { + Ref { + ptr, + lifetime: PhantomData, + } + } + + pub fn cast<U: CastTo>(self) -> Ref<'a, U::Target> { + Ref { + ptr: self.ptr.cast(), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn by_mut(self) -> Mut<'a, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn as_ptr(self) -> *const T { + self.ptr.as_ptr() as *const T + } + + pub unsafe fn deref(self) -> &'a T { + &*self.ptr.as_ptr() + } +} + +#[repr(transparent)] +pub struct Mut<'a, T> +where + T: ?Sized, +{ + pub ptr: NonNull<T>, + lifetime: PhantomData<&'a mut T>, +} + +impl<'a, T> Copy for Mut<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Mut<'a, T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Mut<'a, T> +where + T: ?Sized, +{ + #[cfg(anyhow_no_ptr_addr_of)] + pub fn new(ptr: &'a mut T) -> Self { + Mut { + ptr: NonNull::from(ptr), + lifetime: PhantomData, + } + } + + pub fn cast<U: CastTo>(self) -> Mut<'a, U::Target> { + Mut { + ptr: self.ptr.cast(), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn by_ref(self) -> Ref<'a, T> { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub fn extend<'b>(self) -> Mut<'b, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub unsafe fn deref_mut(self) -> &'a mut T { + &mut *self.ptr.as_ptr() + } +} + +impl<'a, T> Mut<'a, T> { + pub unsafe fn read(self) -> T { + self.ptr.as_ptr().read() + } +} + +// Force turbofish on all calls of `.cast::<U>()`. +pub trait CastTo { + type Target; +} + +impl<T> CastTo for T { + type Target = T; +} diff --git a/third_party/rust/anyhow/src/wrapper.rs b/third_party/rust/anyhow/src/wrapper.rs new file mode 100644 index 0000000000..5f18a50313 --- /dev/null +++ b/third_party/rust/anyhow/src/wrapper.rs @@ -0,0 +1,81 @@ +use crate::StdError; +use core::fmt::{self, Debug, Display}; + +#[cfg(backtrace)] +use std::any::Demand; + +#[repr(transparent)] +pub struct MessageError<M>(pub M); + +impl<M> Debug for MessageError<M> +where + M: Display + Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.0, f) + } +} + +impl<M> Display for MessageError<M> +where + M: Display + Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {} + +#[repr(transparent)] +pub struct DisplayError<M>(pub M); + +impl<M> Debug for DisplayError<M> +where + M: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl<M> Display for DisplayError<M> +where + M: Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +impl<M> StdError for DisplayError<M> where M: Display + 'static {} + +#[cfg(feature = "std")] +#[repr(transparent)] +pub struct BoxedError(pub Box<dyn StdError + Send + Sync>); + +#[cfg(feature = "std")] +impl Debug for BoxedError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(&self.0, f) + } +} + +#[cfg(feature = "std")] +impl Display for BoxedError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } +} + +#[cfg(feature = "std")] +impl StdError for BoxedError { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + self.0.source() + } + + #[cfg(backtrace)] + fn provide<'a>(&'a self, demand: &mut Demand<'a>) { + self.0.provide(demand); + } +} |