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