Skip to content

Commit 9498677

Browse files
authored
Make ContextCompat consistent and non-ambiguous with WrapErr (#150)
See: #149 Fixes: #149
2 parents 907daa2 + c98bc8c commit 9498677

File tree

5 files changed

+26
-83
lines changed

5 files changed

+26
-83
lines changed

color-eyre/tests/theme.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,12 @@ fn test_backwards_compatibility(target: String, file_name: &str) {
170170
fn normalize_backtrace(input: &str) -> String {
171171
input
172172
.lines()
173-
.take_while(|v| !v.contains("core::panic") && !v.contains("theme_test_helper::main"))
173+
.take_while(|v| {
174+
!v.contains("core::panic")
175+
&& !v.contains("theme_test_helper::main")
176+
&& !v.contains("theme::test_error_backwards_compatibility::closure")
177+
&& !v.contains("theme::test_error_backwards_compatibility::{{closure}}")
178+
})
174179
.collect::<Vec<_>>()
175180
.join("\n")
176181
}

eyre/src/context.rs

+13-20
Original file line numberDiff line numberDiff line change
@@ -61,42 +61,34 @@ where
6161
Err(e) => Err(e.ext_report(msg())),
6262
}
6363
}
64+
}
6465

65-
#[cfg(feature = "anyhow")]
66-
fn context<D>(self, msg: D) -> Result<T, Report>
66+
#[cfg(feature = "anyhow")]
67+
impl<T, E> crate::ContextCompat<T> for Result<T, E>
68+
where
69+
Self: WrapErr<T, E>,
70+
{
71+
#[track_caller]
72+
fn context<D>(self, msg: D) -> crate::Result<T, Report>
6773
where
6874
D: Display + Send + Sync + 'static,
6975
{
7076
self.wrap_err(msg)
7177
}
7278

73-
#[cfg(feature = "anyhow")]
74-
fn with_context<D, F>(self, msg: F) -> Result<T, Report>
79+
#[track_caller]
80+
fn with_context<D, F>(self, f: F) -> crate::Result<T, Report>
7581
where
7682
D: Display + Send + Sync + 'static,
7783
F: FnOnce() -> D,
7884
{
79-
self.wrap_err_with(msg)
85+
self.wrap_err_with(f)
8086
}
8187
}
8288

8389
#[cfg(feature = "anyhow")]
8490
impl<T> crate::ContextCompat<T> for Option<T> {
85-
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
86-
where
87-
D: Display + Send + Sync + 'static,
88-
{
89-
self.context(msg)
90-
}
91-
92-
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report>
93-
where
94-
D: Display + Send + Sync + 'static,
95-
F: FnOnce() -> D,
96-
{
97-
self.with_context(msg)
98-
}
99-
91+
#[track_caller]
10092
fn context<D>(self, msg: D) -> Result<T, Report>
10193
where
10294
D: Display + Send + Sync + 'static,
@@ -107,6 +99,7 @@ impl<T> crate::ContextCompat<T> for Option<T> {
10799
}
108100
}
109101

102+
#[track_caller]
110103
fn with_context<D, F>(self, msg: F) -> Result<T, Report>
111104
where
112105
D: Display + Send + Sync + 'static,

eyre/src/lib.rs

+5-29
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ fn capture_handler(error: &(dyn StdError + 'static)) -> Box<dyn EyreHandler> {
624624
}
625625

626626
impl dyn EyreHandler {
627+
/// Check if the handler is of type `T`
627628
pub fn is<T: EyreHandler>(&self) -> bool {
628629
// Get `TypeId` of the type this function is instantiated with.
629630
let t = core::any::TypeId::of::<T>();
@@ -635,6 +636,7 @@ impl dyn EyreHandler {
635636
t == concrete
636637
}
637638

639+
/// Downcast the handler to a concrete type `T`
638640
pub fn downcast_ref<T: EyreHandler>(&self) -> Option<&T> {
639641
if self.is::<T>() {
640642
unsafe { Some(&*(self as *const dyn EyreHandler as *const T)) }
@@ -643,6 +645,7 @@ impl dyn EyreHandler {
643645
}
644646
}
645647

648+
/// Downcast the handler to a concrete type `T`
646649
pub fn downcast_mut<T: EyreHandler>(&mut self) -> Option<&mut T> {
647650
if self.is::<T>() {
648651
unsafe { Some(&mut *(self as *mut dyn EyreHandler as *mut T)) }
@@ -1122,21 +1125,6 @@ pub trait WrapErr<T, E>: context::private::Sealed {
11221125
where
11231126
D: Display + Send + Sync + 'static,
11241127
F: FnOnce() -> D;
1125-
1126-
/// Compatibility re-export of wrap_err for interop with `anyhow`
1127-
#[cfg(feature = "anyhow")]
1128-
#[cfg_attr(track_caller, track_caller)]
1129-
fn context<D>(self, msg: D) -> Result<T, Report>
1130-
where
1131-
D: Display + Send + Sync + 'static;
1132-
1133-
/// Compatibility re-export of wrap_err_with for interop with `anyhow`
1134-
#[cfg(feature = "anyhow")]
1135-
#[cfg_attr(track_caller, track_caller)]
1136-
fn with_context<D, F>(self, f: F) -> Result<T, Report>
1137-
where
1138-
D: Display + Send + Sync + 'static,
1139-
F: FnOnce() -> D;
11401128
}
11411129

11421130
/// Provides the [`ok_or_eyre`][OptionExt::ok_or_eyre] method for [`Option`].
@@ -1194,7 +1182,8 @@ pub trait OptionExt<T>: context::private::Sealed {
11941182
M: Debug + Display + Send + Sync + 'static;
11951183
}
11961184

1197-
/// Provides the `context` method for `Option` when porting from `anyhow`
1185+
/// Provides the `context` and `with_context` methods for `Result` and `Option` to enhance
1186+
/// compatibility when porting from anyhow.
11981187
///
11991188
/// This trait is sealed and cannot be implemented for types outside of
12001189
/// `eyre`.
@@ -1253,19 +1242,6 @@ pub trait ContextCompat<T>: context::private::Sealed {
12531242
where
12541243
D: Display + Send + Sync + 'static,
12551244
F: FnOnce() -> D;
1256-
1257-
/// Compatibility re-export of `context` for porting from `anyhow` to `eyre`
1258-
#[cfg_attr(track_caller, track_caller)]
1259-
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
1260-
where
1261-
D: Display + Send + Sync + 'static;
1262-
1263-
/// Compatibility re-export of `with_context` for porting from `anyhow` to `eyre`
1264-
#[cfg_attr(track_caller, track_caller)]
1265-
fn wrap_err_with<D, F>(self, f: F) -> Result<T, Report>
1266-
where
1267-
D: Display + Send + Sync + 'static,
1268-
F: FnOnce() -> D;
12691245
}
12701246

12711247
/// Equivalent to `Ok::<_, eyre::Error>(value)`.

eyre/tests/test_location.rs

+2-32
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ fn test_context() {
105105
Box::new(LocationHandler::new(expected_location))
106106
}));
107107

108-
use eyre::WrapErr;
108+
use eyre::ContextCompat;
109109
let err = read_path("totally_fake_path")
110110
.context("oopsie")
111111
.unwrap_err();
@@ -122,7 +122,7 @@ fn test_with_context() {
122122
Box::new(LocationHandler::new(expected_location))
123123
}));
124124

125-
use eyre::WrapErr;
125+
use eyre::ContextCompat;
126126
let err = read_path("totally_fake_path")
127127
.with_context(|| "oopsie")
128128
.unwrap_err();
@@ -131,36 +131,6 @@ fn test_with_context() {
131131
println!("{:?}", err);
132132
}
133133

134-
#[cfg(feature = "anyhow")]
135-
#[test]
136-
fn test_option_compat_wrap_err() {
137-
let _ = eyre::set_hook(Box::new(|_e| {
138-
let expected_location = file!();
139-
Box::new(LocationHandler::new(expected_location))
140-
}));
141-
142-
use eyre::ContextCompat;
143-
let err = None::<()>.wrap_err("oopsie").unwrap_err();
144-
145-
// should panic if the location isn't in our crate
146-
println!("{:?}", err);
147-
}
148-
149-
#[cfg(feature = "anyhow")]
150-
#[test]
151-
fn test_option_compat_wrap_err_with() {
152-
let _ = eyre::set_hook(Box::new(|_e| {
153-
let expected_location = file!();
154-
Box::new(LocationHandler::new(expected_location))
155-
}));
156-
157-
use eyre::ContextCompat;
158-
let err = None::<()>.wrap_err_with(|| "oopsie").unwrap_err();
159-
160-
// should panic if the location isn't in our crate
161-
println!("{:?}", err);
162-
}
163-
164134
#[cfg(feature = "anyhow")]
165135
#[test]
166136
fn test_option_compat_context() {

eyre/tests/test_repr.rs

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ mod drop;
44
use self::common::maybe_install_handler;
55
use self::drop::{DetectDrop, Flag};
66
use eyre::Report;
7-
use std::marker::Unpin;
87
use std::mem;
98

109
#[test]

0 commit comments

Comments
 (0)