danielpclark / rutie

“The Tie Between Ruby and Rust.”
MIT License
938 stars 62 forks source link

Mark exception-raising functions as diverging #158

Closed georgeclaghorn closed 1 year ago

georgeclaghorn commented 2 years ago

This allows, for example, raising in a match arm without the need to return a dummy value. The following compiles when VM::raise diverges:

fn serialize() -> RString {
    // ...

    match stylesheet.to_css() {
        Ok(output) => RString::new_utf8(&output.code),
        Err(_) => VM::raise(Class::from_existing("StandardError"), "failed to generate CSS")
    }
}

Without these changes, the above fails to compile:

error[E0308]: `match` arms have incompatible types
   --> src/stylesheet.rs:103:23
    |
101 | /         match stylesheet.to_css() {
102 | |             Ok(output) => RString::new_utf8(&output.code),
    | |                           ------------------------------- this is found to be of type `rutie::RString`
103 | |             Err(_) => VM::raise(Class::from_existing("StandardError"), "failed to generate CSS")
    | |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `rutie::RString`, found `()`
104 | |         }
    | |_________- `match` arms have incompatible types

In general, we no longer need to program as though execution might continue past VM::raise when we know it doesn’t.