auto merge of #17753 : aturon/rust/error-interop, r=alexcrichton
This PR: * Adds the error interoperation traits (`Error` and `FromError`) to a new module, `std::error`, as per [RFC 70](https://github.com/rust-lang/rfcs/blob/master/active/0070-error-chaining.md). Note that this module must live in `std` in order to refer to `String`. Note that, until multidispatch lands, the `FromError` trait cannot be usefully implemented outside of the blanket impl given here. * Incorporates `std::error::FromError` into the `try!` macro. * Implements `Error` for most existing error enumerations. Closes #17747
This commit is contained in:
commit
ff50f24feb
@ -37,8 +37,6 @@ pub use ops::{Shl, Shr};
|
||||
pub use ops::{Index, IndexMut};
|
||||
pub use ops::{Slice, SliceMut};
|
||||
pub use ops::{Fn, FnMut, FnOnce};
|
||||
pub use option::{Option, Some, None};
|
||||
pub use result::{Result, Ok, Err};
|
||||
|
||||
// Reexported functions
|
||||
pub use iter::range;
|
||||
@ -56,7 +54,9 @@ pub use iter::{OrdIterator, MutableDoubleEndedIterator, ExactSize};
|
||||
pub use num::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
|
||||
pub use num::{Signed, Unsigned, Float};
|
||||
pub use num::{Primitive, Int, ToPrimitive, FromPrimitive};
|
||||
pub use option::{Option, Some, None};
|
||||
pub use ptr::RawPtr;
|
||||
pub use result::{Result, Ok, Err};
|
||||
pub use str::{Str, StrSlice};
|
||||
pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
|
||||
pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
|
||||
|
@ -660,7 +660,7 @@ fn write_out_deps(sess: &Session,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let result = (|| {
|
||||
let result = (|| -> io::IoResult<()> {
|
||||
// Build a list of files used to compile the output and
|
||||
// write Makefile-compatible dependency rules
|
||||
let files: Vec<String> = sess.codemap().files.borrow()
|
||||
|
@ -13,6 +13,7 @@
|
||||
//! Base64 binary-to-text encoding
|
||||
use std::fmt;
|
||||
use std::string;
|
||||
use std::error;
|
||||
|
||||
/// Available encoding character sets
|
||||
pub enum CharacterSet {
|
||||
@ -178,6 +179,19 @@ impl fmt::Show for FromBase64Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for FromBase64Error {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
InvalidBase64Byte(_, _) => "invalid character",
|
||||
InvalidBase64Length => "invalid length",
|
||||
}
|
||||
}
|
||||
|
||||
fn detail(&self) -> Option<String> {
|
||||
Some(self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromBase64 for &'a str {
|
||||
/**
|
||||
* Convert any base64 encoded string (literal, `@`, `&`, or `~`)
|
||||
|
@ -13,6 +13,7 @@
|
||||
//! Hex binary-to-text encoding
|
||||
use std::fmt;
|
||||
use std::string;
|
||||
use std::error;
|
||||
|
||||
/// A trait for converting a value to hexadecimal encoding
|
||||
pub trait ToHex {
|
||||
@ -77,6 +78,20 @@ impl fmt::Show for FromHexError {
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for FromHexError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
InvalidHexCharacter(_, _) => "invalid character",
|
||||
InvalidHexLength => "invalid length",
|
||||
}
|
||||
}
|
||||
|
||||
fn detail(&self) -> Option<String> {
|
||||
Some(self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a> FromHex for &'a str {
|
||||
/**
|
||||
* Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`)
|
||||
|
@ -313,6 +313,11 @@ fn io_error_to_error(io: io::IoError) -> ParserError {
|
||||
IoError(io.kind, io.desc)
|
||||
}
|
||||
|
||||
impl std::error::Error for DecoderError {
|
||||
fn description(&self) -> &str { "decoder error" }
|
||||
fn detail(&self) -> Option<std::string::String> { Some(self.to_string()) }
|
||||
}
|
||||
|
||||
pub type EncodeResult = io::IoResult<()>;
|
||||
pub type DecodeResult<T> = Result<T, DecoderError>;
|
||||
|
||||
|
111
src/libstd/error.rs
Normal file
111
src/libstd/error.rs
Normal file
@ -0,0 +1,111 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Traits for working with Errors.
|
||||
//!
|
||||
//! # The `Error` trait
|
||||
//!
|
||||
//! `Error` is a trait representing the basic expectations for error values,
|
||||
//! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
|
||||
//! a description, but they may optionally provide additional detail and cause
|
||||
//! chain information:
|
||||
//!
|
||||
//! ```
|
||||
//! trait Error: Send {
|
||||
//! fn description(&self) -> &str;
|
||||
//!
|
||||
//! fn detail(&self) -> Option<String> { None }
|
||||
//! fn cause(&self) -> Option<&Error> { None }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The `cause` method is generally used when errors cross "abstraction
|
||||
//! boundaries", i.e. when a one module must report an error that is "caused"
|
||||
//! by an error from a lower-level module. This setup makes it possible for the
|
||||
//! high-level module to provide its own errors that do not commit to any
|
||||
//! particular implementation, but also reveal some of its implementation for
|
||||
//! debugging via `cause` chains.
|
||||
//!
|
||||
//! The trait inherits from `Any` to allow *downcasting*: converting from a
|
||||
//! trait object to a specific concrete type when applicable.
|
||||
//!
|
||||
//! # 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, although this will be the
|
||||
//! common case.
|
||||
//!
|
||||
//! The main use of this trait is in the `try!` macro, which uses it to
|
||||
//! automatically convert a given error to the error specified in a function's
|
||||
//! return type.
|
||||
//!
|
||||
//! For example,
|
||||
//!
|
||||
//! ```
|
||||
//! use std::error::FromError;
|
||||
//! use std::io::{File, IoError};
|
||||
//! use std::os::{MemoryMap, MapError};
|
||||
//! use std::path::Path;
|
||||
//!
|
||||
//! enum MyError {
|
||||
//! Io(IoError),
|
||||
//! Map(MapError)
|
||||
//! }
|
||||
//!
|
||||
//! impl FromError<IoError> for MyError {
|
||||
//! fn from_error(err: IoError) -> MyError {
|
||||
//! Io(err)
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! impl FromError<MapError> for MyError {
|
||||
//! fn from_error(err: MapError) -> MyError {
|
||||
//! Map(err)
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! #[allow(unused_variables)]
|
||||
//! fn open_and_map() -> Result<(), MyError> {
|
||||
//! let f = try!(File::open(&Path::new("foo.txt")));
|
||||
//! let m = try!(MemoryMap::new(0, &[]));
|
||||
//! // do something interesting here...
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use option::{Option, None};
|
||||
use kinds::Send;
|
||||
use string::String;
|
||||
|
||||
/// Base functionality for all errors in Rust.
|
||||
pub trait Error: Send {
|
||||
/// A short description of the error; usually a static string.
|
||||
fn description(&self) -> &str;
|
||||
|
||||
/// A detailed description of the error, usually including dynamic information.
|
||||
fn detail(&self) -> Option<String> { None }
|
||||
|
||||
/// 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<E> {
|
||||
/// Perform the conversion.
|
||||
fn from_error(err: E) -> Self;
|
||||
}
|
||||
|
||||
// Any type is convertable from itself
|
||||
impl<E> FromError<E> for E {
|
||||
fn from_error(err: E) -> E {
|
||||
err
|
||||
}
|
||||
}
|
@ -222,7 +222,9 @@ responding to errors that may occur while attempting to read the numbers.
|
||||
#![deny(unused_must_use)]
|
||||
|
||||
use char::Char;
|
||||
use clone::Clone;
|
||||
use default::Default;
|
||||
use error::{FromError, Error};
|
||||
use fmt;
|
||||
use int;
|
||||
use iter::Iterator;
|
||||
@ -433,6 +435,22 @@ impl fmt::Show for IoError {
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for IoError {
|
||||
fn description(&self) -> &str {
|
||||
self.desc
|
||||
}
|
||||
|
||||
fn detail(&self) -> Option<String> {
|
||||
self.detail.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromError<IoError> for Box<Error> {
|
||||
fn from_error(err: IoError) -> Box<Error> {
|
||||
box err
|
||||
}
|
||||
}
|
||||
|
||||
/// A list specifying general categories of I/O error.
|
||||
#[deriving(PartialEq, Eq, Clone, Show)]
|
||||
pub enum IoErrorKind {
|
||||
|
@ -218,6 +218,7 @@ pub mod time;
|
||||
|
||||
/* Common traits */
|
||||
|
||||
pub mod error;
|
||||
pub mod from_str;
|
||||
pub mod num;
|
||||
pub mod to_string;
|
||||
@ -257,6 +258,7 @@ mod std {
|
||||
pub use hash;
|
||||
|
||||
pub use comm; // used for select!()
|
||||
pub use error; // used for try!()
|
||||
pub use fmt; // used for any formatting strings
|
||||
pub use io; // used for println!()
|
||||
pub use local_data; // used for local_data_key!()
|
||||
|
@ -317,8 +317,13 @@ macro_rules! local_data_key(
|
||||
/// error if the value of the expression is `Err`. For more information, see
|
||||
/// `std::io`.
|
||||
#[macro_export]
|
||||
macro_rules! try(
|
||||
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
|
||||
macro_rules! try (
|
||||
($expr:expr) => ({
|
||||
match $expr {
|
||||
Ok(val) => val,
|
||||
Err(err) => return Err(::std::error::FromError::from_error(err))
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
/// Create a `std::vec::Vec` containing the arguments.
|
||||
|
@ -32,11 +32,13 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use clone::Clone;
|
||||
use error::{FromError, Error};
|
||||
use fmt;
|
||||
use io::{IoResult, IoError};
|
||||
use iter::Iterator;
|
||||
use libc::{c_void, c_int};
|
||||
use libc;
|
||||
use boxed::Box;
|
||||
use ops::Drop;
|
||||
use option::{Some, None, Option};
|
||||
use os;
|
||||
@ -48,6 +50,7 @@ use slice::{AsSlice, ImmutableSlice, MutableSlice, ImmutablePartialEqSlice};
|
||||
use slice::CloneableVector;
|
||||
use str::{Str, StrSlice, StrAllocating};
|
||||
use string::String;
|
||||
use to_string::ToString;
|
||||
use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
|
||||
use vec::Vec;
|
||||
|
||||
@ -1437,6 +1440,17 @@ impl fmt::Show for MapError {
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for MapError {
|
||||
fn description(&self) -> &str { "memory map error" }
|
||||
fn detail(&self) -> Option<String> { Some(self.to_string()) }
|
||||
}
|
||||
|
||||
impl FromError<MapError> for Box<Error> {
|
||||
fn from_error(err: MapError) -> Box<Error> {
|
||||
box err
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl MemoryMap {
|
||||
/// Create a new mapping with the given `options`, at least `min_len` bytes
|
||||
|
@ -48,8 +48,6 @@
|
||||
#[doc(no_inline)] pub use ops::{Index, IndexMut};
|
||||
#[doc(no_inline)] pub use ops::{Slice, SliceMut};
|
||||
#[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce};
|
||||
#[doc(no_inline)] pub use option::{Option, Some, None};
|
||||
#[doc(no_inline)] pub use result::{Result, Ok, Err};
|
||||
|
||||
// Reexported functions
|
||||
#[doc(no_inline)] pub use from_str::from_str;
|
||||
@ -73,8 +71,10 @@
|
||||
#[doc(no_inline)] pub use num::{Signed, Unsigned, Primitive, Int, Float};
|
||||
#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
|
||||
#[doc(no_inline)] pub use boxed::Box;
|
||||
#[doc(no_inline)] pub use option::{Option, Some, None};
|
||||
#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
|
||||
#[doc(no_inline)] pub use ptr::{RawPtr, RawMutPtr};
|
||||
#[doc(no_inline)] pub use result::{Result, Ok, Err};
|
||||
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
|
||||
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice};
|
||||
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrSlice};
|
||||
|
Loading…
x
Reference in New Issue
Block a user