From ef713cc4881f4b8733b4ae219f2ca788693e0cda Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 4 May 2020 10:24:13 -0700 Subject: [PATCH 1/3] remove member access fns and --- Cargo.toml | 4 ++-- README.md | 2 +- src/error.rs | 35 ----------------------------------- src/lib.rs | 34 +++++----------------------------- 4 files changed, 8 insertions(+), 67 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1ace559..21f1d12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "eyre" -version = "0.3.10" # remember to update html_root_url +version = "0.4.0" # remember to update html_root_url authors = ["David Tolnay ", "Jane Lusby "] edition = "2018" license = "MIT OR Apache-2.0" @@ -22,7 +22,7 @@ trybuild = { version = "1.0.19", features = ["diff"] } backtrace = "0.3.46" [dependencies] -indenter = "^0.1.1" +indenter = "0.1.3" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/README.md b/README.md index 31b9a32..f74069d 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ Cargo.toml. A global allocator is required. ```toml [dependencies] -eyre = { version = "0.3", default-features = false } +eyre = { version = "0.4", default-features = false } ``` Since the `?`-based error conversions would normally rely on the diff --git a/src/error.rs b/src/error.rs index f8e9bc3..c598572 100644 --- a/src/error.rs +++ b/src/error.rs @@ -2,7 +2,6 @@ use crate::alloc::Box; use crate::chain::Chain; use crate::EyreContext; use crate::{Report, StdError}; -use core::any::Any; use core::any::TypeId; use core::fmt::{self, Debug, Display}; use core::mem::{self, ManuallyDrop}; @@ -437,14 +436,6 @@ where } } - pub fn member_ref(&self) -> Option<&T> { - self.inner.member_ref() - } - - pub fn member_mut(&mut self) -> Option<&mut T> { - self.inner.member_mut() - } - pub fn context(&self) -> &C { self.inner.context.as_ref().unwrap() } @@ -741,32 +732,6 @@ where unsafe { &mut *(self.vtable.object_mut)(self) } } - pub fn member_ref(&self) -> Option<&T> { - self.context - .as_ref() - .unwrap() - .member_ref(TypeId::of::())? - .downcast_ref::() - } - - pub fn member_mut(&mut self) -> Option<&mut T> { - self.context - .as_mut() - .unwrap() - .member_mut(TypeId::of::())? - .downcast_mut::() - } - - #[cfg(backtrace)] - pub(crate) fn backtrace(&self) -> &Backtrace { - // This unwrap can only panic if the underlying error's backtrace method - // is nondeterministic, which would only happen in maliciously - // constructed code. - self.member_ref() - .or_else(|| self.error().backtrace()) - .expect("backtrace capture failed") - } - pub(crate) fn chain(&self) -> Chain { Chain::new(self.error()) } diff --git a/src/lib.rs b/src/lib.rs index f03519b..16772a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ //! //! ```toml //! [dependencies] -//! eyre = "0.3" +//! eyre = "0.4" //! ``` //! # Details //! @@ -185,7 +185,7 @@ //! //! ```toml //! [dependencies] -//! eyre = { version = "0.3", default-features = false } +//! eyre = { version = "0.4", default-features = false } //! ``` //! //! Since the `?`-based error conversions would normally rely on the @@ -227,7 +227,7 @@ //! [`anyhow`]: https://github.com/dtolnay/anyhow //! [`tracing_error::SpanTrace`]: https://docs.rs/tracing-error/*/tracing_error/struct.SpanTrace.html //! [`stable_eyre`]: https://docs.rs/stable-eyre -#![doc(html_root_url = "https://docs.rs/eyre/0.3.10")] +#![doc(html_root_url = "https://docs.rs/eyre/0.4.0")] #![cfg_attr(backtrace, feature(backtrace))] #![cfg_attr(doc_cfg, feature(doc_cfg))] #![cfg_attr(not(feature = "std"), no_std)] @@ -267,7 +267,6 @@ mod wrapper; use crate::alloc::Box; use crate::backtrace::Backtrace; use crate::error::ErrorImpl; -use core::any::{Any, TypeId}; use core::fmt::Display; use core::mem::ManuallyDrop; @@ -570,23 +569,7 @@ pub trait EyreContext: Sized + Send + Sync + 'static { f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result; - /// Member access function - /// - /// The main reason to implement this fn is to provide support for `eyre::Report::backtrace` - /// which will call this fn on `nightly` when attempting access the captured - /// `std::backtrace::Backtrace` - /// - /// # Example - fn member_ref(&self, _typeid: TypeId) -> Option<&dyn Any> { - None - } - - #[doc(hidden)] - fn member_mut(&mut self, _typeid: TypeId) -> Option<&mut dyn Any> { - None - } - - #[doc(hidden)] + /// Override for the `Display` format fn display( &self, error: &(dyn StdError + 'static), @@ -608,6 +591,7 @@ pub trait EyreContext: Sized + Send + Sync + 'static { /// /// On nightly this supports conditionally capturing a `std::backtrace::Backtrace` if the source /// error did not already capture one. +#[allow(dead_code)] pub struct DefaultContext { backtrace: Option, } @@ -620,14 +604,6 @@ impl EyreContext for DefaultContext { Self { backtrace } } - fn member_ref(&self, typeid: TypeId) -> Option<&dyn Any> { - if typeid == TypeId::of::() { - self.backtrace.as_ref().map(|b| b as &dyn Any) - } else { - None - } - } - fn debug( &self, error: &(dyn StdError + 'static), From 6a5d166f09dd317d5e6e42d7c0af61a0b5b619ab Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 4 May 2020 10:38:56 -0700 Subject: [PATCH 2/3] fix nightly errors --- src/context.rs | 5 -- src/error.rs | 34 +-------- tests/test_backtrace.rs | 13 ---- tests/test_context.rs | 160 +--------------------------------------- 4 files changed, 6 insertions(+), 206 deletions(-) delete mode 100644 tests/test_backtrace.rs diff --git a/src/context.rs b/src/context.rs index 006a220..d724e06 100644 --- a/src/context.rs +++ b/src/context.rs @@ -122,11 +122,6 @@ where C: EyreContext, D: Display, { - #[cfg(backtrace)] - fn backtrace(&self) -> Option<&Backtrace> { - Some(self.error.backtrace()) - } - fn source(&self) -> Option<&(dyn StdError + 'static)> { Some(self.error.inner.error()) } diff --git a/src/error.rs b/src/error.rs index c598572..af839a2 100644 --- a/src/error.rs +++ b/src/error.rs @@ -7,9 +7,6 @@ use core::fmt::{self, Debug, Display}; use core::mem::{self, ManuallyDrop}; use core::ptr::{self, NonNull}; -#[cfg(backtrace)] -use crate::backtrace::Backtrace; - #[cfg(feature = "std")] use core::ops::{Deref, DerefMut}; @@ -261,30 +258,6 @@ where unsafe { Report::construct(error, vtable, context) } } - /// Get the backtrace for this Report. - /// - /// Backtraces are only available on the nightly channel. Tracking issue: - /// [rust-lang/rust#53487][tracking]. - /// - /// 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`. - /// - /// [tracking]: https://github.com/rust-lang/rust/issues/53487 - #[cfg(backtrace)] - pub fn backtrace(&self) -> &Backtrace { - self.inner.backtrace() - } - /// An iterator of the chain of source errors contained by this Report. /// /// This iterator will visit every error in the cause chain of this error @@ -436,10 +409,12 @@ where } } + /// Get a reference to the Context for this Report. pub fn context(&self) -> &C { self.inner.context.as_ref().unwrap() } + /// Get a mutable reference to the Context for this Report. pub fn context_mut(&mut self) -> &mut C { self.inner.context.as_mut().unwrap() } @@ -742,11 +717,6 @@ where C: EyreContext, E: StdError, { - #[cfg(backtrace)] - fn backtrace(&self) -> Option<&Backtrace> { - Some(self.erase().backtrace()) - } - fn source(&self) -> Option<&(dyn StdError + 'static)> { self.erase().error().source() } diff --git a/tests/test_backtrace.rs b/tests/test_backtrace.rs deleted file mode 100644 index 53a5a0f..0000000 --- a/tests/test_backtrace.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[rustversion::not(nightly)] -#[ignore] -#[test] -fn test_backtrace() {} - -#[rustversion::nightly] -#[test] -fn test_backtrace() { - use eyre::{eyre, Report}; - - let error: Report = eyre!("oh no!"); - let _ = error.backtrace(); -} diff --git a/tests/test_context.rs b/tests/test_context.rs index 05aa8d2..6ee589d 100644 --- a/tests/test_context.rs +++ b/tests/test_context.rs @@ -1,159 +1,7 @@ -mod drop; - -use crate::drop::{DetectDrop, Flag}; -use eyre::{Report, Result, WrapErr}; -use std::fmt::{self, Display}; -use thiserror::Error; - -// https://github.com/dtolnay/eyre/issues/18 -#[test] -fn test_inference() -> Result<()> { - let x = "1"; - let y: u32 = x.parse().wrap_err("...")?; - assert_eq!(y, 1); - Ok(()) -} - -macro_rules! context_type { - ($name:ident) => { - #[derive(Debug)] - struct $name { - message: &'static str, - drop: DetectDrop, - } - - impl Display for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(self.message) - } - } - }; -} - -context_type!(HighLevel); -context_type!(MidLevel); - -#[derive(Error, Debug)] -#[error("{message}")] -struct LowLevel { - message: &'static str, - drop: DetectDrop, -} - -struct Dropped { - low: Flag, - mid: Flag, - high: Flag, -} - -impl Dropped { - fn none(&self) -> bool { - !self.low.get() && !self.mid.get() && !self.high.get() - } - - fn all(&self) -> bool { - self.low.get() && self.mid.get() && self.high.get() - } -} - -fn make_chain() -> (Report, Dropped) { - let dropped = Dropped { - low: Flag::new(), - mid: Flag::new(), - high: Flag::new(), - }; - - let low = LowLevel { - message: "no such file or directory", - drop: DetectDrop::new(&dropped.low), - }; - - // impl Report for Result - let mid = Err::<(), LowLevel>(low) - .wrap_err(MidLevel { - message: "failed to load config", - drop: DetectDrop::new(&dropped.mid), - }) - .unwrap_err(); - - // impl Report for Result - let high = Err::<(), Report>(mid) - .wrap_err(HighLevel { - message: "failed to start server", - drop: DetectDrop::new(&dropped.high), - }) - .unwrap_err(); - - (high, dropped) -} - -#[test] -fn test_downcast_ref() { - let (err, dropped) = make_chain(); - - assert!(!err.is::()); - assert!(err.downcast_ref::().is_none()); - - assert!(err.is::()); - let high = err.downcast_ref::().unwrap(); - assert_eq!(high.to_string(), "failed to start server"); - - assert!(err.is::()); - let mid = err.downcast_ref::().unwrap(); - assert_eq!(mid.to_string(), "failed to load config"); - - assert!(err.is::()); - let low = err.downcast_ref::().unwrap(); - assert_eq!(low.to_string(), "no such file or directory"); - - assert!(dropped.none()); - drop(err); - assert!(dropped.all()); -} - -#[test] -fn test_downcast_high() { - let (err, dropped) = make_chain(); - - let err = err.downcast::().unwrap(); - assert!(!dropped.high.get()); - assert!(dropped.low.get() && dropped.mid.get()); - - drop(err); - assert!(dropped.all()); -} - #[test] -fn test_downcast_mid() { - let (err, dropped) = make_chain(); - - let err = err.downcast::().unwrap(); - assert!(!dropped.mid.get()); - assert!(dropped.low.get() && dropped.high.get()); - - drop(err); - assert!(dropped.all()); -} - -#[test] -fn test_downcast_low() { - let (err, dropped) = make_chain(); - - let err = err.downcast::().unwrap(); - assert!(!dropped.low.get()); - assert!(dropped.mid.get() && dropped.high.get()); - - drop(err); - assert!(dropped.all()); -} - -#[test] -fn test_unsuccessful_downcast() { - let (err, dropped) = make_chain(); - - let err = err.downcast::().unwrap_err(); - assert!(dropped.none()); +fn test_context() { + use eyre::{eyre, Report}; - drop(err); - assert!(dropped.all()); + let error: Report = eyre!("oh no!"); + let _ = error.context(); } From 5537e49e5bdae55fd3de99f4f4816b4b2ad89a10 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Mon, 4 May 2020 12:15:01 -0700 Subject: [PATCH 3/3] bring back the test i accidentally removed --- tests/test_context.rs | 160 ++++++++++++++++++++++++++++++++++- tests/test_context_access.rs | 7 ++ 2 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 tests/test_context_access.rs diff --git a/tests/test_context.rs b/tests/test_context.rs index 6ee589d..05aa8d2 100644 --- a/tests/test_context.rs +++ b/tests/test_context.rs @@ -1,7 +1,159 @@ +mod drop; + +use crate::drop::{DetectDrop, Flag}; +use eyre::{Report, Result, WrapErr}; +use std::fmt::{self, Display}; +use thiserror::Error; + +// https://github.com/dtolnay/eyre/issues/18 +#[test] +fn test_inference() -> Result<()> { + let x = "1"; + let y: u32 = x.parse().wrap_err("...")?; + assert_eq!(y, 1); + Ok(()) +} + +macro_rules! context_type { + ($name:ident) => { + #[derive(Debug)] + struct $name { + message: &'static str, + drop: DetectDrop, + } + + impl Display for $name { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(self.message) + } + } + }; +} + +context_type!(HighLevel); +context_type!(MidLevel); + +#[derive(Error, Debug)] +#[error("{message}")] +struct LowLevel { + message: &'static str, + drop: DetectDrop, +} + +struct Dropped { + low: Flag, + mid: Flag, + high: Flag, +} + +impl Dropped { + fn none(&self) -> bool { + !self.low.get() && !self.mid.get() && !self.high.get() + } + + fn all(&self) -> bool { + self.low.get() && self.mid.get() && self.high.get() + } +} + +fn make_chain() -> (Report, Dropped) { + let dropped = Dropped { + low: Flag::new(), + mid: Flag::new(), + high: Flag::new(), + }; + + let low = LowLevel { + message: "no such file or directory", + drop: DetectDrop::new(&dropped.low), + }; + + // impl Report for Result + let mid = Err::<(), LowLevel>(low) + .wrap_err(MidLevel { + message: "failed to load config", + drop: DetectDrop::new(&dropped.mid), + }) + .unwrap_err(); + + // impl Report for Result + let high = Err::<(), Report>(mid) + .wrap_err(HighLevel { + message: "failed to start server", + drop: DetectDrop::new(&dropped.high), + }) + .unwrap_err(); + + (high, dropped) +} + +#[test] +fn test_downcast_ref() { + let (err, dropped) = make_chain(); + + assert!(!err.is::()); + assert!(err.downcast_ref::().is_none()); + + assert!(err.is::()); + let high = err.downcast_ref::().unwrap(); + assert_eq!(high.to_string(), "failed to start server"); + + assert!(err.is::()); + let mid = err.downcast_ref::().unwrap(); + assert_eq!(mid.to_string(), "failed to load config"); + + assert!(err.is::()); + let low = err.downcast_ref::().unwrap(); + assert_eq!(low.to_string(), "no such file or directory"); + + assert!(dropped.none()); + drop(err); + assert!(dropped.all()); +} + +#[test] +fn test_downcast_high() { + let (err, dropped) = make_chain(); + + let err = err.downcast::().unwrap(); + assert!(!dropped.high.get()); + assert!(dropped.low.get() && dropped.mid.get()); + + drop(err); + assert!(dropped.all()); +} + #[test] -fn test_context() { - use eyre::{eyre, Report}; +fn test_downcast_mid() { + let (err, dropped) = make_chain(); + + let err = err.downcast::().unwrap(); + assert!(!dropped.mid.get()); + assert!(dropped.low.get() && dropped.high.get()); + + drop(err); + assert!(dropped.all()); +} + +#[test] +fn test_downcast_low() { + let (err, dropped) = make_chain(); + + let err = err.downcast::().unwrap(); + assert!(!dropped.low.get()); + assert!(dropped.mid.get() && dropped.high.get()); + + drop(err); + assert!(dropped.all()); +} + +#[test] +fn test_unsuccessful_downcast() { + let (err, dropped) = make_chain(); + + let err = err.downcast::().unwrap_err(); + assert!(dropped.none()); - let error: Report = eyre!("oh no!"); - let _ = error.context(); + drop(err); + assert!(dropped.all()); } diff --git a/tests/test_context_access.rs b/tests/test_context_access.rs new file mode 100644 index 0000000..6ee589d --- /dev/null +++ b/tests/test_context_access.rs @@ -0,0 +1,7 @@ +#[test] +fn test_context() { + use eyre::{eyre, Report}; + + let error: Report = eyre!("oh no!"); + let _ = error.context(); +}