-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
💥 Proposal
While beginning to address #2941 and investigating the feasibility of introducing Result in some locations, I've noticed that anyhow::Result is exposed from the snarkvm_console_network_environment::prelude, and is used throughout a lot of the library crates.
While anyhow can be convenient for not having to think about creating new error types, it is not designed for use within libraries or to be exposed in public APIs.
This is a proposal to remove anyhow::Result from the prelude, and to progressively replace the use of anyhow for error handling throughout the VM libraries with thiserror. I've noticed there is already some use of thiserror which is great!
Motivation
The author of thiserror and anyhow distinguishes between the use-cases for the two crates briefly in the thiserror README:
Use thiserror if you care about designing your own dedicated error type(s) so that the caller receives exactly the information that you choose in the event of failure. This most often applies to library-like code. Use Anyhow if you don't care what error type your functions return, you just want it to be easy. This is common in application-like code.
Problems with anyhow in libraries:
- Loss of type information: Downstream code cannot match on specific error variants or exhaustively handle different failure modes. Accessing and handling underlying errors requires downcasting which can fail (e.g. can be a problem when refactoring).
- Poor API boundaries:
anyhow::Erroris essentiallyBox<dyn Error>- it's meant for applications that just propagate errors to users, not libraries that need to expose errors as part of their public API. - Documentation gaps: Error variants aren't visible in generated docs, leaving users guessing about the set of possible failure modes. Ideally, a user can read the error type returned within the
Resultand see all possible failure modes for the API their calling.
Benefits of thiserror in libraries:
- Concrete error enums that can be matched and handled exhaustively in a type-safe manner (i.e. no downcasting required).
- Library users can see the full set of possible failure modes just by looking at the error type.
- Proper error composition through transparent wrapping of underlying errors.
Having nice error types would be great for consumers of the snarkvm libs (like leo tooling) so that we can handle different error variants accordingly (e.g. handling a VM halt vs some deployment failure).
Implementation
This might look something like:
- Remove
anyhow::Resultfromsnarkvm_console_network_environment::preludeso that it no longer overrides theResulttype from the std prelude. - When introducing new errors, use
thiserrorto declare concrete types. - Temporarily provide a
Anyhowvariant in concrete error types where necessary as a temporarily workaround? - Open a tracking issue for replacing all
anyhowuse within libraries with dedicated error types/variants (could be a good issue for juniors or newcomers).