Skip to content

error handling #39

@jadamcrain

Description

@jadamcrain

We currently have a very disjointed way of performing error handling in our FFI methods. We sometimes
return "null" where possible, but we really don't have a sound methodology for handling error conditions.

This is a proposal for how we can explicity encode error handling into the model.

consider a creation function which might fail:

Foo* create_foo(FOOConfig config, Other* other);

It could fail for a number of reasons, e.g.:

  1. something in the config is bad / not allowed
  2. the pointer other is null or something (e.g. a runtime) has already been destroyed

We can encode all of the possible failures as a special error type. Typically there would only be one such
error type for a library, but we'd design it such that multiple error types can co-exist:

let error = lib
              .define_error("error", "ok")? // the name of the error and the ok variant (which must exist)
              .add("bad_parameter")?
              .add("null_parameter")?
              .add("runtime_shutdown")?
              .build()?;

In native functions that can fail, we simply declare that the function is fallible:

let function = lib
                 .define_native_function("..")?
                 ...
                 .fallible(error)?
                 .build()?;

Now that this information is part of the model for every function, we can map this in back-end specific ways.

In C, fallible functions will always return the error as an enum and add an out parameter if there is a return type:

error_t create_c(A config, B* pointer, Foo** out);

This is a well-defined pattern that we can use for any function which might be fallible. This will allow C users to check that the error code is "ok" before proceeding.

OO languages can generate an exception type for each error type in a library:

ErrorException {
Error error;
}

Native functions can be wrapped into "exception" functions.

Most of our Java/C# code won't have to change at all except that they'll magically start throwing exceptions instead
of returning null, panicking, or silently failing. All we need is a thin generated layer that checks errors from the FFI
and tosses an exception if this occurs. Since the error information is now on every relevant function/method we can even produce
exception documentation automatically.

Metadata

Metadata

Assignees

Labels

schemaIssue regarding the schema

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions