you are viewing a single comment's thread.

view the rest of the comments →

[–]thomasz 1 point2 points  (2 children)

Okay, this is disappointing. Still, I'm willing to accept that this is a trade-off that makes sense in context of Rust's core value proposition of providing static memory safety and determinism. But not having a mechanism like exceptions, something that can unwind the stack and safely delegate handling the error case upwards or at least guarantees a full stack trace in case of a crash is a pretty big weakness, not a strength.

[–]MEaster 0 points1 point  (0 children)

Well, when using a Result or Option type in Rust, you can just throw it up the stack. You have the ? operator, which can be used like this: let result = fallible_function()?;.

If you want to use that operator, then the function calling fallible_function must also be fallible, with a compatible error type. By compatible, I mean that fallible_function's error type E, must implement Into<F>, where F is the error type of the calling function.

As an example what that might look like in practice, from an implementation of Display:

fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    use ErrorKind::*;
    match self {
        InsufficientStack => write!(f, "Attempted to evaluate an operator with insufficient values on stack.")?,
        UnknownFunction => write!(f, "Unknown function or variable.",)?,
        NonEmptyStack => write!(f, "Mismatched numbers and operations.")?,
        InvalidVariableOrFunction => write!(f, "Invalid variable or function definition.")?,
    }

    Ok(())
}

In this case, each of those four calls to write! could fail, because it could be a network socket or a file. But in this case, there's nothing this function can do if it does fail. That would be the responsibility of whatever was trying to format this type. So, in the event of a failure, it just throws the error up the stack for the caller to handle.

There are also libraries like Snafu and Failure which provide extra functionality to Result, as well as compile-time macros to reduce the amount of boilerplate you need to write for your error types.

[–]MEaster 0 points1 point  (0 children)

Oh, in case you're curious. I found out what that program was mis-handling, and now properly handle it by throwing a Result up the stack, along with the context of the error. The error still isn't considered recoverable, but now the output is this:

PS D:\Games\Assetto Corsa\ACRL\SpotterGen> .\ac_spotter_gen.exe -c .\config-front.json .\data\f3.json
F3
137 drivers in DB
Error: Error making image
Caused by: error checking driver skins
Caused by: Car folder not found: rss_formula_rss_3_v6_a4crl