Should `anyhow::Error::chain` return `dyn Error + Send + Sync`
Opened this issue · 2 comments
ten3roberts commented
anyhow::Error
only supports wrapping Send + Sync
errors, but the API for chain
returns non-send and non-sync errors.
I suspect this is to mimic the source stdlib API, if so, would it be advisable to introduce a chain_send_sync
method?
ten3roberts commented
The same goes for the root_cause
API, which with the lack of Send + Sync
makes an anyhow conversion non-bijective
dtolnay commented
What would be the expected behavior if the causes or root cause are not Send + Sync
?
// [dependencies]
// anyhow = "1"
// threadbound = "0.1"
use std::fmt::{self, Display};
use threadbound::ThreadBound;
#[derive(Debug)]
struct OuterError {
inner: ThreadBound<InnerError>,
}
impl std::error::Error for OuterError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
let inner = self.inner.get_ref()?;
Some(inner)
}
}
impl Display for OuterError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("...")
}
}
#[derive(Copy, Clone, Debug)]
struct InnerError {
p: *const (), // not sync
}
impl std::error::Error for InnerError {}
impl Display for InnerError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("...")
}
}
fn main() {
let err = f().unwrap_err();
for e in err.chain() {
println!("{}", e);
}
}
fn f() -> anyhow::Result<()> {
g()?;
Ok(())
}
fn g() -> Result<(), OuterError> {
Err(OuterError {
inner: ThreadBound::new(InnerError { p: 0 as _ }),
})
}