diff options
Diffstat (limited to 'vendor/clap_builder/src/error/mod.rs')
-rw-r--r-- | vendor/clap_builder/src/error/mod.rs | 923 |
1 files changed, 0 insertions, 923 deletions
diff --git a/vendor/clap_builder/src/error/mod.rs b/vendor/clap_builder/src/error/mod.rs deleted file mode 100644 index af90e27..0000000 --- a/vendor/clap_builder/src/error/mod.rs +++ /dev/null @@ -1,923 +0,0 @@ -//! Error reporting - -#![cfg_attr(not(feature = "error-context"), allow(dead_code))] -#![cfg_attr(not(feature = "error-context"), allow(unused_imports))] -#![cfg_attr(not(feature = "error-context"), allow(unused_variables))] -#![cfg_attr(not(feature = "error-context"), allow(unused_mut))] -#![cfg_attr(not(feature = "error-context"), allow(clippy::let_and_return))] - -// Std -use std::{ - borrow::Cow, - convert::From, - error, - fmt::{self, Debug, Display, Formatter}, - io::{self}, - result::Result as StdResult, -}; - -// Internal -use crate::builder::StyledStr; -use crate::builder::Styles; -use crate::output::fmt::Colorizer; -use crate::output::fmt::Stream; -use crate::parser::features::suggestions; -use crate::util::FlatMap; -use crate::util::{color::ColorChoice, safe_exit, SUCCESS_CODE, USAGE_CODE}; -use crate::Command; - -#[cfg(feature = "error-context")] -mod context; -mod format; -mod kind; - -pub use format::ErrorFormatter; -pub use format::KindFormatter; -pub use kind::ErrorKind; - -#[cfg(feature = "error-context")] -pub use context::ContextKind; -#[cfg(feature = "error-context")] -pub use context::ContextValue; -#[cfg(feature = "error-context")] -pub use format::RichFormatter; - -#[cfg(not(feature = "error-context"))] -pub use KindFormatter as DefaultFormatter; -#[cfg(feature = "error-context")] -pub use RichFormatter as DefaultFormatter; - -/// Short hand for [`Result`] type -/// -/// [`Result`]: std::result::Result -pub type Result<T, E = Error> = StdResult<T, E>; - -/// Command Line Argument Parser Error -/// -/// See [`Command::error`] to create an error. -/// -/// [`Command::error`]: crate::Command::error -pub struct Error<F: ErrorFormatter = DefaultFormatter> { - inner: Box<ErrorInner>, - phantom: std::marker::PhantomData<F>, -} - -#[derive(Debug)] -struct ErrorInner { - kind: ErrorKind, - #[cfg(feature = "error-context")] - context: FlatMap<ContextKind, ContextValue>, - message: Option<Message>, - source: Option<Box<dyn error::Error + Send + Sync>>, - help_flag: Option<&'static str>, - styles: Styles, - color_when: ColorChoice, - color_help_when: ColorChoice, - backtrace: Option<Backtrace>, -} - -impl<F: ErrorFormatter> Error<F> { - /// Create an unformatted error - /// - /// This is for you need to pass the error up to - /// a place that has access to the `Command` at which point you can call [`Error::format`]. - /// - /// Prefer [`Command::error`] for generating errors. - /// - /// [`Command::error`]: crate::Command::error - pub fn raw(kind: ErrorKind, message: impl std::fmt::Display) -> Self { - Self::new(kind).set_message(message.to_string()) - } - - /// Format the existing message with the Command's context - #[must_use] - pub fn format(mut self, cmd: &mut Command) -> Self { - cmd._build_self(false); - let usage = cmd.render_usage_(); - if let Some(message) = self.inner.message.as_mut() { - message.format(cmd, usage); - } - self.with_cmd(cmd) - } - - /// Create an error with a pre-defined message - /// - /// See also - /// - [`Error::insert`] - /// - [`Error::with_cmd`] - /// - /// # Example - /// - /// ```rust - /// # #[cfg(feature = "error-context")] { - /// # use clap_builder as clap; - /// # use clap::error::ErrorKind; - /// # use clap::error::ContextKind; - /// # use clap::error::ContextValue; - /// - /// let cmd = clap::Command::new("prog"); - /// - /// let mut err = clap::Error::new(ErrorKind::ValueValidation) - /// .with_cmd(&cmd); - /// err.insert(ContextKind::InvalidArg, ContextValue::String("--foo".to_owned())); - /// err.insert(ContextKind::InvalidValue, ContextValue::String("bar".to_owned())); - /// - /// err.print(); - /// # } - /// ``` - pub fn new(kind: ErrorKind) -> Self { - Self { - inner: Box::new(ErrorInner { - kind, - #[cfg(feature = "error-context")] - context: FlatMap::new(), - message: None, - source: None, - help_flag: None, - styles: Styles::plain(), - color_when: ColorChoice::Never, - color_help_when: ColorChoice::Never, - backtrace: Backtrace::new(), - }), - phantom: Default::default(), - } - } - - /// Apply [`Command`]'s formatting to the error - /// - /// Generally, this is used with [`Error::new`] - pub fn with_cmd(self, cmd: &Command) -> Self { - self.set_styles(cmd.get_styles().clone()) - .set_color(cmd.get_color()) - .set_colored_help(cmd.color_help()) - .set_help_flag(format::get_help_flag(cmd)) - } - - /// Apply an alternative formatter to the error - /// - /// # Example - /// - /// ```rust - /// # use clap_builder as clap; - /// # use clap::Command; - /// # use clap::Arg; - /// # use clap::error::KindFormatter; - /// let cmd = Command::new("foo") - /// .arg(Arg::new("input").required(true)); - /// let matches = cmd - /// .try_get_matches_from(["foo", "input.txt"]) - /// .map_err(|e| e.apply::<KindFormatter>()) - /// .unwrap_or_else(|e| e.exit()); - /// ``` - pub fn apply<EF: ErrorFormatter>(self) -> Error<EF> { - Error { - inner: self.inner, - phantom: Default::default(), - } - } - - /// Type of error for programmatic processing - pub fn kind(&self) -> ErrorKind { - self.inner.kind - } - - /// Additional information to further qualify the error - #[cfg(feature = "error-context")] - pub fn context(&self) -> impl Iterator<Item = (ContextKind, &ContextValue)> { - self.inner.context.iter().map(|(k, v)| (*k, v)) - } - - /// Lookup a piece of context - #[inline(never)] - #[cfg(feature = "error-context")] - pub fn get(&self, kind: ContextKind) -> Option<&ContextValue> { - self.inner.context.get(&kind) - } - - /// Insert a piece of context - #[inline(never)] - #[cfg(feature = "error-context")] - pub fn insert(&mut self, kind: ContextKind, value: ContextValue) -> Option<ContextValue> { - self.inner.context.insert(kind, value) - } - - /// Should the message be written to `stdout` or not? - #[inline] - pub fn use_stderr(&self) -> bool { - self.stream() == Stream::Stderr - } - - pub(crate) fn stream(&self) -> Stream { - match self.kind() { - ErrorKind::DisplayHelp | ErrorKind::DisplayVersion => Stream::Stdout, - _ => Stream::Stderr, - } - } - - /// Returns the exit code that `.exit` will exit the process with. - /// - /// When the error's kind would print to `stderr` this returns `2`, - /// else it returns `0`. - pub fn exit_code(&self) -> i32 { - if self.use_stderr() { - USAGE_CODE - } else { - SUCCESS_CODE - } - } - - /// Prints the error and exits. - /// - /// Depending on the error kind, this either prints to `stderr` and exits with a status of `2` - /// or prints to `stdout` and exits with a status of `0`. - pub fn exit(&self) -> ! { - // Swallow broken pipe errors - let _ = self.print(); - safe_exit(self.exit_code()) - } - - /// Prints formatted and colored error to `stdout` or `stderr` according to its error kind - /// - /// # Example - /// ```no_run - /// # use clap_builder as clap; - /// use clap::Command; - /// - /// match Command::new("Command").try_get_matches() { - /// Ok(matches) => { - /// // do_something - /// }, - /// Err(err) => { - /// err.print().expect("Error writing Error"); - /// // do_something - /// }, - /// }; - /// ``` - pub fn print(&self) -> io::Result<()> { - let style = self.formatted(); - let color_when = if matches!( - self.kind(), - ErrorKind::DisplayHelp | ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand, - ) { - self.inner.color_help_when - } else { - self.inner.color_when - }; - let c = Colorizer::new(self.stream(), color_when).with_content(style.into_owned()); - c.print() - } - - /// Render the error message to a [`StyledStr`]. - /// - /// # Example - /// ```no_run - /// # use clap_builder as clap; - /// use clap::Command; - /// - /// match Command::new("Command").try_get_matches() { - /// Ok(matches) => { - /// // do_something - /// }, - /// Err(err) => { - /// let err = err.render(); - /// println!("{err}"); - /// // do_something - /// }, - /// }; - /// ``` - pub fn render(&self) -> StyledStr { - self.formatted().into_owned() - } - - #[inline(never)] - fn for_app(kind: ErrorKind, cmd: &Command, styled: StyledStr) -> Self { - Self::new(kind).set_message(styled).with_cmd(cmd) - } - - pub(crate) fn set_message(mut self, message: impl Into<Message>) -> Self { - self.inner.message = Some(message.into()); - self - } - - pub(crate) fn set_source(mut self, source: Box<dyn error::Error + Send + Sync>) -> Self { - self.inner.source = Some(source); - self - } - - pub(crate) fn set_styles(mut self, styles: Styles) -> Self { - self.inner.styles = styles; - self - } - - pub(crate) fn set_color(mut self, color_when: ColorChoice) -> Self { - self.inner.color_when = color_when; - self - } - - pub(crate) fn set_colored_help(mut self, color_help_when: ColorChoice) -> Self { - self.inner.color_help_when = color_help_when; - self - } - - pub(crate) fn set_help_flag(mut self, help_flag: Option<&'static str>) -> Self { - self.inner.help_flag = help_flag; - self - } - - /// Does not verify if `ContextKind` is already present - #[inline(never)] - #[cfg(feature = "error-context")] - pub(crate) fn insert_context_unchecked( - mut self, - kind: ContextKind, - value: ContextValue, - ) -> Self { - self.inner.context.insert_unchecked(kind, value); - self - } - - /// Does not verify if `ContextKind` is already present - #[inline(never)] - #[cfg(feature = "error-context")] - pub(crate) fn extend_context_unchecked<const N: usize>( - mut self, - context: [(ContextKind, ContextValue); N], - ) -> Self { - self.inner.context.extend_unchecked(context); - self - } - - pub(crate) fn display_help(cmd: &Command, styled: StyledStr) -> Self { - Self::for_app(ErrorKind::DisplayHelp, cmd, styled) - } - - pub(crate) fn display_help_error(cmd: &Command, styled: StyledStr) -> Self { - Self::for_app( - ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand, - cmd, - styled, - ) - } - - pub(crate) fn display_version(cmd: &Command, styled: StyledStr) -> Self { - Self::for_app(ErrorKind::DisplayVersion, cmd, styled) - } - - pub(crate) fn argument_conflict( - cmd: &Command, - arg: String, - mut others: Vec<String>, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::ArgumentConflict).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - let others = match others.len() { - 0 => ContextValue::None, - 1 => ContextValue::String(others.pop().unwrap()), - _ => ContextValue::Strings(others), - }; - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - (ContextKind::PriorArg, others), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn empty_value(cmd: &Command, good_vals: &[String], arg: String) -> Self { - Self::invalid_value(cmd, "".to_owned(), good_vals, arg) - } - - pub(crate) fn no_equals(cmd: &Command, arg: String, usage: Option<StyledStr>) -> Self { - let mut err = Self::new(ErrorKind::NoEquals).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err - .extend_context_unchecked([(ContextKind::InvalidArg, ContextValue::String(arg))]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn invalid_value( - cmd: &Command, - bad_val: String, - good_vals: &[String], - arg: String, - ) -> Self { - let suggestion = suggestions::did_you_mean(&bad_val, good_vals.iter()).pop(); - let mut err = Self::new(ErrorKind::InvalidValue).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - (ContextKind::InvalidValue, ContextValue::String(bad_val)), - ( - ContextKind::ValidValue, - ContextValue::Strings(good_vals.iter().map(|s| (*s).to_owned()).collect()), - ), - ]); - if let Some(suggestion) = suggestion { - err = err.insert_context_unchecked( - ContextKind::SuggestedValue, - ContextValue::String(suggestion), - ); - } - } - - err - } - - pub(crate) fn invalid_subcommand( - cmd: &Command, - subcmd: String, - did_you_mean: Vec<String>, - name: String, - suggested_trailing_arg: bool, - usage: Option<StyledStr>, - ) -> Self { - use std::fmt::Write as _; - let styles = cmd.get_styles(); - let invalid = &styles.get_invalid(); - let valid = &styles.get_valid(); - let mut err = Self::new(ErrorKind::InvalidSubcommand).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - let mut suggestions = vec![]; - if suggested_trailing_arg { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "to pass '{}{subcmd}{}' as a value, use '{}{name} -- {subcmd}{}'", - invalid.render(), - invalid.render_reset(), - valid.render(), - valid.render_reset() - ); - suggestions.push(styled_suggestion); - } - - err = err.extend_context_unchecked([ - (ContextKind::InvalidSubcommand, ContextValue::String(subcmd)), - ( - ContextKind::SuggestedSubcommand, - ContextValue::Strings(did_you_mean), - ), - ( - ContextKind::Suggested, - ContextValue::StyledStrs(suggestions), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn unrecognized_subcommand( - cmd: &Command, - subcmd: String, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::InvalidSubcommand).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([( - ContextKind::InvalidSubcommand, - ContextValue::String(subcmd), - )]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn missing_required_argument( - cmd: &Command, - required: Vec<String>, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::MissingRequiredArgument).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([( - ContextKind::InvalidArg, - ContextValue::Strings(required), - )]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn missing_subcommand( - cmd: &Command, - parent: String, - available: Vec<String>, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::MissingSubcommand).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidSubcommand, ContextValue::String(parent)), - ( - ContextKind::ValidSubcommand, - ContextValue::Strings(available), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn invalid_utf8(cmd: &Command, usage: Option<StyledStr>) -> Self { - let mut err = Self::new(ErrorKind::InvalidUtf8).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn too_many_values( - cmd: &Command, - val: String, - arg: String, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::TooManyValues).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - (ContextKind::InvalidValue, ContextValue::String(val)), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn too_few_values( - cmd: &Command, - arg: String, - min_vals: usize, - curr_vals: usize, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::TooFewValues).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - ( - ContextKind::MinValues, - ContextValue::Number(min_vals as isize), - ), - ( - ContextKind::ActualNumValues, - ContextValue::Number(curr_vals as isize), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn value_validation( - arg: String, - val: String, - err: Box<dyn error::Error + Send + Sync>, - ) -> Self { - let mut err = Self::new(ErrorKind::ValueValidation).set_source(err); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - (ContextKind::InvalidValue, ContextValue::String(val)), - ]); - } - - err - } - - pub(crate) fn wrong_number_of_values( - cmd: &Command, - arg: String, - num_vals: usize, - curr_vals: usize, - usage: Option<StyledStr>, - ) -> Self { - let mut err = Self::new(ErrorKind::WrongNumberOfValues).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - ( - ContextKind::ExpectedNumValues, - ContextValue::Number(num_vals as isize), - ), - ( - ContextKind::ActualNumValues, - ContextValue::Number(curr_vals as isize), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - pub(crate) fn unknown_argument( - cmd: &Command, - arg: String, - did_you_mean: Option<(String, Option<String>)>, - suggested_trailing_arg: bool, - usage: Option<StyledStr>, - ) -> Self { - use std::fmt::Write as _; - let styles = cmd.get_styles(); - let invalid = &styles.get_invalid(); - let valid = &styles.get_valid(); - let mut err = Self::new(ErrorKind::UnknownArgument).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - let mut suggestions = vec![]; - if suggested_trailing_arg { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "to pass '{}{arg}{}' as a value, use '{}-- {arg}{}'", - invalid.render(), - invalid.render_reset(), - valid.render(), - valid.render_reset() - ); - suggestions.push(styled_suggestion); - } - - err = err - .extend_context_unchecked([(ContextKind::InvalidArg, ContextValue::String(arg))]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - match did_you_mean { - Some((flag, Some(sub))) => { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "'{}{sub} {flag}{}' exists", - valid.render(), - valid.render_reset() - ); - suggestions.push(styled_suggestion); - } - Some((flag, None)) => { - err = err.insert_context_unchecked( - ContextKind::SuggestedArg, - ContextValue::String(flag), - ); - } - None => {} - } - if !suggestions.is_empty() { - err = err.insert_context_unchecked( - ContextKind::Suggested, - ContextValue::StyledStrs(suggestions), - ); - } - } - - err - } - - pub(crate) fn unnecessary_double_dash( - cmd: &Command, - arg: String, - usage: Option<StyledStr>, - ) -> Self { - use std::fmt::Write as _; - let styles = cmd.get_styles(); - let invalid = &styles.get_invalid(); - let valid = &styles.get_valid(); - let mut err = Self::new(ErrorKind::UnknownArgument).with_cmd(cmd); - - #[cfg(feature = "error-context")] - { - let mut styled_suggestion = StyledStr::new(); - let _ = write!( - styled_suggestion, - "subcommand '{}{arg}{}' exists; to use it, remove the '{}--{}' before it", - valid.render(), - valid.render_reset(), - invalid.render(), - invalid.render_reset() - ); - - err = err.extend_context_unchecked([ - (ContextKind::InvalidArg, ContextValue::String(arg)), - ( - ContextKind::Suggested, - ContextValue::StyledStrs(vec![styled_suggestion]), - ), - ]); - if let Some(usage) = usage { - err = err - .insert_context_unchecked(ContextKind::Usage, ContextValue::StyledStr(usage)); - } - } - - err - } - - fn formatted(&self) -> Cow<'_, StyledStr> { - if let Some(message) = self.inner.message.as_ref() { - message.formatted(&self.inner.styles) - } else { - let styled = F::format_error(self); - Cow::Owned(styled) - } - } -} - -impl<F: ErrorFormatter> From<io::Error> for Error<F> { - fn from(e: io::Error) -> Self { - Error::raw(ErrorKind::Io, e) - } -} - -impl<F: ErrorFormatter> From<fmt::Error> for Error<F> { - fn from(e: fmt::Error) -> Self { - Error::raw(ErrorKind::Format, e) - } -} - -impl<F: ErrorFormatter> std::fmt::Debug for Error<F> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - self.inner.fmt(f) - } -} - -impl<F: ErrorFormatter> error::Error for Error<F> { - #[allow(trivial_casts)] - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - self.inner.source.as_ref().map(|e| e.as_ref() as _) - } -} - -impl<F: ErrorFormatter> Display for Error<F> { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - // Assuming `self.message` already has a trailing newline, from `try_help` or similar - ok!(write!(f, "{}", self.formatted())); - if let Some(backtrace) = self.inner.backtrace.as_ref() { - ok!(writeln!(f)); - ok!(writeln!(f, "Backtrace:")); - ok!(writeln!(f, "{backtrace}")); - } - Ok(()) - } -} - -#[derive(Clone, Debug)] -pub(crate) enum Message { - Raw(String), - Formatted(StyledStr), -} - -impl Message { - fn format(&mut self, cmd: &Command, usage: Option<StyledStr>) { - match self { - Message::Raw(s) => { - let mut message = String::new(); - std::mem::swap(s, &mut message); - - let styled = format::format_error_message( - &message, - cmd.get_styles(), - Some(cmd), - usage.as_ref(), - ); - - *self = Self::Formatted(styled); - } - Message::Formatted(_) => {} - } - } - - fn formatted(&self, styles: &Styles) -> Cow<StyledStr> { - match self { - Message::Raw(s) => { - let styled = format::format_error_message(s, styles, None, None); - - Cow::Owned(styled) - } - Message::Formatted(s) => Cow::Borrowed(s), - } - } -} - -impl From<String> for Message { - fn from(inner: String) -> Self { - Self::Raw(inner) - } -} - -impl From<StyledStr> for Message { - fn from(inner: StyledStr) -> Self { - Self::Formatted(inner) - } -} - -#[cfg(feature = "debug")] -#[derive(Debug)] -struct Backtrace(backtrace::Backtrace); - -#[cfg(feature = "debug")] -impl Backtrace { - fn new() -> Option<Self> { - Some(Self(backtrace::Backtrace::new())) - } -} - -#[cfg(feature = "debug")] -impl Display for Backtrace { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - // `backtrace::Backtrace` uses `Debug` instead of `Display` - write!(f, "{:?}", self.0) - } -} - -#[cfg(not(feature = "debug"))] -#[derive(Debug)] -struct Backtrace; - -#[cfg(not(feature = "debug"))] -impl Backtrace { - fn new() -> Option<Self> { - None - } -} - -#[cfg(not(feature = "debug"))] -impl Display for Backtrace { - fn fmt(&self, _: &mut Formatter) -> fmt::Result { - Ok(()) - } -} - -#[test] -fn check_auto_traits() { - static_assertions::assert_impl_all!(Error: Send, Sync, Unpin); -} |