]> git.lizzy.rs Git - rust.git/blob - src/doc/book/error-handling.md
Auto merge of #30145 - petrochenkov:hyg, r=nrc
[rust.git] / src / doc / book / error-handling.md
1 % Error Handling
2
3 Like most programming languages, Rust encourages the programmer to handle
4 errors in a particular way. Generally speaking, error handling is divided into
5 two broad categories: exceptions and return values. Rust opts for return
6 values.
7
8 In this chapter, we intend to provide a comprehensive treatment of how to deal
9 with errors in Rust. More than that, we will attempt to introduce error handling
10 one piece at a time so that you'll come away with a solid working knowledge of
11 how everything fits together.
12
13 When done naïvely, error handling in Rust can be verbose and annoying. This
14 chapter will explore those stumbling blocks and demonstrate how to use the
15 standard library to make error handling concise and ergonomic.
16
17 # Table of Contents
18
19 This chapter is very long, mostly because we start at the very beginning with
20 sum types and combinators, and try to motivate the way Rust does error handling
21 incrementally. As such, programmers with experience in other expressive type
22 systems may want to jump around.
23
24 * [The Basics](#the-basics)
25     * [Unwrapping explained](#unwrapping-explained)
26     * [The `Option` type](#the-option-type)
27         * [Composing `Option<T>` values](#composing-optiont-values)
28     * [The `Result` type](#the-result-type)
29         * [Parsing integers](#parsing-integers)
30         * [The `Result` type alias idiom](#the-result-type-alias-idiom)
31     * [A brief interlude: unwrapping isn't evil](#a-brief-interlude-unwrapping-isnt-evil)
32 * [Working with multiple error types](#working-with-multiple-error-types)
33     * [Composing `Option` and `Result`](#composing-option-and-result)
34     * [The limits of combinators](#the-limits-of-combinators)
35     * [Early returns](#early-returns)
36     * [The `try!` macro](#the-try-macro)
37     * [Defining your own error type](#defining-your-own-error-type)
38 * [Standard library traits used for error handling](#standard-library-traits-used-for-error-handling)
39     * [The `Error` trait](#the-error-trait)
40     * [The `From` trait](#the-from-trait)
41     * [The real `try!` macro](#the-real-try-macro)
42     * [Composing custom error types](#composing-custom-error-types)
43     * [Advice for library writers](#advice-for-library-writers)
44 * [Case study: A program to read population data](#case-study-a-program-to-read-population-data)
45     * [Initial setup](#initial-setup)
46     * [Argument parsing](#argument-parsing)
47     * [Writing the logic](#writing-the-logic)
48     * [Error handling with `Box<Error>`](#error-handling-with-boxerror)
49     * [Reading from stdin](#reading-from-stdin)
50     * [Error handling with a custom type](#error-handling-with-a-custom-type)
51     * [Adding functionality](#adding-functionality)
52 * [The short story](#the-short-story)
53
54 # The Basics
55
56 You can think of error handling as using *case analysis* to determine whether
57 a computation was successful or not. As you will see, the key to ergonomic error
58 handling is reducing the amount of explicit case analysis the programmer has to
59 do while keeping code composable.
60
61 Keeping code composable is important, because without that requirement, we
62 could [`panic`](../std/macro.panic!.html) whenever we
63 come across something unexpected. (`panic` causes the current task to unwind,
64 and in most cases, the entire program aborts.) Here's an example:
65
66 ```rust,should_panic
67 // Guess a number between 1 and 10.
68 // If it matches the number we had in mind, return true. Else, return false.
69 fn guess(n: i32) -> bool {
70     if n < 1 || n > 10 {
71         panic!("Invalid number: {}", n);
72     }
73     n == 5
74 }
75
76 fn main() {
77     guess(11);
78 }
79 ```
80
81 If you try running this code, the program will crash with a message like this:
82
83 ```text
84 thread '<main>' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5
85 ```
86
87 Here's another example that is slightly less contrived. A program that accepts
88 an integer as an argument, doubles it and prints it.
89
90 <span id="code-unwrap-double"></span>
91
92 ```rust,should_panic
93 use std::env;
94
95 fn main() {
96     let mut argv = env::args();
97     let arg: String = argv.nth(1).unwrap(); // error 1
98     let n: i32 = arg.parse().unwrap(); // error 2
99     println!("{}", 2 * n);
100 }
101 ```
102
103 If you give this program zero arguments (error 1) or if the first argument
104 isn't an integer (error 2), the program will panic just like in the first
105 example.
106
107 You can think of this style of error handling as similar to a bull running
108 through a china shop. The bull will get to where it wants to go, but it will
109 trample everything in the process.
110
111 ## Unwrapping explained
112
113 In the previous example, we claimed
114 that the program would simply panic if it reached one of the two error
115 conditions, yet, the program does not include an explicit call to `panic` like
116 the first example. This is because the
117 panic is embedded in the calls to `unwrap`.
118
119 To “unwrap” something in Rust is to say, “Give me the result of the
120 computation, and if there was an error, just panic and stop the program.”
121 It would be better if we just showed the code for unwrapping because it is so
122 simple, but to do that, we will first need to explore the `Option` and `Result`
123 types. Both of these types have a method called `unwrap` defined on them.
124
125 ### The `Option` type
126
127 The `Option` type is [defined in the standard library][5]:
128
129 ```rust
130 enum Option<T> {
131     None,
132     Some(T),
133 }
134 ```
135
136 The `Option` type is a way to use Rust's type system to express the
137 *possibility of absence*. Encoding the possibility of absence into the type
138 system is an important concept because it will cause the compiler to force the
139 programmer to handle that absence. Let's take a look at an example that tries
140 to find a character in a string:
141
142 <span id="code-option-ex-string-find"></span>
143
144 ```rust
145 // Searches `haystack` for the Unicode character `needle`. If one is found, the
146 // byte offset of the character is returned. Otherwise, `None` is returned.
147 fn find(haystack: &str, needle: char) -> Option<usize> {
148     for (offset, c) in haystack.char_indices() {
149         if c == needle {
150             return Some(offset);
151         }
152     }
153     None
154 }
155 ```
156
157 Notice that when this function finds a matching character, it doesn't just
158 return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or
159 a *value constructor* for the `Option` type. You can think of it as a function
160 with the type `fn<T>(value: T) -> Option<T>`. Correspondingly, `None` is also a
161 value constructor, except it has no arguments. You can think of `None` as a
162 function with the type `fn<T>() -> Option<T>`.
163
164 This might seem like much ado about nothing, but this is only half of the
165 story. The other half is *using* the `find` function we've written. Let's try
166 to use it to find the extension in a file name.
167
168 ```rust
169 # fn find(_: &str, _: char) -> Option<usize> { None }
170 fn main() {
171     let file_name = "foobar.rs";
172     match find(file_name, '.') {
173         None => println!("No file extension found."),
174         Some(i) => println!("File extension: {}", &file_name[i+1..]),
175     }
176 }
177 ```
178
179 This code uses [pattern matching][1] to do *case
180 analysis* on the `Option<usize>` returned by the `find` function. In fact, case
181 analysis is the only way to get at the value stored inside an `Option<T>`. This
182 means that you, as the programmer, must handle the case when an `Option<T>` is
183 `None` instead of `Some(t)`.
184
185 But wait, what about `unwrap`,which we used [`previously`](#code-unwrap-double)?
186 There was no case analysis there! Instead, the case analysis was put inside the
187 `unwrap` method for you. You could define it yourself if you want:
188
189 <span id="code-option-def-unwrap"></span>
190
191 ```rust
192 enum Option<T> {
193     None,
194     Some(T),
195 }
196
197 impl<T> Option<T> {
198     fn unwrap(self) -> T {
199         match self {
200             Option::Some(val) => val,
201             Option::None =>
202               panic!("called `Option::unwrap()` on a `None` value"),
203         }
204     }
205 }
206 ```
207
208 The `unwrap` method *abstracts away the case analysis*. This is precisely the thing
209 that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that
210 `unwrap` is not composable: it is the bull in the china shop.
211
212 ### Composing `Option<T>` values
213
214 In an [example from before](#code-option-ex-string-find),
215 we saw how to use `find` to discover the extension in a file name. Of course,
216 not all file names have a `.` in them, so it's possible that the file name has
217 no extension. This *possibility of absence* is encoded into the types using
218 `Option<T>`. In other words, the compiler will force us to address the
219 possibility that an extension does not exist. In our case, we just print out a
220 message saying as such.
221
222 Getting the extension of a file name is a pretty common operation, so it makes
223 sense to put it into a function:
224
225 ```rust
226 # fn find(_: &str, _: char) -> Option<usize> { None }
227 // Returns the extension of the given file name, where the extension is defined
228 // as all characters proceeding the first `.`.
229 // If `file_name` has no `.`, then `None` is returned.
230 fn extension_explicit(file_name: &str) -> Option<&str> {
231     match find(file_name, '.') {
232         None => None,
233         Some(i) => Some(&file_name[i+1..]),
234     }
235 }
236 ```
237
238 (Pro-tip: don't use this code. Use the
239 [`extension`](../std/path/struct.Path.html#method.extension)
240 method in the standard library instead.)
241
242 The code stays simple, but the important thing to notice is that the type of
243 `find` forces us to consider the possibility of absence. This is a good thing
244 because it means the compiler won't let us accidentally forget about the case
245 where a file name doesn't have an extension. On the other hand, doing explicit
246 case analysis like we've done in `extension_explicit` every time can get a bit
247 tiresome.
248
249 In fact, the case analysis in `extension_explicit` follows a very common
250 pattern: *map* a function on to the value inside of an `Option<T>`, unless the
251 option is `None`, in which case, just return `None`.
252
253 Rust has parametric polymorphism, so it is very easy to define a combinator
254 that abstracts this pattern:
255
256 <span id="code-option-map"></span>
257
258 ```rust
259 fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A {
260     match option {
261         None => None,
262         Some(value) => Some(f(value)),
263     }
264 }
265 ```
266
267 Indeed, `map` is [defined as a method][2] on `Option<T>` in the standard library.
268
269 Armed with our new combinator, we can rewrite our `extension_explicit` method
270 to get rid of the case analysis:
271
272 ```rust
273 # fn find(_: &str, _: char) -> Option<usize> { None }
274 // Returns the extension of the given file name, where the extension is defined
275 // as all characters proceeding the first `.`.
276 // If `file_name` has no `.`, then `None` is returned.
277 fn extension(file_name: &str) -> Option<&str> {
278     find(file_name, '.').map(|i| &file_name[i+1..])
279 }
280 ```
281
282 One other pattern we commonly find is assigning a default value to the case
283 when an `Option` value is `None`. For example, maybe your program assumes that
284 the extension of a file is `rs` even if none is present. As you might imagine,
285 the case analysis for this is not specific to file extensions - it can work
286 with any `Option<T>`:
287
288 ```rust
289 fn unwrap_or<T>(option: Option<T>, default: T) -> T {
290     match option {
291         None => default,
292         Some(value) => value,
293     }
294 }
295 ```
296
297 The trick here is that the default value must have the same type as the value
298 that might be inside the `Option<T>`. Using it is dead simple in our case:
299
300 ```rust
301 # fn find(haystack: &str, needle: char) -> Option<usize> {
302 #     for (offset, c) in haystack.char_indices() {
303 #         if c == needle {
304 #             return Some(offset);
305 #         }
306 #     }
307 #     None
308 # }
309 #
310 # fn extension(file_name: &str) -> Option<&str> {
311 #     find(file_name, '.').map(|i| &file_name[i+1..])
312 # }
313 fn main() {
314     assert_eq!(extension("foobar.csv").unwrap_or("rs"), "csv");
315     assert_eq!(extension("foobar").unwrap_or("rs"), "rs");
316 }
317 ```
318
319 (Note that `unwrap_or` is [defined as a method][3] on `Option<T>` in the
320 standard library, so we use that here instead of the free-standing function we
321 defined above. Don't forget to check out the more general [`unwrap_or_else`][4]
322 method.)
323
324 There is one more combinator that we think is worth paying special attention to:
325 `and_then`. It makes it easy to compose distinct computations that admit the
326 *possibility of absence*. For example, much of the code in this section is
327 about finding an extension given a file name. In order to do this, you first
328 need the file name which is typically extracted from a file *path*. While most
329 file paths have a file name, not *all* of them do. For example, `.`, `..` or
330 `/`.
331
332 So, we are tasked with the challenge of finding an extension given a file
333 *path*. Let's start with explicit case analysis:
334
335 ```rust
336 # fn extension(file_name: &str) -> Option<&str> { None }
337 fn file_path_ext_explicit(file_path: &str) -> Option<&str> {
338     match file_name(file_path) {
339         None => None,
340         Some(name) => match extension(name) {
341             None => None,
342             Some(ext) => Some(ext),
343         }
344     }
345 }
346
347 fn file_name(file_path: &str) -> Option<&str> {
348   // implementation elided
349   unimplemented!()
350 }
351 ```
352
353 You might think that we could just use the `map` combinator to reduce the case
354 analysis, but its type doesn't quite fit. Namely, `map` takes a function that
355 does something only with the inner value. The result of that function is then
356 *always* [rewrapped with `Some`](#code-option-map). Instead, we need something
357 like `map`, but which allows the caller to return another `Option`. Its generic
358 implementation is even simpler than `map`:
359
360 ```rust
361 fn and_then<F, T, A>(option: Option<T>, f: F) -> Option<A>
362         where F: FnOnce(T) -> Option<A> {
363     match option {
364         None => None,
365         Some(value) => f(value),
366     }
367 }
368 ```
369
370 Now we can rewrite our `file_path_ext` function without explicit case analysis:
371
372 ```rust
373 # fn extension(file_name: &str) -> Option<&str> { None }
374 # fn file_name(file_path: &str) -> Option<&str> { None }
375 fn file_path_ext(file_path: &str) -> Option<&str> {
376     file_name(file_path).and_then(extension)
377 }
378 ```
379
380 The `Option` type has many other combinators [defined in the standard
381 library][5]. It is a good idea to skim this list and familiarize
382 yourself with what's available—they can often reduce case analysis
383 for you. Familiarizing yourself with these combinators will pay
384 dividends because many of them are also defined (with similar
385 semantics) for `Result`, which we will talk about next.
386
387 Combinators make using types like `Option` ergonomic because they reduce
388 explicit case analysis. They are also composable because they permit the caller
389 to handle the possibility of absence in their own way. Methods like `unwrap`
390 remove choices because they will panic if `Option<T>` is `None`.
391
392 ## The `Result` type
393
394 The `Result` type is also
395 [defined in the standard library][6]:
396
397 <span id="code-result-def"></span>
398
399 ```rust
400 enum Result<T, E> {
401     Ok(T),
402     Err(E),
403 }
404 ```
405
406 The `Result` type is a richer version of `Option`. Instead of expressing the
407 possibility of *absence* like `Option` does, `Result` expresses the possibility
408 of *error*. Usually, the *error* is used to explain why the execution of some
409 computation failed. This is a strictly more general form of `Option`. Consider
410 the following type alias, which is semantically equivalent to the real
411 `Option<T>` in every way:
412
413 ```rust
414 type Option<T> = Result<T, ()>;
415 ```
416
417 This fixes the second type parameter of `Result` to always be `()` (pronounced
418 “unit” or “empty tuple”). Exactly one value inhabits the `()` type: `()`. (Yup,
419 the type and value level terms have the same notation!)
420
421 The `Result` type is a way of representing one of two possible outcomes in a
422 computation. By convention, one outcome is meant to be expected or “`Ok`” while
423 the other outcome is meant to be unexpected or “`Err`”.
424
425 Just like `Option`, the `Result` type also has an
426 [`unwrap` method
427 defined][7]
428 in the standard library. Let's define it:
429
430 ```rust
431 # enum Result<T, E> { Ok(T), Err(E) }
432 impl<T, E: ::std::fmt::Debug> Result<T, E> {
433     fn unwrap(self) -> T {
434         match self {
435             Result::Ok(val) => val,
436             Result::Err(err) =>
437               panic!("called `Result::unwrap()` on an `Err` value: {:?}", err),
438         }
439     }
440 }
441 ```
442
443 This is effectively the same as our [definition for
444 `Option::unwrap`](#code-option-def-unwrap), except it includes the
445 error value in the `panic!` message. This makes debugging easier, but
446 it also requires us to add a [`Debug`][8] constraint on the `E` type
447 parameter (which represents our error type). Since the vast majority
448 of types should satisfy the `Debug` constraint, this tends to work out
449 in practice. (`Debug` on a type simply means that there's a reasonable
450 way to print a human readable description of values with that type.)
451
452 OK, let's move on to an example.
453
454 ### Parsing integers
455
456 The Rust standard library makes converting strings to integers dead simple.
457 It's so easy in fact, that it is very tempting to write something like the
458 following:
459
460 ```rust
461 fn double_number(number_str: &str) -> i32 {
462     2 * number_str.parse::<i32>().unwrap()
463 }
464
465 fn main() {
466     let n: i32 = double_number("10");
467     assert_eq!(n, 20);
468 }
469 ```
470
471 At this point, you should be skeptical of calling `unwrap`. For example, if
472 the string doesn't parse as a number, you'll get a panic:
473
474 ```text
475 thread '<main>' panicked at 'called `Result::unwrap()` on an `Err` value: ParseIntError { kind: InvalidDigit }', /home/rustbuild/src/rust-buildbot/slave/beta-dist-rustc-linux/build/src/libcore/result.rs:729
476 ```
477
478 This is rather unsightly, and if this happened inside a library you're
479 using, you might be understandably annoyed. Instead, we should try to
480 handle the error in our function and let the caller decide what to
481 do. This means changing the return type of `double_number`. But to
482 what? Well, that requires looking at the signature of the [`parse`
483 method][9] in the standard library:
484
485 ```rust,ignore
486 impl str {
487     fn parse<F: FromStr>(&self) -> Result<F, F::Err>;
488 }
489 ```
490
491 Hmm. So we at least know that we need to use a `Result`. Certainly, it's
492 possible that this could have returned an `Option`. After all, a string either
493 parses as a number or it doesn't, right? That's certainly a reasonable way to
494 go, but the implementation internally distinguishes *why* the string didn't
495 parse as an integer. (Whether it's an empty string, an invalid digit, too big
496 or too small.) Therefore, using a `Result` makes sense because we want to
497 provide more information than simply “absence.” We want to say *why* the
498 parsing failed. You should try to emulate this line of reasoning when faced
499 with a choice between `Option` and `Result`. If you can provide detailed error
500 information, then you probably should. (We'll see more on this later.)
501
502 OK, but how do we write our return type? The `parse` method as defined
503 above is generic over all the different number types defined in the
504 standard library. We could (and probably should) also make our
505 function generic, but let's favor explicitness for the moment. We only
506 care about `i32`, so we need to [find its implementation of
507 `FromStr`](../std/primitive.i32.html) (do a `CTRL-F` in your browser
508 for “FromStr”) and look at its [associated type][10] `Err`. We did
509 this so we can find the concrete error type. In this case, it's
510 [`std::num::ParseIntError`](../std/num/struct.ParseIntError.html).
511 Finally, we can rewrite our function:
512
513 ```rust
514 use std::num::ParseIntError;
515
516 fn double_number(number_str: &str) -> Result<i32, ParseIntError> {
517     match number_str.parse::<i32>() {
518         Ok(n) => Ok(2 * n),
519         Err(err) => Err(err),
520     }
521 }
522
523 fn main() {
524     match double_number("10") {
525         Ok(n) => assert_eq!(n, 20),
526         Err(err) => println!("Error: {:?}", err),
527     }
528 }
529 ```
530
531 This is a little better, but now we've written a lot more code! The case
532 analysis has once again bitten us.
533
534 Combinators to the rescue! Just like `Option`, `Result` has lots of combinators
535 defined as methods. There is a large intersection of common combinators between
536 `Result` and `Option`. In particular, `map` is part of that intersection:
537
538 ```rust
539 use std::num::ParseIntError;
540
541 fn double_number(number_str: &str) -> Result<i32, ParseIntError> {
542     number_str.parse::<i32>().map(|n| 2 * n)
543 }
544
545 fn main() {
546     match double_number("10") {
547         Ok(n) => assert_eq!(n, 20),
548         Err(err) => println!("Error: {:?}", err),
549     }
550 }
551 ```
552
553 The usual suspects are all there for `Result`, including
554 [`unwrap_or`](../std/result/enum.Result.html#method.unwrap_or) and
555 [`and_then`](../std/result/enum.Result.html#method.and_then).
556 Additionally, since `Result` has a second type parameter, there are
557 combinators that affect only the error type, such as
558 [`map_err`](../std/result/enum.Result.html#method.map_err) (instead of
559 `map`) and [`or_else`](../std/result/enum.Result.html#method.or_else)
560 (instead of `and_then`).
561
562 ### The `Result` type alias idiom
563
564 In the standard library, you may frequently see types like
565 `Result<i32>`. But wait, [we defined `Result`](#code-result-def) to
566 have two type parameters. How can we get away with only specifying
567 one? The key is to define a `Result` type alias that *fixes* one of
568 the type parameters to a particular type. Usually the fixed type is
569 the error type. For example, our previous example parsing integers
570 could be rewritten like this:
571
572 ```rust
573 use std::num::ParseIntError;
574 use std::result;
575
576 type Result<T> = result::Result<T, ParseIntError>;
577
578 fn double_number(number_str: &str) -> Result<i32> {
579     unimplemented!();
580 }
581 ```
582
583 Why would we do this? Well, if we have a lot of functions that could return
584 `ParseIntError`, then it's much more convenient to define an alias that always
585 uses `ParseIntError` so that we don't have to write it out all the time.
586
587 The most prominent place this idiom is used in the standard library is
588 with [`io::Result`](../std/io/type.Result.html). Typically, one writes
589 `io::Result<T>`, which makes it clear that you're using the `io`
590 module's type alias instead of the plain definition from
591 `std::result`. (This idiom is also used for
592 [`fmt::Result`](../std/fmt/type.Result.html).)
593
594 ## A brief interlude: unwrapping isn't evil
595
596 If you've been following along, you might have noticed that I've taken a pretty
597 hard line against calling methods like `unwrap` that could `panic` and abort
598 your program. *Generally speaking*, this is good advice.
599
600 However, `unwrap` can still be used judiciously. What exactly justifies use of
601 `unwrap` is somewhat of a grey area and reasonable people can disagree. I'll
602 summarize some of my *opinions* on the matter.
603
604 * **In examples and quick 'n' dirty code.** Sometimes you're writing examples
605   or a quick program, and error handling simply isn't important. Beating the
606   convenience of `unwrap` can be hard in such scenarios, so it is very
607   appealing.
608 * **When panicking indicates a bug in the program.** When the invariants of
609   your code should prevent a certain case from happening (like, say, popping
610   from an empty stack), then panicking can be permissible. This is because it
611   exposes a bug in your program. This can be explicit, like from an `assert!`
612   failing, or it could be because your index into an array was out of bounds.
613
614 This is probably not an exhaustive list. Moreover, when using an
615 `Option`, it is often better to use its
616 [`expect`](../std/option/enum.Option.html#method.expect)
617 method. `expect` does exactly the same thing as `unwrap`, except it
618 prints a message you give to `expect`. This makes the resulting panic
619 a bit nicer to deal with, since it will show your message instead of
620 “called unwrap on a `None` value.”
621
622 My advice boils down to this: use good judgment. There's a reason why the words
623 “never do X” or “Y is considered harmful” don't appear in my writing. There are
624 trade offs to all things, and it is up to you as the programmer to determine
625 what is acceptable for your use cases. My goal is only to help you evaluate
626 trade offs as accurately as possible.
627
628 Now that we've covered the basics of error handling in Rust, and
629 explained unwrapping, let's start exploring more of the standard
630 library.
631
632 # Working with multiple error types
633
634 Thus far, we've looked at error handling where everything was either an
635 `Option<T>` or a `Result<T, SomeError>`. But what happens when you have both an
636 `Option` and a `Result`? Or what if you have a `Result<T, Error1>` and a
637 `Result<T, Error2>`? Handling *composition of distinct error types* is the next
638 challenge in front of us, and it will be the major theme throughout the rest of
639 this chapter.
640
641 ## Composing `Option` and `Result`
642
643 So far, I've talked about combinators defined for `Option` and combinators
644 defined for `Result`. We can use these combinators to compose results of
645 different computations without doing explicit case analysis.
646
647 Of course, in real code, things aren't always as clean. Sometimes you have a
648 mix of `Option` and `Result` types. Must we resort to explicit case analysis,
649 or can we continue using combinators?
650
651 For now, let's revisit one of the first examples in this chapter:
652
653 ```rust,should_panic
654 use std::env;
655
656 fn main() {
657     let mut argv = env::args();
658     let arg: String = argv.nth(1).unwrap(); // error 1
659     let n: i32 = arg.parse().unwrap(); // error 2
660     println!("{}", 2 * n);
661 }
662 ```
663
664 Given our new found knowledge of `Option`, `Result` and their various
665 combinators, we should try to rewrite this so that errors are handled properly
666 and the program doesn't panic if there's an error.
667
668 The tricky aspect here is that `argv.nth(1)` produces an `Option` while
669 `arg.parse()` produces a `Result`. These aren't directly composable. When faced
670 with both an `Option` and a `Result`, the solution is *usually* to convert the
671 `Option` to a `Result`. In our case, the absence of a command line parameter
672 (from `env::args()`) means the user didn't invoke the program correctly. We
673 could just use a `String` to describe the error. Let's try:
674
675 <span id="code-error-double-string"></span>
676
677 ```rust
678 use std::env;
679
680 fn double_arg(mut argv: env::Args) -> Result<i32, String> {
681     argv.nth(1)
682         .ok_or("Please give at least one argument".to_owned())
683         .and_then(|arg| arg.parse::<i32>().map_err(|err| err.to_string()))
684         .map(|n| 2 * n)
685 }
686
687 fn main() {
688     match double_arg(env::args()) {
689         Ok(n) => println!("{}", n),
690         Err(err) => println!("Error: {}", err),
691     }
692 }
693 ```
694
695 There are a couple new things in this example. The first is the use of the
696 [`Option::ok_or`](../std/option/enum.Option.html#method.ok_or)
697 combinator. This is one way to convert an `Option` into a `Result`. The
698 conversion requires you to specify what error to use if `Option` is `None`.
699 Like the other combinators we've seen, its definition is very simple:
700
701 ```rust
702 fn ok_or<T, E>(option: Option<T>, err: E) -> Result<T, E> {
703     match option {
704         Some(val) => Ok(val),
705         None => Err(err),
706     }
707 }
708 ```
709
710 The other new combinator used here is
711 [`Result::map_err`](../std/result/enum.Result.html#method.map_err).
712 This is just like `Result::map`, except it maps a function on to the *error*
713 portion of a `Result` value. If the `Result` is an `Ok(...)` value, then it is
714 returned unmodified.
715
716 We use `map_err` here because it is necessary for the error types to remain
717 the same (because of our use of `and_then`). Since we chose to convert the
718 `Option<String>` (from `argv.nth(1)`) to a `Result<String, String>`, we must
719 also convert the `ParseIntError` from `arg.parse()` to a `String`.
720
721 ## The limits of combinators
722
723 Doing IO and parsing input is a very common task, and it's one that I
724 personally have done a lot of in Rust. Therefore, we will use (and continue to
725 use) IO and various parsing routines to exemplify error handling.
726
727 Let's start simple. We are tasked with opening a file, reading all of its
728 contents and converting its contents to a number. Then we multiply it by `2`
729 and print the output.
730
731 Although I've tried to convince you not to use `unwrap`, it can be useful
732 to first write your code using `unwrap`. It allows you to focus on your problem
733 instead of the error handling, and it exposes the points where proper error
734 handling need to occur. Let's start there so we can get a handle on the code,
735 and then refactor it to use better error handling.
736
737 ```rust,should_panic
738 use std::fs::File;
739 use std::io::Read;
740 use std::path::Path;
741
742 fn file_double<P: AsRef<Path>>(file_path: P) -> i32 {
743     let mut file = File::open(file_path).unwrap(); // error 1
744     let mut contents = String::new();
745     file.read_to_string(&mut contents).unwrap(); // error 2
746     let n: i32 = contents.trim().parse().unwrap(); // error 3
747     2 * n
748 }
749
750 fn main() {
751     let doubled = file_double("foobar");
752     println!("{}", doubled);
753 }
754 ```
755
756 (N.B. The `AsRef<Path>` is used because those are the
757 [same bounds used on
758 `std::fs::File::open`](../std/fs/struct.File.html#method.open).
759 This makes it ergonomic to use any kind of string as a file path.)
760
761 There are three different errors that can occur here:
762
763 1. A problem opening the file.
764 2. A problem reading data from the file.
765 3. A problem parsing the data as a number.
766
767 The first two problems are described via the
768 [`std::io::Error`](../std/io/struct.Error.html) type. We know this
769 because of the return types of
770 [`std::fs::File::open`](../std/fs/struct.File.html#method.open) and
771 [`std::io::Read::read_to_string`](../std/io/trait.Read.html#method.read_to_string).
772 (Note that they both use the [`Result` type alias
773 idiom](#the-result-type-alias-idiom) described previously. If you
774 click on the `Result` type, you'll [see the type
775 alias](../std/io/type.Result.html), and consequently, the underlying
776 `io::Error` type.)  The third problem is described by the
777 [`std::num::ParseIntError`](../std/num/struct.ParseIntError.html)
778 type. The `io::Error` type in particular is *pervasive* throughout the
779 standard library. You will see it again and again.
780
781 Let's start the process of refactoring the `file_double` function. To make this
782 function composable with other components of the program, it should *not* panic
783 if any of the above error conditions are met. Effectively, this means that the
784 function should *return an error* if any of its operations fail. Our problem is
785 that the return type of `file_double` is `i32`, which does not give us any
786 useful way of reporting an error. Thus, we must start by changing the return
787 type from `i32` to something else.
788
789 The first thing we need to decide: should we use `Option` or `Result`? We
790 certainly could use `Option` very easily. If any of the three errors occur, we
791 could simply return `None`. This will work *and it is better than panicking*,
792 but we can do a lot better. Instead, we should pass some detail about the error
793 that occurred. Since we want to express the *possibility of error*, we should
794 use `Result<i32, E>`. But what should `E` be? Since two *different* types of
795 errors can occur, we need to convert them to a common type. One such type is
796 `String`. Let's see how that impacts our code:
797
798 ```rust
799 use std::fs::File;
800 use std::io::Read;
801 use std::path::Path;
802
803 fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
804     File::open(file_path)
805          .map_err(|err| err.to_string())
806          .and_then(|mut file| {
807               let mut contents = String::new();
808               file.read_to_string(&mut contents)
809                   .map_err(|err| err.to_string())
810                   .map(|_| contents)
811          })
812          .and_then(|contents| {
813               contents.trim().parse::<i32>()
814                       .map_err(|err| err.to_string())
815          })
816          .map(|n| 2 * n)
817 }
818
819 fn main() {
820     match file_double("foobar") {
821         Ok(n) => println!("{}", n),
822         Err(err) => println!("Error: {}", err),
823     }
824 }
825 ```
826
827 This code looks a bit hairy. It can take quite a bit of practice before code
828 like this becomes easy to write. The way we write it is by *following the
829 types*. As soon as we changed the return type of `file_double` to
830 `Result<i32, String>`, we had to start looking for the right combinators. In
831 this case, we only used three different combinators: `and_then`, `map` and
832 `map_err`.
833
834 `and_then` is used to chain multiple computations where each computation could
835 return an error. After opening the file, there are two more computations that
836 could fail: reading from the file and parsing the contents as a number.
837 Correspondingly, there are two calls to `and_then`.
838
839 `map` is used to apply a function to the `Ok(...)` value of a `Result`. For
840 example, the very last call to `map` multiplies the `Ok(...)` value (which is
841 an `i32`) by `2`. If an error had occurred before that point, this operation
842 would have been skipped because of how `map` is defined.
843
844 `map_err` is the trick that makes all of this work. `map_err` is just like
845 `map`, except it applies a function to the `Err(...)` value of a `Result`. In
846 this case, we want to convert all of our errors to one type: `String`. Since
847 both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the
848 `to_string()` method to convert them.
849
850 With all of that said, the code is still hairy. Mastering use of combinators is
851 important, but they have their limits. Let's try a different approach: early
852 returns.
853
854 ## Early returns
855
856 I'd like to take the code from the previous section and rewrite it using *early
857 returns*. Early returns let you exit the function early. We can't return early
858 in `file_double` from inside another closure, so we'll need to revert back to
859 explicit case analysis.
860
861 ```rust
862 use std::fs::File;
863 use std::io::Read;
864 use std::path::Path;
865
866 fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
867     let mut file = match File::open(file_path) {
868         Ok(file) => file,
869         Err(err) => return Err(err.to_string()),
870     };
871     let mut contents = String::new();
872     if let Err(err) = file.read_to_string(&mut contents) {
873         return Err(err.to_string());
874     }
875     let n: i32 = match contents.trim().parse() {
876         Ok(n) => n,
877         Err(err) => return Err(err.to_string()),
878     };
879     Ok(2 * n)
880 }
881
882 fn main() {
883     match file_double("foobar") {
884         Ok(n) => println!("{}", n),
885         Err(err) => println!("Error: {}", err),
886     }
887 }
888 ```
889
890 Reasonable people can disagree over whether this code is better that the code
891 that uses combinators, but if you aren't familiar with the combinator approach,
892 this code looks simpler to read to me. It uses explicit case analysis with
893 `match` and `if let`. If an error occurs, it simply stops executing the
894 function and returns the error (by converting it to a string).
895
896 Isn't this a step backwards though? Previously, we said that the key to
897 ergonomic error handling is reducing explicit case analysis, yet we've reverted
898 back to explicit case analysis here. It turns out, there are *multiple* ways to
899 reduce explicit case analysis. Combinators aren't the only way.
900
901 ## The `try!` macro
902
903 A cornerstone of error handling in Rust is the `try!` macro. The `try!` macro
904 abstracts case analysis just like combinators, but unlike combinators, it also
905 abstracts *control flow*. Namely, it can abstract the *early return* pattern
906 seen above.
907
908 Here is a simplified definition of a `try!` macro:
909
910 <span id="code-try-def-simple"></span>
911
912 ```rust
913 macro_rules! try {
914     ($e:expr) => (match $e {
915         Ok(val) => val,
916         Err(err) => return Err(err),
917     });
918 }
919 ```
920
921 (The [real definition](../std/macro.try!.html) is a bit more
922 sophisticated. We will address that later.)
923
924 Using the `try!` macro makes it very easy to simplify our last example. Since
925 it does the case analysis and the early return for us, we get tighter code that
926 is easier to read:
927
928 ```rust
929 use std::fs::File;
930 use std::io::Read;
931 use std::path::Path;
932
933 fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
934     let mut file = try!(File::open(file_path).map_err(|e| e.to_string()));
935     let mut contents = String::new();
936     try!(file.read_to_string(&mut contents).map_err(|e| e.to_string()));
937     let n = try!(contents.trim().parse::<i32>().map_err(|e| e.to_string()));
938     Ok(2 * n)
939 }
940
941 fn main() {
942     match file_double("foobar") {
943         Ok(n) => println!("{}", n),
944         Err(err) => println!("Error: {}", err),
945     }
946 }
947 ```
948
949 The `map_err` calls are still necessary given
950 [our definition of `try!`](#code-try-def-simple).
951 This is because the error types still need to be converted to `String`.
952 The good news is that we will soon learn how to remove those `map_err` calls!
953 The bad news is that we will need to learn a bit more about a couple important
954 traits in the standard library before we can remove the `map_err` calls.
955
956 ## Defining your own error type
957
958 Before we dive into some of the standard library error traits, I'd like to wrap
959 up this section by removing the use of `String` as our error type in the
960 previous examples.
961
962 Using `String` as we did in our previous examples is convenient because it's
963 easy to convert errors to strings, or even make up your own errors as strings
964 on the spot. However, using `String` for your errors has some downsides.
965
966 The first downside is that the error messages tend to clutter your
967 code. It's possible to define the error messages elsewhere, but unless
968 you're unusually disciplined, it is very tempting to embed the error
969 message into your code. Indeed, we did exactly this in a [previous
970 example](#code-error-double-string).
971
972 The second and more important downside is that `String`s are *lossy*. That is,
973 if all errors are converted to strings, then the errors we pass to the caller
974 become completely opaque. The only reasonable thing the caller can do with a
975 `String` error is show it to the user. Certainly, inspecting the string to
976 determine the type of error is not robust. (Admittedly, this downside is far
977 more important inside of a library as opposed to, say, an application.)
978
979 For example, the `io::Error` type embeds an
980 [`io::ErrorKind`](../std/io/enum.ErrorKind.html),
981 which is *structured data* that represents what went wrong during an IO
982 operation. This is important because you might want to react differently
983 depending on the error. (e.g., A `BrokenPipe` error might mean quitting your
984 program gracefully while a `NotFound` error might mean exiting with an error
985 code and showing an error to the user.) With `io::ErrorKind`, the caller can
986 examine the type of an error with case analysis, which is strictly superior
987 to trying to tease out the details of an error inside of a `String`.
988
989 Instead of using a `String` as an error type in our previous example of reading
990 an integer from a file, we can define our own error type that represents errors
991 with *structured data*. We endeavor to not drop information from underlying
992 errors in case the caller wants to inspect the details.
993
994 The ideal way to represent *one of many possibilities* is to define our own
995 sum type using `enum`. In our case, an error is either an `io::Error` or a
996 `num::ParseIntError`, so a natural definition arises:
997
998 ```rust
999 use std::io;
1000 use std::num;
1001
1002 // We derive `Debug` because all types should probably derive `Debug`.
1003 // This gives us a reasonable human readable description of `CliError` values.
1004 #[derive(Debug)]
1005 enum CliError {
1006     Io(io::Error),
1007     Parse(num::ParseIntError),
1008 }
1009 ```
1010
1011 Tweaking our code is very easy. Instead of converting errors to strings, we
1012 simply convert them to our `CliError` type using the corresponding value
1013 constructor:
1014
1015 ```rust
1016 # #[derive(Debug)]
1017 # enum CliError { Io(::std::io::Error), Parse(::std::num::ParseIntError) }
1018 use std::fs::File;
1019 use std::io::Read;
1020 use std::path::Path;
1021
1022 fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> {
1023     let mut file = try!(File::open(file_path).map_err(CliError::Io));
1024     let mut contents = String::new();
1025     try!(file.read_to_string(&mut contents).map_err(CliError::Io));
1026     let n: i32 = try!(contents.trim().parse().map_err(CliError::Parse));
1027     Ok(2 * n)
1028 }
1029
1030 fn main() {
1031     match file_double("foobar") {
1032         Ok(n) => println!("{}", n),
1033         Err(err) => println!("Error: {:?}", err),
1034     }
1035 }
1036 ```
1037
1038 The only change here is switching `map_err(|e| e.to_string())` (which converts
1039 errors to strings) to `map_err(CliError::Io)` or `map_err(CliError::Parse)`.
1040 The *caller* gets to decide the level of detail to report to the user. In
1041 effect, using a `String` as an error type removes choices from the caller while
1042 using a custom `enum` error type like `CliError` gives the caller all of the
1043 conveniences as before in addition to *structured data* describing the error.
1044
1045 A rule of thumb is to define your own error type, but a `String` error type
1046 will do in a pinch, particularly if you're writing an application. If you're
1047 writing a library, defining your own error type should be strongly preferred so
1048 that you don't remove choices from the caller unnecessarily.
1049
1050 # Standard library traits used for error handling
1051
1052 The standard library defines two integral traits for error handling:
1053 [`std::error::Error`](../std/error/trait.Error.html) and
1054 [`std::convert::From`](../std/convert/trait.From.html). While `Error`
1055 is designed specifically for generically describing errors, the `From`
1056 trait serves a more general role for converting values between two
1057 distinct types.
1058
1059 ## The `Error` trait
1060
1061 The `Error` trait is [defined in the standard
1062 library](../std/error/trait.Error.html):
1063
1064 ```rust
1065 use std::fmt::{Debug, Display};
1066
1067 trait Error: Debug + Display {
1068   /// A short description of the error.
1069   fn description(&self) -> &str;
1070
1071   /// The lower level cause of this error, if any.
1072   fn cause(&self) -> Option<&Error> { None }
1073 }
1074 ```
1075
1076 This trait is super generic because it is meant to be implemented for *all*
1077 types that represent errors. This will prove useful for writing composable code
1078 as we'll see later. Otherwise, the trait allows you to do at least the
1079 following things:
1080
1081 * Obtain a `Debug` representation of the error.
1082 * Obtain a user-facing `Display` representation of the error.
1083 * Obtain a short description of the error (via the `description` method).
1084 * Inspect the causal chain of an error, if one exists (via the `cause` method).
1085
1086 The first two are a result of `Error` requiring impls for both `Debug` and
1087 `Display`. The latter two are from the two methods defined on `Error`. The
1088 power of `Error` comes from the fact that all error types impl `Error`, which
1089 means errors can be existentially quantified as a
1090 [trait object](../book/trait-objects.html).
1091 This manifests as either `Box<Error>` or `&Error`. Indeed, the `cause` method
1092 returns an `&Error`, which is itself a trait object. We'll revisit the
1093 `Error` trait's utility as a trait object later.
1094
1095 For now, it suffices to show an example implementing the `Error` trait. Let's
1096 use the error type we defined in the
1097 [previous section](#defining-your-own-error-type):
1098
1099 ```rust
1100 use std::io;
1101 use std::num;
1102
1103 // We derive `Debug` because all types should probably derive `Debug`.
1104 // This gives us a reasonable human readable description of `CliError` values.
1105 #[derive(Debug)]
1106 enum CliError {
1107     Io(io::Error),
1108     Parse(num::ParseIntError),
1109 }
1110 ```
1111
1112 This particular error type represents the possibility of two types of errors
1113 occurring: an error dealing with I/O or an error converting a string to a
1114 number. The error could represent as many error types as you want by adding new
1115 variants to the `enum` definition.
1116
1117 Implementing `Error` is pretty straight-forward. It's mostly going to be a lot
1118 explicit case analysis.
1119
1120 ```rust,ignore
1121 use std::error;
1122 use std::fmt;
1123
1124 impl fmt::Display for CliError {
1125     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1126         match *self {
1127             // Both underlying errors already impl `Display`, so we defer to
1128             // their implementations.
1129             CliError::Io(ref err) => write!(f, "IO error: {}", err),
1130             CliError::Parse(ref err) => write!(f, "Parse error: {}", err),
1131         }
1132     }
1133 }
1134
1135 impl error::Error for CliError {
1136     fn description(&self) -> &str {
1137         // Both underlying errors already impl `Error`, so we defer to their
1138         // implementations.
1139         match *self {
1140             CliError::Io(ref err) => err.description(),
1141             CliError::Parse(ref err) => err.description(),
1142         }
1143     }
1144
1145     fn cause(&self) -> Option<&error::Error> {
1146         match *self {
1147             // N.B. Both of these implicitly cast `err` from their concrete
1148             // types (either `&io::Error` or `&num::ParseIntError`)
1149             // to a trait object `&Error`. This works because both error types
1150             // implement `Error`.
1151             CliError::Io(ref err) => Some(err),
1152             CliError::Parse(ref err) => Some(err),
1153         }
1154     }
1155 }
1156 ```
1157
1158 We note that this is a very typical implementation of `Error`: match on your
1159 different error types and satisfy the contracts defined for `description` and
1160 `cause`.
1161
1162 ## The `From` trait
1163
1164 The `std::convert::From` trait is
1165 [defined in the standard
1166 library](../std/convert/trait.From.html):
1167
1168 <span id="code-from-def"></span>
1169
1170 ```rust
1171 trait From<T> {
1172     fn from(T) -> Self;
1173 }
1174 ```
1175
1176 Deliciously simple, yes? `From` is very useful because it gives us a generic
1177 way to talk about conversion *from* a particular type `T` to some other type
1178 (in this case, “some other type” is the subject of the impl, or `Self`).
1179 The crux of `From` is the
1180 [set of implementations provided by the standard
1181 library](../std/convert/trait.From.html).
1182
1183 Here are a few simple examples demonstrating how `From` works:
1184
1185 ```rust
1186 let string: String = From::from("foo");
1187 let bytes: Vec<u8> = From::from("foo");
1188 let cow: ::std::borrow::Cow<str> = From::from("foo");
1189 ```
1190
1191 OK, so `From` is useful for converting between strings. But what about errors?
1192 It turns out, there is one critical impl:
1193
1194 ```rust,ignore
1195 impl<'a, E: Error + 'a> From<E> for Box<Error + 'a>
1196 ```
1197
1198 This impl says that for *any* type that impls `Error`, we can convert it to a
1199 trait object `Box<Error>`. This may not seem terribly surprising, but it is
1200 useful in a generic context.
1201
1202 Remember the two errors we were dealing with previously? Specifically,
1203 `io::Error` and `num::ParseIntError`. Since both impl `Error`, they work with
1204 `From`:
1205
1206 ```rust
1207 use std::error::Error;
1208 use std::fs;
1209 use std::io;
1210 use std::num;
1211
1212 // We have to jump through some hoops to actually get error values.
1213 let io_err: io::Error = io::Error::last_os_error();
1214 let parse_err: num::ParseIntError = "not a number".parse::<i32>().unwrap_err();
1215
1216 // OK, here are the conversions.
1217 let err1: Box<Error> = From::from(io_err);
1218 let err2: Box<Error> = From::from(parse_err);
1219 ```
1220
1221 There is a really important pattern to recognize here. Both `err1` and `err2`
1222 have the *same type*. This is because they are existentially quantified types,
1223 or trait objects. In particular, their underlying type is *erased* from the
1224 compiler's knowledge, so it truly sees `err1` and `err2` as exactly the same.
1225 Additionally, we constructed `err1` and `err2` using precisely the same
1226 function call: `From::from`. This is because `From::from` is overloaded on both
1227 its argument and its return type.
1228
1229 This pattern is important because it solves a problem we had earlier: it gives
1230 us a way to reliably convert errors to the same type using the same function.
1231
1232 Time to revisit an old friend; the `try!` macro.
1233
1234 ## The real `try!` macro
1235
1236 Previously, we presented this definition of `try!`:
1237
1238 ```rust
1239 macro_rules! try {
1240     ($e:expr) => (match $e {
1241         Ok(val) => val,
1242         Err(err) => return Err(err),
1243     });
1244 }
1245 ```
1246
1247 This is not its real definition. Its real definition is
1248 [in the standard library](../std/macro.try!.html):
1249
1250 <span id="code-try-def"></span>
1251
1252 ```rust
1253 macro_rules! try {
1254     ($e:expr) => (match $e {
1255         Ok(val) => val,
1256         Err(err) => return Err(::std::convert::From::from(err)),
1257     });
1258 }
1259 ```
1260
1261 There's one tiny but powerful change: the error value is passed through
1262 `From::from`. This makes the `try!` macro a lot more powerful because it gives
1263 you automatic type conversion for free.
1264
1265 Armed with our more powerful `try!` macro, let's take a look at code we wrote
1266 previously to read a file and convert its contents to an integer:
1267
1268 ```rust
1269 use std::fs::File;
1270 use std::io::Read;
1271 use std::path::Path;
1272
1273 fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
1274     let mut file = try!(File::open(file_path).map_err(|e| e.to_string()));
1275     let mut contents = String::new();
1276     try!(file.read_to_string(&mut contents).map_err(|e| e.to_string()));
1277     let n = try!(contents.trim().parse::<i32>().map_err(|e| e.to_string()));
1278     Ok(2 * n)
1279 }
1280 ```
1281
1282 Earlier, we promised that we could get rid of the `map_err` calls. Indeed, all
1283 we have to do is pick a type that `From` works with. As we saw in the previous
1284 section, `From` has an impl that lets it convert any error type into a
1285 `Box<Error>`:
1286
1287 ```rust
1288 use std::error::Error;
1289 use std::fs::File;
1290 use std::io::Read;
1291 use std::path::Path;
1292
1293 fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, Box<Error>> {
1294     let mut file = try!(File::open(file_path));
1295     let mut contents = String::new();
1296     try!(file.read_to_string(&mut contents));
1297     let n = try!(contents.trim().parse::<i32>());
1298     Ok(2 * n)
1299 }
1300 ```
1301
1302 We are getting very close to ideal error handling. Our code has very little
1303 overhead as a result from error handling because the `try!` macro encapsulates
1304 three things simultaneously:
1305
1306 1. Case analysis.
1307 2. Control flow.
1308 3. Error type conversion.
1309
1310 When all three things are combined, we get code that is unencumbered by
1311 combinators, calls to `unwrap` or case analysis.
1312
1313 There's one little nit left: the `Box<Error>` type is *opaque*. If we
1314 return a `Box<Error>` to the caller, the caller can't (easily) inspect
1315 underlying error type. The situation is certainly better than `String`
1316 because the caller can call methods like
1317 [`description`](../std/error/trait.Error.html#tymethod.description)
1318 and [`cause`](../std/error/trait.Error.html#method.cause), but the
1319 limitation remains: `Box<Error>` is opaque. (N.B. This isn't entirely
1320 true because Rust does have runtime reflection, which is useful in
1321 some scenarios that are [beyond the scope of this
1322 chapter](https://crates.io/crates/error).)
1323
1324 It's time to revisit our custom `CliError` type and tie everything together.
1325
1326 ## Composing custom error types
1327
1328 In the last section, we looked at the real `try!` macro and how it does
1329 automatic type conversion for us by calling `From::from` on the error value.
1330 In particular, we converted errors to `Box<Error>`, which works, but the type
1331 is opaque to callers.
1332
1333 To fix this, we use the same remedy that we're already familiar with: a custom
1334 error type. Once again, here is the code that reads the contents of a file and
1335 converts it to an integer:
1336
1337 ```rust
1338 use std::fs::File;
1339 use std::io::{self, Read};
1340 use std::num;
1341 use std::path::Path;
1342
1343 // We derive `Debug` because all types should probably derive `Debug`.
1344 // This gives us a reasonable human readable description of `CliError` values.
1345 #[derive(Debug)]
1346 enum CliError {
1347     Io(io::Error),
1348     Parse(num::ParseIntError),
1349 }
1350
1351 fn file_double_verbose<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> {
1352     let mut file = try!(File::open(file_path).map_err(CliError::Io));
1353     let mut contents = String::new();
1354     try!(file.read_to_string(&mut contents).map_err(CliError::Io));
1355     let n: i32 = try!(contents.trim().parse().map_err(CliError::Parse));
1356     Ok(2 * n)
1357 }
1358 ```
1359
1360 Notice that we still have the calls to `map_err`. Why? Well, recall the
1361 definitions of [`try!`](#code-try-def) and [`From`](#code-from-def). The
1362 problem is that there is no `From` impl that allows us to convert from error
1363 types like `io::Error` and `num::ParseIntError` to our own custom `CliError`.
1364 Of course, it is easy to fix this! Since we defined `CliError`, we can impl
1365 `From` with it:
1366
1367 ```rust
1368 # #[derive(Debug)]
1369 # enum CliError { Io(io::Error), Parse(num::ParseIntError) }
1370 use std::io;
1371 use std::num;
1372
1373 impl From<io::Error> for CliError {
1374     fn from(err: io::Error) -> CliError {
1375         CliError::Io(err)
1376     }
1377 }
1378
1379 impl From<num::ParseIntError> for CliError {
1380     fn from(err: num::ParseIntError) -> CliError {
1381         CliError::Parse(err)
1382     }
1383 }
1384 ```
1385
1386 All these impls are doing is teaching `From` how to create a `CliError` from
1387 other error types. In our case, construction is as simple as invoking the
1388 corresponding value constructor. Indeed, it is *typically* this easy.
1389
1390 We can finally rewrite `file_double`:
1391
1392 ```rust
1393 # use std::io;
1394 # use std::num;
1395 # enum CliError { Io(::std::io::Error), Parse(::std::num::ParseIntError) }
1396 # impl From<io::Error> for CliError {
1397 #     fn from(err: io::Error) -> CliError { CliError::Io(err) }
1398 # }
1399 # impl From<num::ParseIntError> for CliError {
1400 #     fn from(err: num::ParseIntError) -> CliError { CliError::Parse(err) }
1401 # }
1402
1403 use std::fs::File;
1404 use std::io::Read;
1405 use std::path::Path;
1406
1407 fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, CliError> {
1408     let mut file = try!(File::open(file_path));
1409     let mut contents = String::new();
1410     try!(file.read_to_string(&mut contents));
1411     let n: i32 = try!(contents.trim().parse());
1412     Ok(2 * n)
1413 }
1414 ```
1415
1416 The only thing we did here was remove the calls to `map_err`. They are no
1417 longer needed because the `try!` macro invokes `From::from` on the error value.
1418 This works because we've provided `From` impls for all the error types that
1419 could appear.
1420
1421 If we modified our `file_double` function to perform some other operation, say,
1422 convert a string to a float, then we'd need to add a new variant to our error
1423 type:
1424
1425 ```rust
1426 use std::io;
1427 use std::num;
1428
1429 enum CliError {
1430     Io(io::Error),
1431     ParseInt(num::ParseIntError),
1432     ParseFloat(num::ParseFloatError),
1433 }
1434 ```
1435
1436 And add a new `From` impl:
1437
1438 ```rust
1439 # enum CliError {
1440 #     Io(::std::io::Error),
1441 #     ParseInt(num::ParseIntError),
1442 #     ParseFloat(num::ParseFloatError),
1443 # }
1444
1445 use std::num;
1446
1447 impl From<num::ParseFloatError> for CliError {
1448     fn from(err: num::ParseFloatError) -> CliError {
1449         CliError::ParseFloat(err)
1450     }
1451 }
1452 ```
1453
1454 And that's it!
1455
1456 ## Advice for library writers
1457
1458 If your library needs to report custom errors, then you should
1459 probably define your own error type. It's up to you whether or not to
1460 expose its representation (like
1461 [`ErrorKind`](../std/io/enum.ErrorKind.html)) or keep it hidden (like
1462 [`ParseIntError`](../std/num/struct.ParseIntError.html)). Regardless
1463 of how you do it, it's usually good practice to at least provide some
1464 information about the error beyond just its `String`
1465 representation. But certainly, this will vary depending on use cases.
1466
1467 At a minimum, you should probably implement the
1468 [`Error`](../std/error/trait.Error.html)
1469 trait. This will give users of your library some minimum flexibility for
1470 [composing errors](#the-real-try-macro). Implementing the `Error` trait also
1471 means that users are guaranteed the ability to obtain a string representation
1472 of an error (because it requires impls for both `fmt::Debug` and
1473 `fmt::Display`).
1474
1475 Beyond that, it can also be useful to provide implementations of `From` on your
1476 error types. This allows you (the library author) and your users to
1477 [compose more detailed errors](#composing-custom-error-types). For example,
1478 [`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html)
1479 provides `From` impls for both `io::Error` and `byteorder::Error`.
1480
1481 Finally, depending on your tastes, you may also want to define a
1482 [`Result` type alias](#the-result-type-alias-idiom), particularly if your
1483 library defines a single error type. This is used in the standard library
1484 for [`io::Result`](../std/io/type.Result.html)
1485 and [`fmt::Result`](../std/fmt/type.Result.html).
1486
1487 # Case study: A program to read population data
1488
1489 This chapter was long, and depending on your background, it might be
1490 rather dense. While there is plenty of example code to go along with
1491 the prose, most of it was specifically designed to be pedagogical. So,
1492 we're going to do something new: a case study.
1493
1494 For this, we're going to build up a command line program that lets you
1495 query world population data. The objective is simple: you give it a location
1496 and it will tell you the population. Despite the simplicity, there is a lot
1497 that can go wrong!
1498
1499 The data we'll be using comes from the [Data Science
1500 Toolkit][11]. I've prepared some data from it for this exercise. You
1501 can either grab the [world population data][12] (41MB gzip compressed,
1502 145MB uncompressed) or just the [US population data][13] (2.2MB gzip
1503 compressed, 7.2MB uncompressed).
1504
1505 Up until now, we've kept the code limited to Rust's standard library. For a real
1506 task like this though, we'll want to at least use something to parse CSV data,
1507 parse the program arguments and decode that stuff into Rust types automatically. For that, we'll use the
1508 [`csv`](https://crates.io/crates/csv),
1509 and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
1510
1511 ## Initial setup
1512
1513 We're not going to spend a lot of time on setting up a project with
1514 Cargo because it is already covered well in [the Cargo
1515 chapter](../book/hello-cargo.html) and [Cargo's documentation][14].
1516
1517 To get started from scratch, run `cargo new --bin city-pop` and make sure your
1518 `Cargo.toml` looks something like this:
1519
1520 ```text
1521 [package]
1522 name = "city-pop"
1523 version = "0.1.0"
1524 authors = ["Andrew Gallant <jamslam@gmail.com>"]
1525
1526 [[bin]]
1527 name = "city-pop"
1528
1529 [dependencies]
1530 csv = "0.*"
1531 rustc-serialize = "0.*"
1532 getopts = "0.*"
1533 ```
1534
1535 You should already be able to run:
1536
1537 ```text
1538 cargo build --release
1539 ./target/release/city-pop
1540 # Outputs: Hello, world!
1541 ```
1542
1543 ## Argument parsing
1544
1545 Let's get argument parsing out of the way. We won't go into too much
1546 detail on Getopts, but there is [some good documentation][15]
1547 describing it. The short story is that Getopts generates an argument
1548 parser and a help message from a vector of options (The fact that it
1549 is a vector is hidden behind a struct and a set of methods). Once the
1550 parsing is done, we can decode the program arguments into a Rust
1551 struct. From there, we can get information about the flags, for
1552 instance, whether they were passed in, and what arguments they
1553 had. Here's our program with the appropriate `extern crate`
1554 statements, and the basic argument setup for Getopts:
1555
1556 ```rust,ignore
1557 extern crate getopts;
1558 extern crate rustc_serialize;
1559
1560 use getopts::Options;
1561 use std::env;
1562
1563 fn print_usage(program: &str, opts: Options) {
1564     println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program)));
1565 }
1566
1567 fn main() {
1568     let args: Vec<String> = env::args().collect();
1569     let program = args[0].clone();
1570
1571     let mut opts = Options::new();
1572     opts.optflag("h", "help", "Show this usage message.");
1573
1574     let matches = match opts.parse(&args[1..]) {
1575         Ok(m)  => { m }
1576         Err(e) => { panic!(e.to_string()) }
1577     };
1578     if matches.opt_present("h") {
1579         print_usage(&program, opts);
1580         return;
1581     }
1582     let data_path = args[1].clone();
1583     let city = args[2].clone();
1584
1585         // Do stuff with information
1586 }
1587 ```
1588
1589 First, we get a vector of the arguments passed into our program. We
1590 then store the first one, knowing that it is our program's name. Once
1591 that's done, we set up our argument flags, in this case a simplistic
1592 help message flag. Once we have the argument flags set up, we use
1593 `Options.parse` to parse the argument vector (starting from index one,
1594 because index 0 is the program name). If this was successful, we
1595 assign matches to the parsed object, if not, we panic. Once past that,
1596 we test if the user passed in the help flag, and if so print the usage
1597 message. The option help messages are constructed by Getopts, so all
1598 we have to do to print the usage message is tell it what we want it to
1599 print for the program name and template. If the user has not passed in
1600 the help flag, we assign the proper variables to their corresponding
1601 arguments.
1602
1603 ## Writing the logic
1604
1605 We all write code differently, but error handling is usually the last thing we
1606 want to think about. This isn't great for the overall design of a program, but
1607 it can be useful for rapid prototyping. Because Rust forces us to be explicit
1608 about error handling (by making us call `unwrap`), it is easy to see which
1609 parts of our program can cause errors.
1610
1611 In this case study, the logic is really simple. All we need to do is parse the
1612 CSV data given to us and print out a field in matching rows. Let's do it. (Make
1613 sure to add `extern crate csv;` to the top of your file.)
1614
1615 ```rust,ignore
1616 // This struct represents the data in each row of the CSV file.
1617 // Type based decoding absolves us of a lot of the nitty gritty error
1618 // handling, like parsing strings as integers or floats.
1619 #[derive(Debug, RustcDecodable)]
1620 struct Row {
1621     country: String,
1622     city: String,
1623     accent_city: String,
1624     region: String,
1625
1626     // Not every row has data for the population, latitude or longitude!
1627     // So we express them as `Option` types, which admits the possibility of
1628     // absence. The CSV parser will fill in the correct value for us.
1629     population: Option<u64>,
1630     latitude: Option<f64>,
1631     longitude: Option<f64>,
1632 }
1633
1634 fn print_usage(program: &str, opts: Options) {
1635     println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program)));
1636 }
1637
1638 fn main() {
1639     let args: Vec<String> = env::args().collect();
1640     let program = args[0].clone();
1641
1642     let mut opts = Options::new();
1643     opts.optflag("h", "help", "Show this usage message.");
1644
1645     let matches = match opts.parse(&args[1..]) {
1646         Ok(m)  => { m }
1647         Err(e) => { panic!(e.to_string()) }
1648     };
1649
1650     if matches.opt_present("h") {
1651         print_usage(&program, opts);
1652                 return;
1653         }
1654
1655         let data_file = args[1].clone();
1656         let data_path = Path::new(&data_file);
1657         let city = args[2].clone();
1658
1659         let file = fs::File::open(data_path).unwrap();
1660         let mut rdr = csv::Reader::from_reader(file);
1661
1662         for row in rdr.decode::<Row>() {
1663                 let row = row.unwrap();
1664
1665                 if row.city == city {
1666                         println!("{}, {}: {:?}",
1667                                 row.city, row.country,
1668                                 row.population.expect("population count"));
1669                 }
1670         }
1671 }
1672 ```
1673
1674 Let's outline the errors. We can start with the obvious: the three places that
1675 `unwrap` is called:
1676
1677 1. [`fs::File::open`](../std/fs/struct.File.html#method.open)
1678    can return an
1679    [`io::Error`](../std/io/struct.Error.html).
1680 2. [`csv::Reader::decode`](http://burntsushi.net/rustdoc/csv/struct.Reader.html#method.decode)
1681    decodes one record at a time, and
1682    [decoding a
1683    record](http://burntsushi.net/rustdoc/csv/struct.DecodedRecords.html)
1684    (look at the `Item` associated type on the `Iterator` impl)
1685    can produce a
1686    [`csv::Error`](http://burntsushi.net/rustdoc/csv/enum.Error.html).
1687 3. If `row.population` is `None`, then calling `expect` will panic.
1688
1689 Are there any others? What if we can't find a matching city? Tools like `grep`
1690 will return an error code, so we probably should too. So we have logic errors
1691 specific to our problem, IO errors and CSV parsing errors. We're going to
1692 explore two different ways to approach handling these errors.
1693
1694 I'd like to start with `Box<Error>`. Later, we'll see how defining our own
1695 error type can be useful.
1696
1697 ## Error handling with `Box<Error>`
1698
1699 `Box<Error>` is nice because it *just works*. You don't need to define your own
1700 error types and you don't need any `From` implementations. The downside is that
1701 since `Box<Error>` is a trait object, it *erases the type*, which means the
1702 compiler can no longer reason about its underlying type.
1703
1704 [Previously](#the-limits-of-combinators) we started refactoring our code by
1705 changing the type of our function from `T` to `Result<T, OurErrorType>`. In
1706 this case, `OurErrorType` is just `Box<Error>`. But what's `T`? And can we add
1707 a return type to `main`?
1708
1709 The answer to the second question is no, we can't. That means we'll need to
1710 write a new function. But what is `T`? The simplest thing we can do is to
1711 return a list of matching `Row` values as a `Vec<Row>`. (Better code would
1712 return an iterator, but that is left as an exercise to the reader.)
1713
1714 Let's refactor our code into its own function, but keep the calls to `unwrap`.
1715 Note that we opt to handle the possibility of a missing population count by
1716 simply ignoring that row.
1717
1718 ```rust,ignore
1719 struct Row {
1720     // unchanged
1721 }
1722
1723 struct PopulationCount {
1724     city: String,
1725     country: String,
1726     // This is no longer an `Option` because values of this type are only
1727     // constructed if they have a population count.
1728     count: u64,
1729 }
1730
1731 fn print_usage(program: &str, opts: Options) {
1732     println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>", program)));
1733 }
1734
1735 fn search<P: AsRef<Path>>(file_path: P, city: &str) -> Vec<PopulationCount> {
1736     let mut found = vec![];
1737     let file = fs::File::open(file_path).unwrap();
1738     let mut rdr = csv::Reader::from_reader(file);
1739     for row in rdr.decode::<Row>() {
1740         let row = row.unwrap();
1741         match row.population {
1742             None => { } // skip it
1743             Some(count) => if row.city == city {
1744                 found.push(PopulationCount {
1745                     city: row.city,
1746                     country: row.country,
1747                     count: count,
1748                 });
1749             },
1750         }
1751     }
1752     found
1753 }
1754
1755 fn main() {
1756         let args: Vec<String> = env::args().collect();
1757         let program = args[0].clone();
1758
1759         let mut opts = Options::new();
1760         opts.optflag("h", "help", "Show this usage message.");
1761
1762         let matches = match opts.parse(&args[1..]) {
1763                 Ok(m)  => { m }
1764                 Err(e) => { panic!(e.to_string()) }
1765         };
1766         if matches.opt_present("h") {
1767                 print_usage(&program, opts);
1768                 return;
1769         }
1770
1771         let data_file = args[1].clone();
1772         let data_path = Path::new(&data_file);
1773         let city = args[2].clone();
1774         for pop in search(&data_path, &city) {
1775                 println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
1776         }
1777 }
1778
1779 ```
1780
1781 While we got rid of one use of `expect` (which is a nicer variant of `unwrap`),
1782 we still should handle the absence of any search results.
1783
1784 To convert this to proper error handling, we need to do the following:
1785
1786 1. Change the return type of `search` to be `Result<Vec<PopulationCount>,
1787    Box<Error>>`.
1788 2. Use the [`try!` macro](#code-try-def) so that errors are returned to the
1789    caller instead of panicking the program.
1790 3. Handle the error in `main`.
1791
1792 Let's try it:
1793
1794 ```rust,ignore
1795 fn search<P: AsRef<Path>>
1796          (file_path: P, city: &str)
1797          -> Result<Vec<PopulationCount>, Box<Error+Send+Sync>> {
1798     let mut found = vec![];
1799     let file = try!(fs::File::open(file_path));
1800     let mut rdr = csv::Reader::from_reader(file);
1801     for row in rdr.decode::<Row>() {
1802         let row = try!(row);
1803         match row.population {
1804             None => { } // skip it
1805             Some(count) => if row.city == city {
1806                 found.push(PopulationCount {
1807                     city: row.city,
1808                     country: row.country,
1809                     count: count,
1810                 });
1811             },
1812         }
1813     }
1814     if found.is_empty() {
1815         Err(From::from("No matching cities with a population were found."))
1816     } else {
1817         Ok(found)
1818     }
1819 }
1820 ```
1821
1822 Instead of `x.unwrap()`, we now have `try!(x)`. Since our function returns a
1823 `Result<T, E>`, the `try!` macro will return early from the function if an
1824 error occurs.
1825
1826 There is one big gotcha in this code: we used `Box<Error + Send + Sync>`
1827 instead of `Box<Error>`. We did this so we could convert a plain string to an
1828 error type. We need these extra bounds so that we can use the
1829 [corresponding `From`
1830 impls](../std/convert/trait.From.html):
1831
1832 ```rust,ignore
1833 // We are making use of this impl in the code above, since we call `From::from`
1834 // on a `&'static str`.
1835 impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a>
1836
1837 // But this is also useful when you need to allocate a new string for an
1838 // error message, usually with `format!`.
1839 impl From<String> for Box<Error + Send + Sync>
1840 ```
1841
1842 Since `search` now returns a `Result<T, E>`, `main` should use case analysis
1843 when calling `search`:
1844
1845 ```rust,ignore
1846 ...
1847 match search(&data_file, &city) {
1848     Ok(pops) => {
1849         for pop in pops {
1850             println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
1851         }
1852     }
1853     Err(err) => println!("{}", err)
1854 }
1855 ...
1856 ```
1857
1858 Now that we've seen how to do proper error handling with `Box<Error>`, let's
1859 try a different approach with our own custom error type. But first, let's take
1860 a quick break from error handling and add support for reading from `stdin`.
1861
1862 ## Reading from stdin
1863
1864 In our program, we accept a single file for input and do one pass over the
1865 data. This means we probably should be able to accept input on stdin. But maybe
1866 we like the current format too—so let's have both!
1867
1868 Adding support for stdin is actually quite easy. There are only three things we
1869 have to do:
1870
1871 1. Tweak the program arguments so that a single parameter—the
1872    city—can be accepted while the population data is read from stdin.
1873 2. Modify the program so that an option `-f` can take the file, if it
1874     is not passed into stdin.
1875 3. Modify the `search` function to take an *optional* file path. When `None`,
1876    it should know to read from stdin.
1877
1878 First, here's the new usage:
1879
1880 ```rust,ignore
1881 fn print_usage(program: &str, opts: Options) {
1882         println!("{}", opts.usage(&format!("Usage: {} [options] <city>", program)));
1883 }
1884 ```
1885 The next part is going to be only a little harder:
1886
1887 ```rust,ignore
1888 ...
1889 let mut opts = Options::new();
1890 opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
1891 opts.optflag("h", "help", "Show this usage message.");
1892 ...
1893 let file = matches.opt_str("f");
1894 let data_file = file.as_ref().map(Path::new);
1895
1896 let city = if !matches.free.is_empty() {
1897         matches.free[0].clone()
1898 } else {
1899         print_usage(&program, opts);
1900         return;
1901 };
1902
1903 for pop in search(&data_file, &city) {
1904         println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
1905 }
1906 ...
1907 ```
1908
1909 In this piece of code, we take `file` (which has the type
1910 `Option<String>`), and convert it to a type that `search` can use, in
1911 this case, `&Option<AsRef<Path>>`. To do this, we take a reference of
1912 file, and map `Path::new` onto it. In this case, `as_ref()` converts
1913 the `Option<String>` into an `Option<&str>`, and from there, we can
1914 execute `Path::new` to the content of the optional, and return the
1915 optional of the new value. Once we have that, it is a simple matter of
1916 getting the `city` argument and executing `search`.
1917
1918 Modifying `search` is slightly trickier. The `csv` crate can build a
1919 parser out of
1920 [any type that implements `io::Read`](http://burntsushi.net/rustdoc/csv/struct.Reader.html#method.from_reader).
1921 But how can we use the same code over both types? There's actually a
1922 couple ways we could go about this. One way is to write `search` such
1923 that it is generic on some type parameter `R` that satisfies
1924 `io::Read`. Another way is to just use trait objects:
1925
1926 ```rust,ignore
1927 fn search<P: AsRef<Path>>
1928          (file_path: &Option<P>, city: &str)
1929          -> Result<Vec<PopulationCount>, Box<Error+Send+Sync>> {
1930     let mut found = vec![];
1931     let input: Box<io::Read> = match *file_path {
1932         None => Box::new(io::stdin()),
1933         Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
1934     };
1935     let mut rdr = csv::Reader::from_reader(input);
1936     // The rest remains unchanged!
1937 }
1938 ```
1939
1940 ## Error handling with a custom type
1941
1942 Previously, we learned how to
1943 [compose errors using a custom error type](#composing-custom-error-types).
1944 We did this by defining our error type as an `enum` and implementing `Error`
1945 and `From`.
1946
1947 Since we have three distinct errors (IO, CSV parsing and not found), let's
1948 define an `enum` with three variants:
1949
1950 ```rust,ignore
1951 #[derive(Debug)]
1952 enum CliError {
1953     Io(io::Error),
1954     Csv(csv::Error),
1955     NotFound,
1956 }
1957 ```
1958
1959 And now for impls on `Display` and `Error`:
1960
1961 ```rust,ignore
1962 impl fmt::Display for CliError {
1963     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1964         match *self {
1965             CliError::Io(ref err) => err.fmt(f),
1966             CliError::Csv(ref err) => err.fmt(f),
1967             CliError::NotFound => write!(f, "No matching cities with a \
1968                                              population were found."),
1969         }
1970     }
1971 }
1972
1973 impl Error for CliError {
1974     fn description(&self) -> &str {
1975         match *self {
1976             CliError::Io(ref err) => err.description(),
1977             CliError::Csv(ref err) => err.description(),
1978             CliError::NotFound => "not found",
1979         }
1980     }
1981 }
1982 ```
1983
1984 Before we can use our `CliError` type in our `search` function, we need to
1985 provide a couple `From` impls. How do we know which impls to provide? Well,
1986 we'll need to convert from both `io::Error` and `csv::Error` to `CliError`.
1987 Those are the only external errors, so we'll only need two `From` impls for
1988 now:
1989
1990 ```rust,ignore
1991 impl From<io::Error> for CliError {
1992     fn from(err: io::Error) -> CliError {
1993         CliError::Io(err)
1994     }
1995 }
1996
1997 impl From<csv::Error> for CliError {
1998     fn from(err: csv::Error) -> CliError {
1999         CliError::Csv(err)
2000     }
2001 }
2002 ```
2003
2004 The `From` impls are important because of how
2005 [`try!` is defined](#code-try-def). In particular, if an error occurs,
2006 `From::from` is called on the error, which in this case, will convert it to our
2007 own error type `CliError`.
2008
2009 With the `From` impls done, we only need to make two small tweaks to our
2010 `search` function: the return type and the “not found” error. Here it is in
2011 full:
2012
2013 ```rust,ignore
2014 fn search<P: AsRef<Path>>
2015          (file_path: &Option<P>, city: &str)
2016          -> Result<Vec<PopulationCount>, CliError> {
2017     let mut found = vec![];
2018     let input: Box<io::Read> = match *file_path {
2019         None => Box::new(io::stdin()),
2020         Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
2021     };
2022     let mut rdr = csv::Reader::from_reader(input);
2023     for row in rdr.decode::<Row>() {
2024         let row = try!(row);
2025         match row.population {
2026             None => { } // skip it
2027             Some(count) => if row.city == city {
2028                 found.push(PopulationCount {
2029                     city: row.city,
2030                     country: row.country,
2031                     count: count,
2032                 });
2033             },
2034         }
2035     }
2036     if found.is_empty() {
2037         Err(CliError::NotFound)
2038     } else {
2039         Ok(found)
2040     }
2041 }
2042 ```
2043
2044 No other changes are necessary.
2045
2046 ## Adding functionality
2047
2048 Writing generic code is great, because generalizing stuff is cool, and
2049 it can then be useful later. But sometimes, the juice isn't worth the
2050 squeeze. Look at what we just did in the previous step:
2051
2052 1. Defined a new error type.
2053 2. Added impls for `Error`, `Display` and two for `From`.
2054
2055 The big downside here is that our program didn't improve a whole lot.
2056 There is quite a bit of overhead to representing errors with `enum`s,
2057 especially in short programs like this.
2058
2059 *One* useful aspect of using a custom error type like we've done here is that
2060 the `main` function can now choose to handle errors differently. Previously,
2061 with `Box<Error>`, it didn't have much of a choice: just print the message.
2062 We're still doing that here, but what if we wanted to, say, add a `--quiet`
2063 flag? The `--quiet` flag should silence any verbose output.
2064
2065 Right now, if the program doesn't find a match, it will output a message saying
2066 so. This can be a little clumsy, especially if you intend for the program to
2067 be used in shell scripts.
2068
2069 So let's start by adding the flags. Like before, we need to tweak the usage
2070 string and add a flag to the Option variable. Once we've done that, Getopts does the rest:
2071
2072 ```rust,ignore
2073 ...
2074 let mut opts = Options::new();
2075 opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
2076 opts.optflag("h", "help", "Show this usage message.");
2077 opts.optflag("q", "quiet", "Silences errors and warnings.");
2078 ...
2079 ```
2080
2081 Now we just need to implement our “quiet” functionality. This requires us to
2082 tweak the case analysis in `main`:
2083
2084 ```rust,ignore
2085 match search(&args.arg_data_path, &args.arg_city) {
2086     Err(CliError::NotFound) if args.flag_quiet => process::exit(1),
2087     Err(err) => panic!("{}", err),
2088     Ok(pops) => for pop in pops {
2089         println!("{}, {}: {:?}", pop.city, pop.country, pop.count);
2090     }
2091 }
2092 ```
2093
2094 Certainly, we don't want to be quiet if there was an IO error or if the data
2095 failed to parse. Therefore, we use case analysis to check if the error type is
2096 `NotFound` *and* if `--quiet` has been enabled. If the search failed, we still
2097 quit with an exit code (following `grep`'s convention).
2098
2099 If we had stuck with `Box<Error>`, then it would be pretty tricky to implement
2100 the `--quiet` functionality.
2101
2102 This pretty much sums up our case study. From here, you should be ready to go
2103 out into the world and write your own programs and libraries with proper error
2104 handling.
2105
2106 # The Short Story
2107
2108 Since this chapter is long, it is useful to have a quick summary for error
2109 handling in Rust. These are some good “rules of thumb." They are emphatically
2110 *not* commandments. There are probably good reasons to break every one of these
2111 heuristics!
2112
2113 * If you're writing short example code that would be overburdened by error
2114   handling, it's probably just fine to use `unwrap` (whether that's
2115   [`Result::unwrap`](../std/result/enum.Result.html#method.unwrap),
2116   [`Option::unwrap`](../std/option/enum.Option.html#method.unwrap)
2117   or preferably
2118   [`Option::expect`](../std/option/enum.Option.html#method.expect)).
2119   Consumers of your code should know to use proper error handling. (If they
2120   don't, send them here!)
2121 * If you're writing a quick 'n' dirty program, don't feel ashamed if you use
2122   `unwrap`. Be warned: if it winds up in someone else's hands, don't be
2123   surprised if they are agitated by poor error messages!
2124 * If you're writing a quick 'n' dirty program and feel ashamed about panicking
2125   anyway, then use either a `String` or a `Box<Error + Send + Sync>` for your
2126   error type (the `Box<Error + Send + Sync>` type is because of the
2127   [available `From` impls](../std/convert/trait.From.html)).
2128 * Otherwise, in a program, define your own error types with appropriate
2129   [`From`](../std/convert/trait.From.html)
2130   and
2131   [`Error`](../std/error/trait.Error.html)
2132   impls to make the [`try!`](../std/macro.try!.html)
2133   macro more ergonomic.
2134 * If you're writing a library and your code can produce errors, define your own
2135   error type and implement the
2136   [`std::error::Error`](../std/error/trait.Error.html)
2137   trait. Where appropriate, implement
2138   [`From`](../std/convert/trait.From.html) to make both
2139   your library code and the caller's code easier to write. (Because of Rust's
2140   coherence rules, callers will not be able to impl `From` on your error type,
2141   so your library should do it.)
2142 * Learn the combinators defined on
2143   [`Option`](../std/option/enum.Option.html)
2144   and
2145   [`Result`](../std/result/enum.Result.html).
2146   Using them exclusively can be a bit tiring at times, but I've personally
2147   found a healthy mix of `try!` and combinators to be quite appealing.
2148   `and_then`, `map` and `unwrap_or` are my favorites.
2149
2150 [1]: ../book/patterns.html
2151 [2]: ../std/option/enum.Option.html#method.map
2152 [3]: ../std/option/enum.Option.html#method.unwrap_or
2153 [4]: ../std/option/enum.Option.html#method.unwrap_or_else
2154 [5]: ../std/option/enum.Option.html
2155 [6]: ../std/result/
2156 [7]: ../std/result/enum.Result.html#method.unwrap
2157 [8]: ../std/fmt/trait.Debug.html
2158 [9]: ../std/primitive.str.html#method.parse
2159 [10]: ../book/associated-types.html
2160 [11]: https://github.com/petewarden/dstkdata
2161 [12]: http://burntsushi.net/stuff/worldcitiespop.csv.gz
2162 [13]: http://burntsushi.net/stuff/uscitiespop.csv.gz
2163 [14]: http://doc.crates.io/guide.html
2164 [15]: http://doc.rust-lang.org/getopts/getopts/index.html