diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c4541e34cdb35..bbf5d7a6042f2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -51,15 +51,12 @@ use core::prelude::*; use core::any::Any; use core::cmp::Ordering; use core::default::Default; -use core::error::Error; use core::fmt; use core::hash::{self, Hash}; use core::mem; use core::ops::{Deref, DerefMut}; -use core::ptr::{self, Unique}; -use core::raw::{TraitObject, Slice}; - -use heap; +use core::ptr::{Unique}; +use core::raw::{TraitObject}; /// A value that represents the heap. This is the default place that the `box` /// keyword allocates into when no place is supplied. @@ -303,49 +300,3 @@ impl DoubleEndedIterator for Box { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Box {} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From for Box { - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + 'a> From for Box { - fn from(err: E) -> Box { - Box::new(err) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box { - fn from(err: &'b str) -> Box { - #[derive(Debug)] - struct StringError(Box); - impl Error for StringError { - fn description(&self) -> &str { &self.0 } - } - impl fmt::Display for StringError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } - } - - // Unfortunately `String` is located in libcollections, so we construct - // a `Box` manually here. - unsafe { - let alloc = if err.len() == 0 { - 0 as *mut u8 - } else { - let ptr = heap::allocate(err.len(), 1); - if ptr.is_null() { ::oom(); } - ptr as *mut u8 - }; - ptr::copy(err.as_bytes().as_ptr(), alloc, err.len()); - Box::new(StringError(mem::transmute(Slice { - data: alloc, - len: err.len(), - }))) - } - } -} diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index d8d7ad9887a8c..7a7725320914f 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -17,7 +17,6 @@ use core::prelude::*; use core::default::Default; -use core::error::Error; use core::fmt; use core::hash; use core::iter::{IntoIterator, FromIterator}; @@ -723,11 +722,6 @@ impl fmt::Display for FromUtf8Error { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf8Error { - fn description(&self) -> &str { "invalid utf-8" } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for FromUtf16Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -735,11 +729,6 @@ impl fmt::Display for FromUtf16Error { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for FromUtf16Error { - fn description(&self) -> &str { "invalid utf-16" } -} - #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for String { fn from_iter>(iter: I) -> String { diff --git a/src/libcore/error.rs b/src/libcore/error.rs deleted file mode 100644 index 24035b7d9a83b..0000000000000 --- a/src/libcore/error.rs +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -//! 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`. At a minimum, errors must provide -//! a description, but they may optionally provide additional detail (via -//! `Display`) and cause chain information: -//! -//! ``` -//! use std::fmt::Display; -//! -//! trait Error: Display { -//! fn description(&self) -> &str; -//! -//! 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. - -#![stable(feature = "rust1", since = "1.0.0")] - -use prelude::*; -use fmt::{Debug, Display}; - -/// Base functionality for all errors in Rust. -#[stable(feature = "rust1", since = "1.0.0")] -pub trait Error: Debug + Display { - /// A short description of the error. - /// - /// The description should not contain newlines or sentence-ending - /// punctuation, to facilitate embedding in larger user-facing - /// strings. - #[stable(feature = "rust1", since = "1.0.0")] - fn description(&self) -> &str; - - /// The lower-level cause of this error, if any. - #[stable(feature = "rust1", since = "1.0.0")] - fn cause(&self) -> Option<&Error> { None } -} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 3a9af50fefbc7..2189e2c3ad1ba 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -147,7 +147,6 @@ pub mod slice; pub mod str; pub mod hash; pub mod fmt; -pub mod error; #[doc(primitive = "bool")] mod bool { diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a4829ed96b353..7daa1a9f420b6 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -20,7 +20,6 @@ use self::wrapping::{OverflowingOps, WrappingOps}; use char::CharExt; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord}; -use error::Error; use fmt; use intrinsics; use iter::Iterator; @@ -2948,16 +2947,9 @@ enum IntErrorKind { Underflow, } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for ParseIntError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseIntError { - fn description(&self) -> &str { +impl ParseIntError { + #[unstable(feature = "core", reason = "available through Error trait")] + pub fn description(&self) -> &str { match self.kind { IntErrorKind::Empty => "cannot parse integer from empty string", IntErrorKind::InvalidDigit => "invalid digit found in string", @@ -2967,6 +2959,13 @@ impl Error for ParseIntError { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseIntError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + /// An error which can be returned when parsing a float. #[derive(Debug, Clone, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] @@ -2978,19 +2977,19 @@ enum FloatErrorKind { Invalid, } -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Display for ParseFloatError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseFloatError { - fn description(&self) -> &str { +impl ParseFloatError { + #[unstable(feature = "core", reason = "available through Error trait")] + pub fn description(&self) -> &str { match self.kind { FloatErrorKind::Empty => "cannot parse float from empty string", FloatErrorKind::Invalid => "invalid float literal", } } } + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for ParseFloatError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 934c4515614ef..4c366d327187e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -22,7 +22,6 @@ use char::CharExt; use clone::Clone; use cmp::{self, Eq}; use default::Default; -use error::Error; use fmt; use iter::ExactSizeIterator; use iter::{Map, Iterator, DoubleEndedIterator}; @@ -192,11 +191,6 @@ impl fmt::Display for ParseBoolError { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for ParseBoolError { - fn description(&self) -> &str { "failed to parse bool" } -} - /* Section: Creating a string */ @@ -241,16 +235,6 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str { mem::transmute(v) } -#[stable(feature = "rust1", since = "1.0.0")] -impl Error for Utf8Error { - fn description(&self) -> &str { - match *self { - Utf8Error::TooShort => "invalid utf-8: not enough bytes", - Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Utf8Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libstd/error.rs b/src/libstd/error.rs new file mode 100644 index 0000000000000..150ffcdd77a9f --- /dev/null +++ b/src/libstd/error.rs @@ -0,0 +1,152 @@ +// 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. + +//! 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`. At a minimum, errors must provide +//! a description, but they may optionally provide additional detail (via +//! `Display`) and cause chain information: +//! +//! ``` +//! use std::fmt::Display; +//! +//! trait Error: Display { +//! fn description(&self) -> &str; +//! +//! 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. + +#![stable(feature = "rust1", since = "1.0.0")] + +// A note about crates and the facade: +// +// Originally, the `Error` trait was defined in libcore, and the impls +// were scattered about. However, coherence objected to this +// arrangement, because to create the blanket impls for `Box` required +// knowing that `&str: !Error`, and we have no means to deal with that +// sort of conflict just now. Therefore, for the time being, we have +// moved the `Error` trait into libstd. As we evolve a sol'n to the +// coherence challenge (e.g., specialization, neg impls, etc) we can +// reconsider what crate these items belong in. + +use boxed::Box; +use convert::From; +use fmt::{self, Debug, Display}; +use marker::Send; +use num; +use option::Option; +use option::Option::None; +use str; +use string::{self, String}; + +/// Base functionality for all errors in Rust. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Error: Debug + Display { + /// A short description of the error. + /// + /// The description should not contain newlines or sentence-ending + /// punctuation, to facilitate embedding in larger user-facing + /// strings. + #[stable(feature = "rust1", since = "1.0.0")] + fn description(&self) -> &str; + + /// The lower-level cause of this error, if any. + #[stable(feature = "rust1", since = "1.0.0")] + fn cause(&self) -> Option<&Error> { None } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + 'a> From for Box { + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b> From<&'b str> for Box { + fn from(err: &'b str) -> Box { + #[derive(Debug)] + struct StringError(String); + + impl Error for StringError { + fn description(&self) -> &str { &self.0 } + } + + impl Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(&self.0, f) + } + } + + Box::new(StringError(String::from_str(err))) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for str::ParseBoolError { + fn description(&self) -> &str { "failed to parse bool" } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for str::Utf8Error { + fn description(&self) -> &str { + match *self { + str::Utf8Error::TooShort => "invalid utf-8: not enough bytes", + str::Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents", + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for num::ParseIntError { + fn description(&self) -> &str { + self.description() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for num::ParseFloatError { + fn description(&self) -> &str { + self.description() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for string::FromUtf8Error { + fn description(&self) -> &str { + "invalid utf-8" + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for string::FromUtf16Error { + fn description(&self) -> &str { + "invalid utf-16" + } +} + diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 41ac3d60df558..807f0c5753e6b 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -183,7 +183,7 @@ pub use core::raw; pub use core::simd; pub use core::result; pub use core::option; -pub use core::error; +pub mod error; #[cfg(not(test))] pub use alloc::boxed; pub use alloc::rc;