Nemo157
October 19, 2022, 9:03am
11
Are you referring to the issue with io::Error::source not giving back the immediate error?
opened 06:58PM - 14 Sep 22 UTC
T-libs-api
C-bug
A-error-handling
I tried this code ([playground](https://play.rust-lang.org/?version=stable&mode=… debug&edition=2021&gist=8652db49f5a01a73b64051a4aa9bc7d2)):
```rust
use std::error::Error;
#[derive(Debug, PartialEq, Eq)]
struct E;
impl std::fmt::Display for E {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "E")
}
}
impl Error for E {}
#[test]
fn custom_io_has_source() {
let e = E;
let e = std::io::Error::new(std::io::ErrorKind::Other, e);
assert_eq!(e.source().and_then(|s| s.downcast_ref::<E>()), Some(&E));
}
```
I expected to see this happen: the test passed
Instead, this happened: the test failed with
```
thread 'custom_io_has_source' panicked at 'assertion failed: `(left == right)`
left: `None`,
right: `Some(E)`', src/lib.rs:18:5
```
I don't _believe_ this is intentional, since the code standard library `impl Error for io::Error` specifically has:
https://github.com/rust-lang/rust/blob/a92669638461836f41f54f95e396f9082bb91391/library/std/src/io/error.rs#L963
In fact, it was _specifically_ implemented in https://github.com/rust-lang/rust/pull/58963, but that PR doesn't appear to have included any tests. The test above fails even on 1.30.0 (which is the first Rust version with `fn source`).
What's even more interesting is that `assert!(e.cause().is_some())` fails all the way back to Rust 1.0, so it sure seems like something is fishy here.
I wonder if @thomcc may know how the source might be disappearing given his work in #87869?
Another interesting tidbit here is that using [`io_error_downcast`](https://github.com/rust-lang/rust/issues/99262) we _do_ get the inner error, meaning there will (when that feature lands) be a discrepancy between `io::Error`'s `.source()` and `.downcast()`.
```rust
assert_eq!(e.downcast::<E>().unwrap(), Box::new(E));
```
### Meta
`rustc --version --verbose`:
```
rustc 1.63.0 (4b91a6ea7 2022-08-08)
binary: rustc
commit-hash: 4b91a6ea7258a947e59c6522cd5898e7c0a6a88f
commit-date: 2022-08-08
host: aarch64-unknown-linux-gnu
release: 1.63.0
LLVM version: 14.0.5
```
There is an inherent method for getting it (std::io::Error::get_ref ) so it should be possible to inspect any error in the chain using a loop going through Error::source and attempting downcasting to go through io::Error::get_ref as linked in the last comment on the issue.