Skip to content

Made Results API more composable #10364

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustpkg/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,7 @@ fn test_linker_build() {
let workspace = workspace.path();
let matches = getopts([], optgroups());
let options = build_session_options(@"rustpkg",
matches.get_ref(),
matches.as_ref().unwrap(),
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
let sess = build_session(options,
Expand Down
1 change: 0 additions & 1 deletion src/libstd/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ mod tests {
use super::*;
use super::AnyRefExt;
use option::{Some, None};
use hash::Hash;

#[deriving(Eq)]
struct Test;
Expand Down
167 changes: 43 additions & 124 deletions src/libstd/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,23 @@

//! A type representing either success or failure

use any::Any;
use clone::Clone;
use cmp::Eq;
use fmt;
use iter::Iterator;
use kinds::Send;
use option::{None, Option, Some, OptionIterator};
use option::{None, Option, Some};
use option::{ToOption, IntoOption, AsOption};
use str::OwnedStr;
use to_str::ToStr;
use vec::OwnedVector;
use vec;

/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
///
/// In order to provide informative error messages, `E` is required to implement `ToStr`.
/// It is further recommended for `E` to be a descriptive error type, eg a `enum` for
/// all possible errors cases.
#[deriving(Clone, DeepClone, Eq, Ord, TotalEq, TotalOrd, ToStr)]
pub enum Result<T, E> {
/// Contains the successful result value
/// Contains the success value
Ok(T),

/// Contains the error value
Err(E)
}
Expand All @@ -40,7 +35,7 @@ pub enum Result<T, E> {
// Type implementation
/////////////////////////////////////////////////////////////////////////////

impl<T, E: ToStr> Result<T, E> {
impl<T, E> Result<T, E> {
/////////////////////////////////////////////////////////////////////////
// Querying the contained values
/////////////////////////////////////////////////////////////////////////
Expand All @@ -60,71 +55,48 @@ impl<T, E: ToStr> Result<T, E> {
!self.is_ok()
}

/////////////////////////////////////////////////////////////////////////
// Adapter for working with references
/////////////////////////////////////////////////////////////////////////

/// Convert from `Result<T, E>` to `Result<&T, &E>`
#[inline]
pub fn as_ref<'r>(&'r self) -> Result<&'r T, &'r E> {
match *self {
Ok(ref x) => Ok(x),
Err(ref x) => Err(x),
}
}

/// Convert from `Result<T, E>` to `Result<&mut T, &mut E>`
#[inline]
pub fn as_mut<'r>(&'r mut self) -> Result<&'r mut T, &'r mut E> {
match *self {
Ok(ref mut x) => Ok(x),
Err(ref mut x) => Err(x),
}
}

/////////////////////////////////////////////////////////////////////////
// Getting to contained values
// Adapter for each variant
/////////////////////////////////////////////////////////////////////////

/// Unwraps a result, yielding the content of an `Ok`.
/// Fails if the value is a `Err` with a custom failure message provided by `msg`.
/// Convert from `Result<T, E>` to `Option<T>`
#[inline]
pub fn expect<M: Any + Send>(self, msg: M) -> T {
pub fn ok(self) -> Option<T> {
match self {
Ok(t) => t,
Err(_) => fail!(msg),
Ok(x) => Some(x),
Err(_) => None,
}
}

/// Unwraps a result, yielding the content of an `Err`.
/// Fails if the value is a `Ok` with a custom failure message provided by `msg`.
/// Convert from `Result<T, E>` to `Option<E>`
#[inline]
pub fn expect_err<M: Any + Send>(self, msg: M) -> E {
pub fn err(self) -> Option<E> {
match self {
Err(e) => e,
Ok(_) => fail!(msg),
Ok(_) => None,
Err(x) => Some(x),
}
}

/// Unwraps a result, yielding the content of an `Ok`.
/// Fails if the value is a `Err` with an error message derived
/// from `E`'s `ToStr` implementation.
/////////////////////////////////////////////////////////////////////////
// Adapter for working with references
/////////////////////////////////////////////////////////////////////////

/// Convert from `Result<T, E>` to `Result<&T, &E>`
#[inline]
pub fn unwrap(self) -> T {
match self {
Ok(t) => t,
Err(e) => fail!("called `Result::unwrap()` on `Err` value '{}'",
e.to_str()),
pub fn as_ref<'r>(&'r self) -> Result<&'r T, &'r E> {
match *self {
Ok(ref x) => Ok(x),
Err(ref x) => Err(x),
}
}

/// Unwraps a result, yielding the content of an `Err`.
/// Fails if the value is a `Ok`.
/// Convert from `Result<T, E>` to `Result<&mut T, &mut E>`
#[inline]
pub fn unwrap_err(self) -> E {
match self {
Ok(_) => fail!("called `Result::unwrap_err()` on an `Ok` value"),
Err(e) => e
pub fn as_mut<'r>(&'r mut self) -> Result<&'r mut T, &'r mut E> {
match *self {
Ok(ref mut x) => Ok(x),
Err(ref mut x) => Err(x),
}
}

Expand Down Expand Up @@ -163,34 +135,6 @@ impl<T, E: ToStr> Result<T, E> {
}
}

/////////////////////////////////////////////////////////////////////////
// Iterator constructors
/////////////////////////////////////////////////////////////////////////

/// Returns an `Iterator` over one or zero references to the value of an `Ok`
///
/// Example:
///
/// for buf in read_file(file) {
/// print_buf(buf)
/// }
#[inline]
pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
match *self {
Ok(ref t) => Some(t),
Err(..) => None,
}.move_iter()
}

/// Returns an `Iterator` over one or zero references to the value of an `Err`
#[inline]
pub fn iter_err<'r>(&'r self) -> OptionIterator<&'r E> {
match *self {
Ok(..) => None,
Err(ref t) => Some(t),
}.move_iter()
}

////////////////////////////////////////////////////////////////////////
// Boolean operations on the values, eager and lazy
/////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -239,17 +183,23 @@ impl<T, E: ToStr> Result<T, E> {
// Common special cases
/////////////////////////////////////////////////////////////////////////

/// Get a reference to the value out of a successful result
///
/// # Failure
///
/// If the result is an error
/// Unwraps a result, yielding the content of an `Ok`.
/// Fails if the value is an `Err`.
#[inline]
pub fn get_ref<'a>(&'a self) -> &'a T {
match *self {
Ok(ref t) => t,
Err(ref e) => fail!("called `Result::get_ref()` on `Err` value '{}'",
e.to_str()),
pub fn unwrap(self) -> T {
match self {
Ok(t) => t,
Err(_) => fail!("called `Result::unwrap()` on an `Err` value")
}
}

/// Unwraps a result, yielding the content of an `Err`.
/// Fails if the value is an `Ok`.
#[inline]
pub fn unwrap_err(self) -> E {
match self {
Ok(_) => fail!("called `Result::unwrap_err()` on an `Ok` value"),
Err(e) => e
}
}
}
Expand Down Expand Up @@ -458,31 +408,6 @@ mod tests {
assert_eq!(op2().or_else(|e| Err::<int, ~str>(e + "!")).unwrap_err(), ~"sadface!");
}

#[test]
pub fn test_impl_iter() {
let mut valid = false;
let okval = Ok::<~str, ~str>(~"a");
okval.iter().next().map(|_| { valid = true; });
assert!(valid);

let errval = Err::<~str, ~str>(~"b");
errval.iter().next().map(|_| { valid = false; });
assert!(valid);
}

#[test]
pub fn test_impl_iter_err() {
let mut valid = true;
let okval = Ok::<~str, ~str>(~"a");
okval.iter_err().next().map(|_| { valid = false });
assert!(valid);

valid = false;
let errval = Err::<~str, ~str>(~"b");
errval.iter_err().next().map(|_| { valid = true });
assert!(valid);
}

#[test]
pub fn test_impl_map() {
assert_eq!(Ok::<~str, ~str>(~"a").map(|x| x + "b"), Ok(~"ab"));
Expand All @@ -495,12 +420,6 @@ mod tests {
assert_eq!(Err::<~str, ~str>(~"a").map_err(|x| x + "b"), Err(~"ab"));
}

#[test]
pub fn test_get_ref_method() {
let foo: Result<int, ()> = Ok(100);
assert_eq!(*foo.get_ref(), 100);
}

#[test]
fn test_collect() {
assert_eq!(collect(range(0, 0)
Expand Down
1 change: 1 addition & 0 deletions src/libstd/rt/local_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub unsafe fn borrow<T>(f: |&mut T|) {
/// it wherever possible.
#[cfg(not(windows), not(target_os = "android"))]
pub mod compiled {
#[cfg(not(test))]
use libc::c_void;
use cast;
use option::{Option, Some, None};
Expand Down
2 changes: 1 addition & 1 deletion src/test/run-fail/result-get-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern:called `Result::unwrap()` on `Err` value 'kitty'
// error-pattern:called `Result::unwrap()` on an `Err` value

use std::result;

Expand Down
2 changes: 1 addition & 1 deletion src/test/run-pass/tempfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn test_rm_tempdir() {
let f: proc() -> TempDir = proc() {
TempDir::new("test_rm_tempdir").unwrap()
};
let tmp = task::try(f).expect("test_rm_tmdir");
let tmp = task::try(f).ok().expect("test_rm_tmdir");
path = tmp.path().clone();
assert!(path.exists());
}
Expand Down