diff --git a/src/libcore/error.rs b/src/libcore/error.rs new file mode 100644 index 0000000000000..f0eb9b8424a22 --- /dev/null +++ b/src/libcore/error.rs @@ -0,0 +1,35 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A trait for converting between different types of errors. +//! +//! # The `FromError` trait +//! +//! `FromError` is a simple trait that expresses conversions between different +//! error types. To provide maximum flexibility, it does not require either of +//! the types to actually implement the `Error` trait from the `std` crate, +//! although this will be the common case. +//! +//! The main use of this trait is in the `try!` macro from the `std` crate, +//! which uses it to automatically convert a given error to the error specified +//! in a function's return type. + +/// A trait for types that can be converted from a given error type `E`. +pub trait FromError { + /// Perform the conversion. + fn from_error(err: E) -> Self; +} + +// Any type is convertable from itself +impl FromError for E { + fn from_error(err: E) -> E { + err + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5e3c74477d15c..a8ad0c29c05f6 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -58,7 +58,7 @@ #![no_std] #![allow(unknown_features)] -#![feature(globs, intrinsics, lang_items, macro_rules, phase)] +#![feature(default_type_params, globs, intrinsics, lang_items, macro_rules, phase)] #![feature(simd, unsafe_destructor, slicing_syntax)] #![deny(missing_docs)] @@ -102,6 +102,7 @@ pub mod ops; pub mod cmp; pub mod clone; pub mod default; +pub mod error; /* Core types and methods on primitives */ diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 0dc4fb839659d..a8d593dcda88a 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -278,6 +278,7 @@ pub use self::Result::*; +use error::FromError; use std::fmt::Show; use slice; use slice::AsSlice; @@ -633,10 +634,10 @@ impl Result { /// ``` #[inline] #[stable] - pub fn and(self, res: Result) -> Result { + pub fn and = E>(self, res: Result) -> Result { match self { Ok(_) => res, - Err(e) => Err(e), + Err(e) => Err(FromError::from_error(e)), } } @@ -657,10 +658,10 @@ impl Result { /// ``` #[inline] #[unstable = "waiting for unboxed closures"] - pub fn and_then(self, op: |T| -> Result) -> Result { + pub fn and_then = E>(self, op: |T| -> Result) -> Result { match self { Ok(t) => op(t), - Err(e) => Err(e), + Err(e) => Err(FromError::from_error(e)), } } diff --git a/src/libcoretest/result.rs b/src/libcoretest/result.rs index 92124e2f299cd..024e360d68b8b 100644 --- a/src/libcoretest/result.rs +++ b/src/libcoretest/result.rs @@ -8,24 +8,36 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::error::FromError; use core::iter::range; +#[deriving(PartialEq, Show)] +struct Error(&'static str); +impl FromError<&'static str> for Error { + fn from_error(msg: &'static str) -> Error { + Error(msg) + } +} + pub fn op1() -> Result { Ok(666) } pub fn op2() -> Result { Err("sadface") } +pub fn op3(n: int) -> Result { Ok(n * 2) } +pub fn op4(_: int) -> Result { Err(Error("oh well :(")) } #[test] pub fn test_and() { - assert_eq!(op1().and(Ok(667i)).unwrap(), 667); + assert_eq!(op1().and(Ok::(667i)).unwrap(), 667); assert_eq!(op1().and(Err::<(), &'static str>("bad")).unwrap_err(), "bad"); - assert_eq!(op2().and(Ok(667i)).unwrap_err(), "sadface"); - assert_eq!(op2().and(Err::<(),&'static str>("bad")).unwrap_err(), + assert_eq!(op2().and(Ok::(667i)).unwrap_err(), "sadface"); + assert_eq!(op2().and(Err::<(), &'static str>("bad")).unwrap_err(), "sadface"); } #[test] pub fn test_and_then() { + assert_eq!(op1().and_then(|i| Ok::(i + 1)).unwrap(), 667); assert_eq!(op1().and_then(|_| Err::("bad")).unwrap_err(), "bad"); @@ -34,6 +46,11 @@ pub fn test_and_then() { "sadface"); assert_eq!(op2().and_then(|_| Err::("bad")).unwrap_err(), "sadface"); + + assert_eq!(op1().and_then(op3).unwrap(), 666 * 2); + assert_eq!(op2().and_then(op3).unwrap_err(), Error("sadface")); + assert_eq!(op1().and_then(op4).unwrap_err(), Error("oh well :(")); + assert_eq!(op2().and_then(op4).unwrap_err(), Error("sadface")); } #[test] diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 82ad893f88a1a..5a56e6a09f2dc 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -78,6 +78,7 @@ //! } //! ``` +pub use core::error::FromError; use option::{Option, None}; use kinds::Send; use string::String; @@ -93,16 +94,3 @@ pub trait Error: Send { /// The lower-level cause of this error, if any. fn cause(&self) -> Option<&Error> { None } } - -/// A trait for types that can be converted from a given error type `E`. -pub trait FromError { - /// Perform the conversion. - fn from_error(err: E) -> Self; -} - -// Any type is convertable from itself -impl FromError for E { - fn from_error(err: E) -> E { - err - } -}