From 3ba9481cc2c9ed87930b2936da6e5a0bd517fe28 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Thu, 25 Feb 2016 10:30:26 -1000 Subject: [PATCH] Improve style guide regarding how to use `Result<_, ()>`. --- STYLE.md | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/STYLE.md b/STYLE.md index f144795dd..5329af777 100644 --- a/STYLE.md +++ b/STYLE.md @@ -9,19 +9,44 @@ there are some differences and *ring* adds additional guidelines. ## Error checking -Use `Result` as the return type for functions that may fail. In general, -functions do not report error codes for a variety of reasons; when they fail, -they only report that they fail. If a function only needs to return a boolean -indicator that it succeeded or failed, use `Result<(), ()>` as the return type. -Never use `Option` or `bool` or other types as return values to indicate -failure. If an external function (e.g. part of the Rust standard library) -returns `Option` to indicate failure, use `ok_or(())` to map it to -`Result`. +Use `Result` as the return type for functions that may fail. Never use +`Option` or `bool` or other types as return values to indicate failure. +`Result` is used because it is annotated `#[must_use]`, so the Rust compiler +will not let callers silently ignore the return value of functions that return +`Result`s. + +*ring* functions generally do not report error codes for a variety of reasons; +when they fail, they only report that they fail. If a function only needs to +return a boolean indicator that it succeeded or failed, use `Result<(), ()>` as +the return type. + +If an external function (e.g. part of the Rust standard library) returns +`Option` to indicate failure, use `ok_or(())` to map it to `Result`. +When the last statement `x` in a function is already the same `Result` +type that the function returns, just make that statement the return expression; +that is, write `x`, not `let result = try!(x); Ok(result)`. Use the early-return-on-failure pattern by wrapping calls to functions that may fail with `try!()`. Do not use `Result::or_else`, `Result::and`, etc. to chain together strings of potentially-failing operations. +```rust +// The return type is of the form `Result<_, ()>`, not `Option<_>` or something +// else. +fn good_example(x: u32, y: u32) -> Result { + // * `ok_or` is used to map `Option` to `Result` here. + // * `try!` is used to return early on failure. + let sum = try!(x.checked_add(y).ok_or(())); + + // Early return is used. + try!(foo(sum)); + + // `try!()` isn't used when the last statement is already of the form + // `Result<_, ()>`. + bar(sum) +} +``` + ## Arrays and Slices When creating a slice from the start of a indexable value, use `x[..n]`, not