diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/anyhow/src/kind.rs | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/anyhow/src/kind.rs')
-rw-r--r-- | vendor/anyhow/src/kind.rs | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/vendor/anyhow/src/kind.rs b/vendor/anyhow/src/kind.rs new file mode 100644 index 000000000..59857057d --- /dev/null +++ b/vendor/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) + } +} |