logoalt Hacker News

nateb2022yesterday at 10:01 PM1 replyview on HN

> 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.


Replies

vsgherziyesterday at 10:41 PM

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.