Idea: Error conditions in function signature

While coding in Rust, I don't have to keep a lot of things in my head thanks to the strong guarantees provided by the compiler. In contrast, while coding in Python, I have to remember what are the exact names of the attributes of duck that def use_duck(duck) uses. Not to mention whether use_duck is allowed to modify duck or am I allowed to use duck again after the function exits.

Most of the information that we need to correctly use a function is provided in the type signature of that function.

Although, there is one more thing that is desirable in the type signature: The error conditions expected by the function.
This is inspired from this post: http://web.archive.org/web/20080916193133/http://dlweinreb.wordpress.com/2008/03/24/what-conditions-exceptions-are-really-about/

For example:

fn open_file(path: &str, mode: Mode) -> File 
errors [MalformedPath, FileNotFound, IOError] {
// ....
}

fn do_something_with_file()
errors [FailedToOpenFile{msg: String}] {
    let file = open_file("/foo/bar.txt", Mode::ReadOnly)
                .map_err(|err| match err {
                    MalformedPath => FailedToOpenFile{
                        msg: String::from("Please make sure the path is well fromed")
                    },
                    _ => FailedToOpenFile{
                        msg: String::from("Unexpected error while trying to open file")
                    }
                })?;
    // do stuff with file
}

Compared to checked exceptions in Java, adding a new error condition to open_file, say PermissionDenied doesn't require us to modify do_something_with_file() because we use a catch all pattern while matching over errors.

I am not sure how easy this is to implement.
One simple (from the user's perspective) way to do this is by desugaring:

fn foo(..) -> T
errors[ <<errors>> ] {..}

// this desugars to
enum _FooError {
<<errors>>
}

fn foo(..) -> Result<T, _FooError> {..}

But that leaves the question of how to refer to the generated enums while pattern matching over it.
It would be really nice and ergonomic if the compiler is able to infer this from the types.

Is it possible to implement something similar to this?
Is it possible in today's Rust to approximate this?
Do you have any other idea to make error conditions more visible?

This seems like a better question for internals.rust-lang.org

This looks like anonomous sum types to me.

1 Like