-
Notifications
You must be signed in to change notification settings - Fork 3.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
start of error handling #134
Conversation
cc me |
# Error Handling | ||
|
||
Rust's laser-focus on safety spills over into a related area: error handling. | ||
Errors are a fact of life in software. Rust has a number of tools that you can |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: do you mean "language features" where you say "tools"? For some reason I always think of tools as external things that you run on your code...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean "a thing you use to accomplish a task", a more general sense than you, I think.
Just added some commits with some small suggestions I couldn't help making while reading :) Other thoughts: Unwind vs abortI'm sure this will come as a shock, but I'm of the opinion that the detail about unwinding vs. aborting is too much for 07-02. The thing that sealed this opinion for me was this sentence:
My mind wants to put a wikipedia-style Is there a section planned for the book that would be about these scenarios (FFI? kernels? i don't even know) that we could move this to? Could we reference the nomicon instead? assert!I'm also questioning the inclusion of the example
What about framing it in more of an iterative software development story? "We got this requirement to make a function to compare numbers between 0 and 100, there's no validation in the UI right now aside from the type checking, so you can totally enter a number greater than 100, but the person asking for this function didn't tell us what the code should do in this case. For now, we're choosing to panic; we're waiting on an answer from them about what we should do, but this prevents us from proceeding with potentially invalid input"? Also sort of contrived, and not the only reason you might panic and then switch to recovering, but it is one reason. This sentence:
gives me the sense that you're not entirely happy with this example :) I'll think on this and see if I get any ideas for something else. try!
Yeah, I think it would be good to have main call a function that calls |
number of tools that you can use when something bad happens to handle the | ||
situation appropriately. | ||
|
||
Rust splits errors into two major kinds: errors that are recoverable and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "groups" errors might read a little better.
Okay, I've removed a bunch of the stuff about unwind vs abort, I've added in the start of a vector example. We also wanted to talk about unwrap... |
efa4088
to
146c07b
Compare
Okay, so. I decided to totally re-write this. Here's a summary: We now focus on showing off functions that already handle errors this way, rather than writing a ton of our own. This general structure is this:
that last part isn't there yet, I wanted to take the temperature on this approach first. One of the biggest changes here is that we don't talk about I also totally scrapped the details about how panic works. Maybe that's too much and we want to put a little bit of it back in, I dunno. I'm inclined to add that at the end, in its own "advanced" section. |
Oh, and this also means that Travis is gonna fail because nightly-only for now. |
Nightly is failing too though, with some cyclic references: https://travis-ci.org/rust-lang/book/jobs/154542003#L366 |
|
||
```rust,should_panic | ||
fn main() { | ||
let v = vec![1, 2, 3]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually haven't talked about vec!
at this point, oops! Any reason this couldn't be an array?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comes after the data structures chapter, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not the way we currently have them ordered, no reason we couldn't swap them though if you wanted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh whoops! Yeah, I think we should swap them; this one should be the last of the three current chapters
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to swap them in SUMMARY on master to remind us, then we can deal with the merge conflicts later :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rebased to fix this
Overall, I love the new direction ❤️ I think it's just what the reader needs at this point in the book. 👏 👏 👏 👏 👏 |
``` | ||
|
||
We attempt to access the hundredth element of our vector, but it only has three | ||
elements. In this situation, Rust will panic. Let's try it: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should say why it's panicking here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see that you have that below. I would reorder it: start with the why and then delve into the mechanics.
I just mentioned this to @aturon , but I believe the "write your own errors" chapter should be moved to the nanescent "advice for library authors" chapter, since we really need traits to talk about it. |
oh poo. Can't the reader just read all the chapters at once? It would be much more efficient that way ;) |
a95c62d
to
efccc7a
Compare
Okay, many of the nits should now be addressed, though not 100% of them yet. |
Ok, I think I'm ready for another review, anyone have time for another look @steveklabnik @aturon @LukasKalbertodt @jonathandturner ? <3 |
(I plan on reviewing later today) On Mon, Oct 17, 2016 at 4:41 PM, Carol (Nichols || Goulding) <
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really, really great. I have some minor nits.
@@ -3,7 +3,10 @@ language: rust | |||
cache: cargo | |||
rust: | |||
- nightly | |||
- stable | |||
# - beta | |||
# ^ to be changed once question_mark is in beta |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rust-lang/rust#36995 means that this will be 1.14 🎊
- [Error Handling](ch09-00-error-handling.md) | ||
- [Unrecoverable errors with panic!](ch09-01-unrecoverable-errors-with-panic.md) | ||
- [Recoverable errors with `Result<T, E>`](ch09-02-recoverable-errors-with-result.md) | ||
- [To `panic!` or Not To `panic!`](ch09-03-to-panic-or-not-to-panic.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this title is in ... title case. The other two sub-titles aren't. Is that just because this is a Shakespeare reference? if so, I'm cool with that, just making sure the others don't need to also be title case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The others do need to be in title case. Good catch!
> up by the operating system. If you're in a situation where you need to make | ||
> the resulting binary as small as possible, you can switch from unwinding on | ||
> panic to aborting on panic by adding `panic = 'abort'` to the appropriate | ||
> `[profile]` sections in your `Cargo.toml` file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"file" is redundant here.
read an element at an index that doesn't exist, Rust will stop execution and | ||
refuse to continue with an invalid value. Let's try it and see: | ||
|
||
```bash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're very handy when prototyping, before you're ready to decide how to | ||
handle errors, and in that case they leave clear markers to look for when you | ||
are ready to make your program more robust. They're useful in tests since they | ||
will cause the test to fail if there's an error anyplace you call them. In |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any place
fn read_username_from_file() -> Result<String, io::Error> { | ||
let mut f = try!(File::open("hello.txt")); | ||
let mut s = String::new(); | ||
try!(f.read_to_string(&mut s)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'd put whitespace both above and below this line
# | ||
fn read_username_from_file() -> Result<String, io::Error> { | ||
let mut s = String::new(); | ||
File::open("hello.txt")?.read_to_string(&mut s)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here, whitespace, above and below
<!-- NOTE: as of 2016-10-12, the error message when calling `?` in a function | ||
that doesn't return a result is confusing. `try!` isn't as bad, so I'm using | ||
that. When https://github.com/rust-lang/rust/issues/35946 is fixed, we can | ||
switch this example to use `?`. /Carol --> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know the error was any different between the two!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeep :(
if value < 1 || value > 100 { | ||
panic!("Guess value must be between 1 and 100, got {}.", value); | ||
} | ||
Guess { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'd put a newline above this
that would be a violation of the contract that `Guess::new` is relying on. This | ||
function needs to signal to the calling code that it has a bug somewhere | ||
leading to the contract violation. The conditions in which `Guess::new` might | ||
panic should be discussed in its public-facing API documentation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to mention the # Panics
convention here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(or maybe a forward reference to the documentation section of the building a library chapter)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forward reference is good :)
Nits addressed! Thank you as always @steveklabnik :) Anyone else? |
ah yes, that'd make sense. On Tue, Oct 18, 2016 at 6:26 PM, Carol (Nichols || Goulding) <
|
Merging this and sending it to nostarch. |
ch16-03 タイポ修正:ミューテック→ミューテックス
…ary-page rust-lang#134 add glossary page
I started on the error handling chapter. I feel... okay about it. I dunno.
I decided to go with an example that we start with a panic, and then convert to a result. I think this draws the connection a bit better than showing two totally different examples, but at the downside of showing function panic that probably shouldn't. Reasonable folks may differ on this tradeoff; I'm open to arguments.
I decided to stop here rather than go on to all the From stuff, because I wanted to make sure that this was on track first. Should we use a different example? Is the length of time spent talking about panic vs abort a waste of time right here? How should I end up demonstrating try!, just making another dummy function from main()?