Skip to content

Tracking issue: Replace unwrap with expect #3899

Description

Explanation

Calling unwrap on an Option or Result causes the program to panic if the Option is None or the Result is Err. If the program panics because of an unwrap call, the error message isn't really helpful. To help contributors and users of bevy find problems faster we can use expect to our advantage. Calling expect works exactly the same as unwrap, but allows us to pass a string containing an explanation of why the panic occurred or rather what we expected to be the case.

Example

Unwrap

fn main() {
    // Panics with the following message:
    // thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:5:12
    let number: Option<i32> = None;
    number.unwrap();

    // Doesn't panic.
    let number: Option<i32> = Some(1);
    number.unwrap();
}

Expect

fn main() {
    // Panics with the following message:
    // thread 'main' panicked at 'Number should exist', src/main.rs:5:12
    let number: Option<i32> = None;
    number.expect("Number should exist");

    // Doesn't panic.
    let number: Option<i32> = Some(1);
    number.expect("Number should exist");
}

To-Do

Replace most of the unwraps inside of the individual crates with more explanatory expects. Changing the unwrap calls inside of our main code is more important than inside of our tests, but it's appreciated if it is done in both.

General error handling

Through the PR's made for this tracking issue we realized that we have a lot of very similar and common error messages that all have to stay consistent for a good user and developer experience. Since this is hard to maintain we want to introduce better error handling in general for things like getting a resource (#4047).

If you realize that in one of your PR's you are writing the same error message multiple times, you might as well consider doing something similar to #4047 and create better error handling for those things.

Invariants

Not every unwrap call should be replaced with expect. This is because sometimes unwrap is used on an invariant. An invariant is something that doesn't vary and can therefore be assumed to always successfully unwrap without panicking.

Error codes

Whenever possible and reasonable please add the error to the error codes when adding an error message. This should only be done for errors that can't be explained in a single line and therefore need a more in depth explanation of how to fix the error.

No final dot

There shouldn't be a dot at the end of an error message. This is because Rust will add : Err at the end of an expect error message on a Result. On an Option this looks fine, but to keep it consistent don't add a dot there either.

Example

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=aed00b15860c0c31534e110ca7852a4d

// expect on an Option
thread 'main' panicked at 'this is an error message.', src/main.rs:9:16

// expect on a Result
thread 'main' panicked at 'this is an error message.: Err1', src/main.rs:9:16

Crates

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-Code-QualityA section of code that is hard to understand or changeC-Tracking-IssueAn issue that collects information about a broad development initiative

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions