Skip to content

Rolling up PRs in the queue #19118

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 41 commits into from Nov 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8347450
libstd: improve os::args() doc
liigo Nov 14, 2014
0f11eb5
Guide: add a pointer to play.rust-lang.org and explain how to run the…
danluu Nov 15, 2014
2aa241d
Reference: Add missing third dot of range
cakebaker Nov 18, 2014
33f8a82
librustrt: check for mips+linux config in stack_overflow
Nov 18, 2014
0e6d97a
New guide: error handling
steveklabnik Nov 12, 2014
bde225e
Feature gate non-ASCII lifetime identifiers
Nov 18, 2014
ad61ff4
deriving: error out when used on a non-type
kmcallister Nov 18, 2014
16b9f67
Error handling guide
steveklabnik Nov 12, 2014
5b5638f
Switch to an independent enum for `Lit*` subtokens.
huonw Nov 18, 2014
9d20a46
Update src/grammar for language changes.
huonw Nov 19, 2014
ff0278b
Update makefiles to ensure src/grammar/verify.rs is built.
huonw Nov 19, 2014
4af3494
std: Stabilize std::fmt
alexcrichton Nov 17, 2014
38b1425
iOS: fixed broken build after disallowed coercions
vhbit Nov 19, 2014
210e059
clearly define `int` and `uint` to fix unsoundness
thestinger Nov 7, 2014
b64c7b8
Refactor QPath to take an ast::TraitRef
nikomatsakis Nov 8, 2014
0b6ec70
Ensure that the type parameters passed to methods outlive the call ex…
nikomatsakis Nov 14, 2014
2477bc4
Update libcollections tests to pass the new type rules. They used to …
nikomatsakis Nov 14, 2014
6679595
Parse and store suffixes on literals.
huonw Nov 19, 2014
606a309
Switch numeric suffix parsing to use the new system.
huonw Nov 19, 2014
7586abf
Adjust Antlr4 lexer to include suffixes.
huonw Nov 19, 2014
a11078f
Update documentation for literal suffixes.
huonw Nov 19, 2014
ebe812f
Reference: Change "an box" to "a box"
cakebaker Nov 19, 2014
40aa833
Document almost all of atomics.
steveklabnik Nov 19, 2014
1b5cbd0
Forbid matching struct variants with tuple variant patterns
Nov 18, 2014
fee71bd
rollup merge of #18728: thestinger/int
Nov 19, 2014
655eb44
rollup merge of #18868: nikomatsakis/issue-17388-unbound-path-assoc-type
Nov 19, 2014
cbdaf2e
rollup merge of #18903: steveklabnik/error_handling_guide
Nov 19, 2014
0191b49
rollup merge of #18940: nikomatsakis/issue-18899
Nov 19, 2014
f6b4e39
rollup merge of #18944: liigo/improve-os-args-doc
Nov 19, 2014
384f611
rollup merge of #18968: danluu/guide_play
Nov 19, 2014
a22f06d
rollup merge of #19040: alexcrichton/issue-18904
Nov 19, 2014
8997b09
rollup merge of #19072: cakebaker/add_missing_dot
Nov 19, 2014
1faa096
rollup merge of #19073: jakub-/issue-19069
Nov 19, 2014
9b5ec0e
rollup merge of #19076: jxv/master
Nov 19, 2014
7884dd9
rollup merge of #19087: jakub-/issue-19086
Nov 19, 2014
c28acd0
rollup merge of #19090: kmcallister/deriving-non-type
Nov 19, 2014
00ffcca
rollup merge of #19101: vhbit/ios-rng-fix
Nov 19, 2014
f71b852
rollup merge of #19103: huonw/literal-suffixes
Nov 19, 2014
1b8ee82
rollup merge of #19107: cakebaker/change_an_box_to_a_box
Nov 19, 2014
2e9f705
rollup merge of #19108: steveklabnik/doc_atomic_bool
Nov 19, 2014
ee66c84
Fixes to the roll-up
Nov 19, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,7 @@ do
make_dir $h/test/doc-guide-tasks
make_dir $h/test/doc-guide-plugin
make_dir $h/test/doc-guide-crates
make_dir $h/test/doc-guide-error-handling
make_dir $h/test/doc-rust
done

Expand Down
2 changes: 1 addition & 1 deletion mk/docs.mk
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
######################################################################
DOCS := index intro tutorial guide guide-ffi guide-macros guide-lifetimes \
guide-tasks guide-container guide-pointers guide-testing \
guide-plugin guide-crates complement-bugreport \
guide-plugin guide-crates complement-bugreport guide-error-handling \
complement-lang-faq complement-design-faq complement-project-faq \
rustdoc guide-unsafe guide-strings reference

Expand Down
16 changes: 12 additions & 4 deletions mk/grammar.mk
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,25 @@ endef
$(BG):
$(Q)mkdir -p $(BG)

$(BG)RustLexer.class: $(SG)RustLexer.g4
$(BG)RustLexer.class: $(BG) $(SG)RustLexer.g4
$(Q)$(CFG_ANTLR4) -o $(B)grammar $(SG)RustLexer.g4
$(Q)$(CFG_JAVAC) -d $(BG) $(BG)RustLexer.java

$(BG)verify: $(SG)verify.rs rustc-stage2-H-$(CFG_BUILD) $(LD)stamp.regex_macros $(LD)stamp.rustc
$(Q)$(RUSTC) -O --out-dir $(BG) -L $(L) $(SG)verify.rs
check-build-lexer-verifier: $(BG)verify

ifeq ($(NO_REBUILD),)
VERIFY_DEPS := rustc-stage2-H-$(CFG_BUILD) $(LD)stamp.regex_macros $(LD)stamp.rustc
else
VERIFY_DEPS :=
endif

$(BG)verify: $(BG) $(SG)verify.rs $(VERIFY_DEPS)
$(Q)$(RUSTC) --out-dir $(BG) -L $(L) $(SG)verify.rs

ifdef CFG_JAVAC
ifdef CFG_ANTLR4
ifdef CFG_GRUN
check-lexer: $(BG) $(BG)RustLexer.class $(BG)verify
check-lexer: $(BG) $(BG)RustLexer.class check-build-lexer-verifier
$(info Verifying libsyntax against the reference lexer ...)
$(Q)$(SG)check.sh $(S) "$(BG)" \
"$(CFG_GRUN)" "$(BG)verify" "$(BG)RustLexer.tokens"
Expand Down
2 changes: 1 addition & 1 deletion mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ check-docs: cleantestlibs cleantmptestlogs check-stage2-docs

# Some less critical tests that are not prone to breakage.
# Not run as part of the normal test suite, but tested by bors on checkin.
check-secondary: check-build-compiletest check-lexer check-pretty
check-secondary: check-build-compiletest check-build-lexer-verifier check-lexer check-pretty

# check + check-secondary.
#
Expand Down
228 changes: 228 additions & 0 deletions src/doc/guide-error-handling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
% Error Handling in Rust

> The best-laid plans of mice and men
> Often go awry
>
> "Tae a Moose", Robert Burns

Sometimes, things just go wrong. It's important to have a plan for when the
inevitable happens. Rust has rich support for handling errors that may (let's
be honest: will) occur in your programs.

There are two main kinds of errors that can occur in your programs: failures,
and panics. Let's talk about the difference between the two, and then discuss
how to handle each. Then, we'll discuss upgrading failures to panics.

# Failure vs. Panic

Rust uses two terms to differentiate between two forms of error: failure, and
panic. A **failure** is an error that can be recovered from in some way. A
**panic** is an error that cannot be recovered from.

What do we mean by 'recover'? Well, in most cases, the possibility of an error
is expected. For example, consider the `from_str` function:

```{rust,ignore}
from_str("5");
```

This function takes a string argument and converts it into another type. But
because it's a string, you can't be sure that the conversion actually works.
For example, what should this convert to?

```{rust,ignore}
from_str("hello5world");
```

This won't work. So we know that this function will only work properly for some
inputs. It's expected behavior. We call this kind of error 'failure.'

On the other hand, sometimes, there are errors that are unexpected, or which
we cannot recover from. A classic example is an `assert!`:

```{rust,ignore}
assert!(x == 5);
```

We use `assert!` to declare that something is true. If it's not true, something
is very wrong. Wrong enough that we can't continue with things in the current
state. Another example is using the `unreachable!()` macro

```{rust,ignore}
enum Event {
NewRelease,
}

fn probability(_: &Event) -> f64 {
// real implementation would be more complex, of course
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",
}
}

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

This will give us an error:

```{notrust,ignore}
error: non-exhaustive patterns: `_` not covered [E0004]
```

While we know that we've covered all possible cases, Rust can't tell. It
doesn't know that probability is between 0.0 and 1.0. So we add another case:

```rust
use Event::NewRelease;

enum Event {
NewRelease,
}

fn probability(_: &Event) -> f64 {
// real implementation would be more complex, of course
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() {
println!("{}", descriptive_probability(NewRelease));
}
```

We shouldn't ever hit the `_` case, so we use the `unreachable!()` macro to
indicate this. `unreachable!()` gives a different kind of error than `Result`.
Rust calls these sorts of errors 'panics.'

# Handling errors with `Option` and `Result`

The simplest way to indicate that a function may fail is to use the `Option<T>`
type. Remember our `from_str()` example? Here's its type signature:

```{rust,ignore}
pub fn from_str<A: FromStr>(s: &str) -> Option<A>
```

`from_str()` returns an `Option<A>`. If the conversion succeeds, it will return
`Some(value)`, and if it fails, it will return `None`.

This is appropriate for the simplest of cases, but doesn't give us a lot of
information in the failure case. What if we wanted to know _why_ the conversion
failed? For this, we can use the `Result<T, E>` type. It looks like this:

```rust
enum Result<T, E> {
Ok(T),
Err(E)
}
```

This enum is provided by Rust itself, so you don't need to define it to use it
in your code. The `Ok(T)` variant represents a success, and the `Err(E)` variant
represents a failure. Returning a `Result` instead of an `Option` is recommended
for all but the most trivial of situations.

Here's an example of using `Result`:

```rust
#[deriving(Show)]
enum Version { Version1, Version2 }

#[deriving(Show)]
enum ParseError { InvalidHeaderLength, InvalidVersion }

fn parse_version(header: &[u8]) -> Result<Version, ParseError> {
if header.len() < 1 {
return Err(ParseError::InvalidHeaderLength);
}
match header[0] {
1 => Ok(Version::Version1),
2 => Ok(Version::Version2),
_ => Err(ParseError::InvalidVersion)
}
}

let version = parse_version(&[1, 2, 3, 4]);
match version {
Ok(v) => {
println!("working with version: {}", v);
}
Err(e) => {
println!("error parsing header: {}", e);
}
}
```

This function makes use of an enum, `ParseError`, to enumerate the various
errors that can occur.

# Non-recoverable errors with `panic!`

In the case of an error that is unexpected and not recoverable, the `panic!`
macro will induce a panic. This will crash the current task, and give an error:

```{rust,ignore}
panic!("boom");
```

gives

```{notrust,ignore}
task '<main>' panicked at 'boom', hello.rs:2
```

when you run it.

Because these kinds of situations are relatively rare, use panics sparingly.

# Upgrading failures to panics

In certain circumstances, even though a function may fail, we may want to treat
it as a panic instead. For example, `io::stdin().read_line()` returns an
`IoResult<String>`, a form of `Result`, when there is an error reading the
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 the `unwrap()` method:

```{rust,ignore}
io::stdin().read_line().unwrap();
```

`unwrap()` will `panic!` if the `Option` is `None`. This basically says "Give
me the value, and if something goes wrong, just crash." This is less reliable
than matching the error and attempting to recover, but is also significantly
shorter. Sometimes, just crashing is appropriate.

There's another way of doing this that's a bit nicer than `unwrap()`:

```{rust,ignore}
let input = io::stdin().read_line()
.ok()
.expect("Failed to read line");
```
`ok()` converts the `IoResult` into an `Option`, and `expect()` does the same
thing as `unwrap()`, but takes a message. This message is passed along to the
underlying `panic!`, providing a better error message if the code errors.
2 changes: 2 additions & 0 deletions src/doc/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ $ ./main # or main.exe on Windows
Hello, world!
```

You can also run these examples on [play.rust-lang.org](http://play.rust-lang.org/) by clicking on the arrow that appears in the upper right of the example when you mouse over the code.

Success! Let's go over what just happened in detail.

```{rust}
Expand Down
1 change: 1 addition & 0 deletions src/doc/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ a guide that can help you out:
* [References and Lifetimes](guide-lifetimes.html)
* [Crates and modules](guide-crates.html)
* [Tasks and Communication](guide-tasks.html)
* [Error Handling](guide-error-handling.html)
* [Foreign Function Interface](guide-ffi.html)
* [Writing Unsafe and Low-Level Code](guide-unsafe.html)
* [Macros](guide-macros.html)
Expand Down
1 change: 1 addition & 0 deletions src/doc/po4a.conf
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
[type: text] src/doc/guide-testing.md $lang:doc/l10n/$lang/guide-testing.md
[type: text] src/doc/guide-unsafe.md $lang:doc/l10n/$lang/guide-unsafe.md
[type: text] src/doc/guide-crates.md $lang:doc/l10n/$lang/guide-crates.md
[type: text] src/doc/guide-error-handling.md $lang:doc/l10n/$lang/guide-error-handling.md
[type: text] src/doc/guide.md $lang:doc/l10n/$lang/guide.md
[type: text] src/doc/index.md $lang:doc/l10n/$lang/index.md
[type: text] src/doc/intro.md $lang:doc/l10n/$lang/intro.md
Expand Down
Loading