@@ -14,7 +14,7 @@ When done naïvely, error handling in Rust can be verbose and annoying. This
1414chapter will explore those stumbling blocks and demonstrate how to use the
1515standard library to make error handling concise and ergonomic.
1616
17- ## Table of Contents
17+ # Table of Contents
1818
1919This chapter is very long, mostly because we start at the very beginning with
2020sum types and combinators, and try to motivate the way Rust does error handling
@@ -24,11 +24,11 @@ systems may want to jump around.
2424* [ The Basics] ( #the-basics )
2525 * [ Unwrapping explained] ( #unwrapping-explained )
2626 * [ The ` Option ` type] ( #the-option-type )
27- * [ Composing ` Option<T> ` values] ( #composing-option-t -values )
27+ * [ Composing ` Option<T> ` values] ( #composing-optiont -values )
2828 * [ The ` Result ` type] ( #the-result-type )
2929 * [ Parsing integers] ( #parsing-integers )
3030 * [ The ` Result ` type alias idiom] ( #the-result-type-alias-idiom )
31- * [ A brief interlude: unwrapping isn't evil] ( #a-brief-interlude-unwrapping-isn-t -evil )
31+ * [ A brief interlude: unwrapping isn't evil] ( #a-brief-interlude-unwrapping-isnt -evil )
3232* [ Working with multiple error types] ( #working-with-multiple-error-types )
3333 * [ Composing ` Option ` and ` Result ` ] ( #composing-option-and-result )
3434 * [ The limits of combinators] ( #the-limits-of-combinators )
@@ -42,17 +42,16 @@ systems may want to jump around.
4242 * [ Composing custom error types] ( #composing-custom-error-types )
4343 * [ Advice for library writers] ( #advice-for-library-writers )
4444* [ Case study: A program to read population data] ( #case-study-a-program-to-read-population-data )
45- * [ It's on Github] ( #it-s-on-github )
4645 * [ Initial setup] ( #initial-setup )
4746 * [ Argument parsing] ( #argument-parsing )
4847 * [ Writing the logic] ( #writing-the-logic )
49- * [ Error handling with ` Box<Error> ` ] ( #error-handling-with-box-error )
48+ * [ Error handling with ` Box<Error> ` ] ( #error-handling-with-boxerror )
5049 * [ Reading from stdin] ( #reading-from-stdin )
5150 * [ Error handling with a custom type] ( #error-handling-with-a-custom-type )
5251 * [ Adding functionality] ( #adding-functionality )
5352* [ The short story] ( #the-short-story )
5453
55- ## The Basics
54+ # The Basics
5655
5756You can think of error handling as using * case analysis* to determine whether
5857a computation was successful or not. As you will see, the key to ergonomic error
@@ -107,7 +106,7 @@ You can think of this style of error handling as similar to a bull running
107106through a china shop. The bull will get to where it wants to go, but it will
108107trample everything in the process.
109108
110- ### Unwrapping explained
109+ ## Unwrapping explained
111110
112111In the previous example, we claimed
113112that the program would simply panic if it reached one of the two error
@@ -121,7 +120,7 @@ It would be better if we just showed the code for unwrapping because it is so
121120simple, but to do that, we will first need to explore the ` Option ` and ` Result `
122121types. Both of these types have a method called ` unwrap ` defined on them.
123122
124- ### The ` Option ` type
123+ ## The ` Option ` type
125124
126125The ` Option ` type is
127126[ defined in the standard library] [ 1 ] :
@@ -205,7 +204,7 @@ The `unwrap` method *abstracts away the case analysis*. This is precisely the th
205204that makes ` unwrap ` ergonomic to use. Unfortunately, that ` panic! ` means that
206205` unwrap ` is not composable: it is the bull in the china shop.
207206
208- #### Composing ` Option<T> ` values
207+ ### Composing ` Option<T> ` values
209208
210209In [ ` option-ex-string-find ` ] ( #code-option-ex-string-find-2 )
211210we saw how to use ` find ` to discover the extension in a file name. Of course,
@@ -382,7 +381,8 @@ Combinators make using types like `Option` ergonomic because they reduce
382381explicit case analysis. They are also composable because they permit the caller
383382to handle the possibility of absence in their own way. Methods like ` unwrap `
384383remove choices because they will panic if ` Option<T> ` is ` None ` .
385- ### The ` Result ` type
384+
385+ ## The ` Result ` type
386386
387387The ` Result ` type is also
388388[ defined in the standard library] [ 6 ] :
@@ -442,7 +442,7 @@ way to print a human readable description of values with that type.)
442442
443443OK, let's move on to an example.
444444
445- #### Parsing integers
445+ ### Parsing integers
446446
447447The Rust standard library makes converting strings to integers dead simple.
448448It's so easy in fact, that it is very tempting to write something like the
@@ -548,7 +548,9 @@ Additionally, since `Result` has a second type parameter, there are
548548combinators that affect only the error type, such as
549549[ ` map_err ` ] ( ../std/result/enum.Result.html#method.map_err ) (instead of
550550` map ` ) and [ ` or_else ` ] ( ../std/result/enum.Result.html#method.or_else )
551- (instead of ` and_then ` ). #### The ` Result ` type alias idiom
551+ (instead of ` and_then ` ).
552+
553+ ### The ` Result ` type alias idiom
552554
553555In the standard library, you may frequently see types like
554556` Result<i32> ` . But wait, [ we defined ` Result ` ] ( #code-result-def-1 ) to
@@ -580,9 +582,7 @@ module's type alias instead of the plain definition from
580582` std::result ` . (This idiom is also used for
581583[ ` fmt::Result ` ] ( ../std/fmt/type.Result.html ) .)
582584
583- ### A brief interlude:
584-
585- unwrapping isn't evil
585+ ## A brief interlude: unwrapping isn't evil
586586
587587If you've been following along, you might have noticed that I've taken a pretty
588588hard line against calling methods like ` unwrap ` that could ` panic ` and abort
@@ -620,7 +620,7 @@ Now that we've covered the basics of error handling in Rust, and
620620explained unwrapping, let's start exploring more of the standard
621621library.
622622
623- ## Working with multiple error types
623+ # Working with multiple error types
624624
625625Thus far, we've looked at error handling where everything was either an
626626` Option<T> ` or a ` Result<T, SomeError> ` . But what happens when you have both an
@@ -629,7 +629,7 @@ Thus far, we've looked at error handling where everything was either an
629629challenge in front of us, and it will be the major theme throughout the rest of
630630this chapter.
631631
632- ### Composing ` Option ` and ` Result `
632+ ## Composing ` Option ` and ` Result `
633633
634634So far, I've talked about combinators defined for ` Option ` and combinators
635635defined for ` Result ` . We can use these combinators to compose results of
@@ -706,7 +706,7 @@ the same (because of our use of `and_then`). Since we chose to convert the
706706` Option<String> ` (from ` argv.nth(1) ` ) to a ` Result<String, String> ` , we must
707707also convert the ` ParseIntError ` from ` arg.parse() ` to a ` String ` .
708708
709- ### The limits of combinators
709+ ## The limits of combinators
710710
711711Doing IO and parsing input is a very common task, and it's one that I
712712personally have done a lot of in Rust. Therefore, we will use (and continue to
@@ -839,7 +839,7 @@ With all of that said, the code is still hairy. Mastering use of combinators is
839839important, but they have their limits. Let's try a different approach: early
840840returns.
841841
842- ### Early returns
842+ ## Early returns
843843
844844I'd like to take the code from the previous section and rewrite it using * early
845845returns* . Early returns let you exit the function early. We can't return early
@@ -886,7 +886,7 @@ ergonomic error handling is reducing explicit case analysis, yet we've reverted
886886back to explicit case analysis here. It turns out, there are * multiple* ways to
887887reduce explicit case analysis. Combinators aren't the only way.
888888
889- ### The ` try! ` macro
889+ ## The ` try! ` macro
890890
891891A cornerstone of error handling in Rust is the ` try! ` macro. The ` try! ` macro
892892abstracts case analysis just like combinators, but unlike combinators, it also
@@ -939,7 +939,7 @@ The good news is that we will soon learn how to remove those `map_err` calls!
939939The bad news is that we will need to learn a bit more about a couple important
940940traits in the standard library before we can remove the ` map_err ` calls.
941941
942- ### Defining your own error type
942+ ## Defining your own error type
943943
944944Before we dive into some of the standard library error traits, I'd like to wrap
945945up this section by removing the use of ` String ` as our error type in the
@@ -1033,14 +1033,16 @@ will do in a pinch, particularly if you're writing an application. If you're
10331033writing a library, defining your own error type should be strongly preferred so
10341034that you don't remove choices from the caller unnecessarily.
10351035
1036- ## Standard library traits used for error handling
1036+ # Standard library traits used for error handling
10371037
10381038The standard library defines two integral traits for error handling:
10391039[ ` std::error::Error ` ] ( ../std/error/trait.Error.html ) and
10401040[ ` std::convert::From ` ] ( ../std/convert/trait.From.html ) . While ` Error `
10411041is designed specifically for generically describing errors, the ` From `
10421042trait serves a more general role for converting values between two
1043- distinct types. ### The ` Error ` trait
1043+ distinct types.
1044+
1045+ ## The ` Error ` trait
10441046
10451047The ` Error ` trait is [ defined in the standard
10461048library] ( ../std/error/trait.Error.html ) :
@@ -1147,7 +1149,7 @@ We note that this is a very typical implementation of `Error`: match on your
11471149different error types and satisfy the contracts defined for ` description ` and
11481150` cause ` .
11491151
1150- ### The ` From ` trait
1152+ ## The ` From ` trait
11511153
11521154The ` std::convert::From ` trait is
11531155[ defined in the standard
@@ -1217,7 +1219,7 @@ us a way to reliably convert errors to the same type using the same function.
12171219
12181220Time to revisit an old friend; the ` try! ` macro.
12191221
1220- ### The real ` try! ` macro
1222+ ## The real ` try! ` macro
12211223
12221224Previously, we presented this definition of ` try! ` :
12231225
@@ -1307,7 +1309,7 @@ chapter](https://crates.io/crates/error).)
13071309
13081310It's time to revisit our custom ` CliError ` type and tie everything together.
13091311
1310- ### Composing custom error types
1312+ ## Composing custom error types
13111313
13121314In the last section, we looked at the real ` try! ` macro and how it does
13131315automatic type conversion for us by calling ` From::from ` on the error value.
@@ -1437,7 +1439,7 @@ impl From<num::ParseFloatError> for CliError {
14371439
14381440And that's it!
14391441
1440- ### Advice for library writers
1442+ ## Advice for library writers
14411443
14421444If your library needs to report custom errors, then you should
14431445probably define your own error type. It's up to you whether or not to
@@ -1468,7 +1470,7 @@ library defines a single error type. This is used in the standard library
14681470for [ ` io::Result ` ] ( ../std/io/type.Result.html )
14691471and [ ` fmt::Result ` ] ( ../std/fmt/type.Result.html ) .
14701472
1471- ## Case study: A program to read population data
1473+ # Case study: A program to read population data
14721474
14731475This chapter was long, and depending on your background, it might be
14741476rather dense. While there is plenty of example code to go along with
@@ -1492,7 +1494,7 @@ parse the program arguments and decode that stuff into Rust types automatically.
14921494[ ` csv ` ] ( https://crates.io/crates/csv ) ,
14931495and [ ` rustc-serialize ` ] ( https://crates.io/crates/rustc-serialize ) crates.
14941496
1495- ### Initial setup
1497+ ## Initial setup
14961498
14971499We're not going to spend a lot of time on setting up a project with
14981500Cargo because it is already covered well in [ the Cargo
@@ -1524,7 +1526,7 @@ cargo build --release
15241526# Outputs: Hello, world!
15251527```
15261528
1527- ### Argument parsing
1529+ ## Argument parsing
15281530
15291531Let's get argument parsing out of the way. we won't go into too much
15301532detail on Getopts, but there is [ some good documentation] [ 15 ]
@@ -1584,7 +1586,7 @@ print for the program name and template. If the user has not passed in
15841586the help flag, we assign the proper variables to their corresponding
15851587arguments.
15861588
1587- ### Writing the logic
1589+ ## Writing the logic
15881590
15891591We're all different in how we write code, but error handling is
15901592usually the last thing we want to think about. This isn't very good
@@ -1681,7 +1683,7 @@ explore two different ways to approach handling these errors.
16811683I'd like to start with ` Box<Error> ` . Later, we'll see how defining our own
16821684error type can be useful.
16831685
1684- ### Error handling with ` Box<Error> `
1686+ ## Error handling with ` Box<Error> `
16851687
16861688` Box<Error> ` is nice because it * just works* . You don't need to define your own
16871689error types and you don't need any ` From ` implementations. The downside is that
@@ -1830,7 +1832,7 @@ Now that we've seen how to do proper error handling with `Box<Error>`, let's
18301832try a different approach with our own custom error type. But first, let's take
18311833a quick break from error handling and add support for reading from ` stdin ` .
18321834
1833- ### Reading from stdin
1835+ ## Reading from stdin
18341836
18351837In our program, we accept a single file for input and do one pass over the
18361838data. This means we probably should be able to accept input on stdin. But maybe
@@ -1907,7 +1909,8 @@ fn search<P: AsRef<Path>>
19071909 // The rest remains unchanged!
19081910}
19091911```
1910- ### Error handling with a custom type
1912+
1913+ ## Error handling with a custom type
19111914
19121915Previously, we learned how to
19131916[ compose errors using a custom error type] ( #composing-custom-error-types ) .
@@ -2013,7 +2016,7 @@ fn search<P: AsRef<Path>>
20132016
20142017No other changes are necessary.
20152018
2016- ### Adding functionality
2019+ ## Adding functionality
20172020
20182021Writing generic code is great, because generalizing stuff is cool, and
20192022it can then be useful later. But sometimes, the juice isn't worth the
@@ -2073,7 +2076,7 @@ This pretty much sums up our case study. From here, you should be ready to go
20732076out into the world and write your own programs and libraries with proper error
20742077handling.
20752078
2076- ## The Short Story
2079+ # The Short Story
20772080
20782081Since this chapter is long, it is useful to have a quick summary for error
20792082handling in Rust. These are some good “rules of thumb." They are emphatically
0 commit comments