← Back to context

Comment by kazinator

18 hours ago

The success and error types are not the same, because they are in different positions in the type, and so distinguished by different patterns.

If you have literally the above convention where a valid result is a String, and an error result is also a String (e.g. error message) that is still type safe.

  match (whatever()) {
    Ok(s) => println!("good result string: {s}"),
    Err(s) => println!("error string: {s}"),
  }

The success type and error type having to be different is not a good way to express the idea; rather that success and error cases are distinguished by type (even if the success and error data units are of the same type).

In other words, the "Ok" and "Err" entities are an ingredient of the type and that effectively makes the result and error be distinguished at the type level.

But we could also argue that Rust still allows you to write an integer-returning function such that -1 means error.

Basically, you need the whole 'success and error types are different' in a language like Python if you make the return type something like "int | string", where 'string' stands for your error message.

Of course that breaks down, when the success type is also an error message, eg when you are looking up something in a catalogue of error messages.

Rust has no trouble with this, for exactly the reasons you line out.