Skip to content

Commit 9506104

Browse files
committed
Prevent duplicated error information in "wrapping errors" example
The "Wrapping errors" example, which illustrates how to wrap errors, is using the wrapped error in the text that is displayed as well as the implementation of source(). In so doing it effectively duplicates the error information. Such behavior does not play nice with error reporting crates such as anyhow, eyre, and others that make use of both this data. It is also questionable at best from a logical point of view, because, as the name suggests, the source should be a lower level error that is the cause of this one. With this change we update the documentation, suggesting the usage of a custom error string describing at a higher level what went wrong. To keep the example simple, we did not include the actual string in the error (a comment already suggests that this could be done), although that probably should be done in real life to provide additional context. An alternative approach would be to not return a source, but I figured that it's sort of desired for the illustration of wrapping an error.
1 parent 19f0a03 commit 9506104

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

src/error/multiple_error_types/wrap_error.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ An alternative to boxing errors is to wrap them in your own error type.
44

55
```rust,editable
66
use std::error;
7+
use std::error::Error as _;
78
use std::num::ParseIntError;
89
use std::fmt;
910
@@ -22,8 +23,10 @@ impl fmt::Display for DoubleError {
2223
match *self {
2324
DoubleError::EmptyVec =>
2425
write!(f, "please use a vector with at least one element"),
25-
// This is a wrapper, so defer to the underlying types' implementation of `fmt`.
26-
DoubleError::Parse(ref e) => e.fmt(f),
26+
// The wrapped error contains additional information and is available
27+
// via the source() method.
28+
DoubleError::Parse(..) =>
29+
write!(f, "the provided string could not be parsed as int"),
2730
}
2831
}
2932
}
@@ -51,6 +54,8 @@ impl From<ParseIntError> for DoubleError {
5154
5255
fn double_first(vec: Vec<&str>) -> Result<i32> {
5356
let first = vec.first().ok_or(DoubleError::EmptyVec)?;
57+
// Here we implicitly use the `ParseIntError` implementation of `From` (which
58+
// we defined above) in order to create a `DoubleError`.
5459
let parsed = first.parse::<i32>()?;
5560
5661
Ok(2 * parsed)
@@ -59,7 +64,12 @@ fn double_first(vec: Vec<&str>) -> Result<i32> {
5964
fn print(result: Result<i32>) {
6065
match result {
6166
Ok(n) => println!("The first doubled is {}", n),
62-
Err(e) => println!("Error: {}", e),
67+
Err(e) => {
68+
println!("Error: {}", e);
69+
if let Some(source) = e.source() {
70+
println!(" Caused by: {}", source);
71+
}
72+
},
6373
}
6474
}
6575

0 commit comments

Comments
 (0)