Skip to content

Instantly share code, notes, and snippets.

@U007D
Last active October 12, 2017 16:11
Show Gist options
  • Select an option

  • Save U007D/07b045f0e74566716fe6e6171c8eef47 to your computer and use it in GitHub Desktop.

Select an option

Save U007D/07b045f0e74566716fe6e6171c8eef47 to your computer and use it in GitHub Desktop.
Issues with using Errors in Rust

No consistent basis with which to work with Errors

(inconsistencies or issues in bold)

using the Standard Library

  • std::fmt::Error:

    • is a (marker) struct
    • does implement PartialEq (among other traits)
    • does not implement a kind() method
    • does not define ErrorKind variants
  • std::io::Error:

    • is a struct encapsulating an enum
    • does not implement PartialEq
    • does implement a kind() method
    • does implements ErrorKind variants which implement PartialEq
  • std::error::Error

    • is a trait
    • does not define or implement PartialEq
    • does not define or implement a kind() method
    • does hot define ErrorKind variants

using error-chain

  • error-chain
    • is Rust's defacto-standard error-handling crate
    • does not implement PartialEq
    • does implement a kind() method
    • does implement ErrorKind variants which do not implement PartialEq

using pattern matching

  • pattern-matching (as opposed to via PartialEq) is often cited as the recommended way to distinguish Errors, given these numerous inconsistencies). There are crates (such as matches) for reducing boilerplate when pattern-matching
  • pattern matching Errors adds boilerplate, obfuscates code and is an incomplete solution. e.g.:
fn string_validator_ref_handles_empty_input() {
  // GivenNotes:
  let input = String::new();
  let expected_result = ErrorKind::ValueNone;

  // When
  let result = (&input).validate_ref::<NonEmptyStringValidator>().err().unwrap()
/* Idealized */

// Then
  assert_eq!(*result, expected_result);
}
/* Reality */

// Then
  assert!(matches!(*result, expected_result); //Error: pattern unreachable (match doesn't work this way; unintuitive at this level)
  assert!(matches!(*result, val if val == expected_result)); //not ergonomic; Error: binary operation `==` cannot be applied to type `error::ErrorKind`
  assert!(matches!(*result, ErrorKind::ValueNone); //works, but without variable support, important scenarios become unrepresentable:
      // suppose two methods must yield same result.  To ensure consistency through refactorings, a test is developed:
      // assert!(matches(*result_a, *result_b) //not possible, as per above; constant solution not available
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment