Skip to content

Error handling guide #18903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 20, 2014
Merged

Error handling guide #18903

merged 2 commits into from
Nov 20, 2014

Conversation

steveklabnik
Copy link
Member

Now that we've done fail -> panic, I feel bringing back the error handling guide is a good idea. We had one long ago, but it was removed when conditions were removed.

This doesn't cover the new FromError stuff, but I feel like it's already useful in this state, so I'm sending this PR now.

}
```

If we ever hit the third match arm, something is very, very wrong. Rust calls
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be better to use a different example for unreachable!(). In this one unreachable!() is used to work-around a compiler limitation and if I didn't know that when reading this, I'd be very confused by what it is you mean by something very, very wrong.

I'll try to be constructive and come up with a better example but essentially anything where unreachable!() specifies an invariant in the control flow that's not encoded in the types would do, I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the compiler going to be able to figure this out eventually? How would it do it?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most likely not, it'd after all require incorporating a complete SMT solver the way Liquid Haskell does and it'd only work for some subset of Rust. From the user's perspective it is still, however, a compiler limitation. Maybe it is useful to mention this unreachable!() use case separately, though. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then why is this a bad example? I guess I'm not seeing the distinction you're drawing here.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for example in rustc we have the ast::Expr_ enum, which enumerates all the possible expression nodes. One of the variants is ExprIfLet, however, in most of the components of the compiler encountering a value of that variant is a contract violation because the if let construct is desugared at a very early stage, immediately after a program is parsed.

This is the sort of a thing that I tend to use unreachable!() for and I think it's good for: expressing paths in the control flow that should not be reached according to an implicit contract enforced in a different part of my program. This is a bit subtle but still different than using it for essentially "hacking" the compiler to accept your program.

Anyway, I am being slightly pedantic here, I just thought that we could do better here, how about something like this:

enum Event {
    Rust10ShipsIn2015
}

fn probability(_: &Event) -> f64 {
    0.95
}

fn descriptive_probability(event: Event) -> &'static str {
    match probability(&event) {
        1.00          => "certain",
        0.00          => "impossible",
        0.00 ... 0.25 => "very unlikely",
        0.25 ... 0.50 => "unlikely",
        0.50 ... 0.75 => "likely",
        0.75 ... 1.00  => "very likely",
        _ => unreachable!()
    }
}

fn main() {
    std::io::println(descriptive_probability(Rust10ShipsIn2015));
}

Feel free to cut down if you think it's a good fit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed things to add this :)

@ghost
Copy link

ghost commented Nov 12, 2014

This looks very good, I think. I wonder if it'd also be useful to talk about downgrading panics to failures by isolating them in separate tasks. Or rather, elaborating more on the idea that tasks provide a natural boundary for panics to be isolated from other parts of a system.

line. This allows us to handle and possibly recover from this sort of error.

If we don't want to handle this error, and would rather just abort the program,
we can use two methods, `ok()` and `unwrap()`:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah! So, I forgot that unwrap is on Result too.

@oli-obk
Copy link
Contributor

oli-obk commented Nov 13, 2014

also, this guide overlaps with the result-docs. Maybe unify them?
http://doc.rust-lang.org/core/result/index.html

@steveklabnik
Copy link
Member Author

It does overlap a bunch. We should pull some of the broader stuff out of the Result docs and put it here.

@steveklabnik
Copy link
Member Author

This should be good to ship, r?

error: non-exhaustive patterns: `_` not covered [E0004]
```

While we know that we've covered all possible cases, Rust can't tell. So we add
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Could we maybe just point out why it is we've handled all possible cases (i.e. probability having a value between 0 and 1)?

@ghost
Copy link

ghost commented Nov 18, 2014

@steveklabnik This looks very nice! A few more nits from me and I'm happy but maybe another pair of eyes would be useful too.

@steveklabnik
Copy link
Member Author

Updated with everything but try!. I'm not opposed to it going in, but figured I'd get the rest up quick in case someone wants to look at it.

```

We shouldn't ever hit the `_` case, so we use the `unreachable!()` macro to
indicate this. `unreachable!()` gives a differnet kind of error than `Result`.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/differnet/different

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, fixed

@steveklabnik
Copy link
Member Author

We currently document try! in the Result module, and I think I'm just going to leave it there for now.

@bors bors merged commit 16b9f67 into rust-lang:master Nov 20, 2014
lnicola pushed a commit to lnicola/rust that referenced this pull request Jan 20, 2025
Implement implicit sized bound inlay hints
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants