> I own the code that I bring into my repo, I belive the standard library is sufficent for my needs without having to pull in more crates.
Unless you're working on something with extremely limited scope, dependencies will become unavoidable; without resorting to reinventing many wheels.
> This is not THE idiomatic way to write rust but rather the way that I write errors. > impl From<std::num::ParseIntError> for DemoError { > fn from(error: std::num::ParseIntError) -> Self { > DemoError::ParseErr(error) > } > }
This introduces a lot of observability risk.
You've essentially built a context eraser. By using a generic From impl with the ? operator, you’re prioritizing brevity during the "happy path" write, but you're losing the "Why" of the error. If my_function has five different string-to-int conversions, your logs will just tell you "Invalid Digit." Good luck grep-ing that in a 100k LOC codebase.
map_err can help fix this, but look at what that does to your logic:
let my_number: i32 = first_input
.parse()
.map_err(|_|
DemoError::new(DemoErrorKind::FirstNumberErr(
first_input.into()
))
)?;
In a real-world refactor, someone is going to change first_input to validated_input and forget to update the variable inside that closure. Now your error message will report the wrong data. It sends the SRE team down a rabbit hole investigating the wrong input while the real bug sits elsewhere.And by calling error.to_string() in your Display impl:
DemoErrorKind::ParseErr(error) => write!(
f,
"error parsing with {}", error.to_string()
),
...you are manually "flattening" the error. You’ve just nuked the original error's type identity. If a caller up the stack wanted to programmatically handle a specific ParseIntError variant, they can't. You've turned a structured error into a "stringly-typed" nightmare.Realistically your risk of mismanaging your boilerplate is significantly higher than a supply chain attack on a crate maintained by the core library team.
This particular one is just how I decided to take context. You could easily keep the original error type and add context onto the struct as an additional field. Or an alternative could be to take a string and the error type. The I’m using someone’s library because I don’t trust myself argument doesn’t really track for me.