diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-04-01 15:25:47 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-04-01 15:25:47 -0400 |
| commit | 19d3dab31b1fca3abc3ba00173b9148bd70d24b0 (patch) | |
| tree | 1be2f77b15b0c96a7021aa4fe360390f173c4284 | |
| parent | 15b58fedcacba7d10a9f7d460a83da645a09ad3e (diff) | |
| download | rust-19d3dab31b1fca3abc3ba00173b9148bd70d24b0.tar.gz rust-19d3dab31b1fca3abc3ba00173b9148bd70d24b0.zip | |
Collect the definition of the `Error` trait into `libstd` for now. This
sidesteps a coherence difficulty where `liballoc` had to prove that `&str: !Error`, which didn't involve any local types.
| -rw-r--r-- | src/liballoc/boxed.rs | 53 | ||||
| -rw-r--r-- | src/libcollections/string.rs | 11 | ||||
| -rw-r--r-- | src/libcore/error.rs | 56 | ||||
| -rw-r--r-- | src/libcore/lib.rs | 1 | ||||
| -rw-r--r-- | src/libcore/num/mod.rs | 41 | ||||
| -rw-r--r-- | src/libcore/str/mod.rs | 16 | ||||
| -rw-r--r-- | src/libstd/error.rs | 152 | ||||
| -rw-r--r-- | src/libstd/lib.rs | 2 |
8 files changed, 175 insertions, 157 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c4541e34cdb..bbf5d7a6042 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<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> { #[stable(feature = "rust1", since = "1.0.0")] impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {} -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> { - fn from(err: E) -> Box<Error + 'a> { - Box::new(err) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, E: Error + Send + 'a> From<E> for Box<Error + Send + 'a> { - fn from(err: E) -> Box<Error + Send + 'a> { - Box::new(err) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> { - fn from(err: &'b str) -> Box<Error + Send + 'a> { - #[derive(Debug)] - struct StringError(Box<str>); - 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<str>` 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 d8d7ad9887a..7a772532091 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}; @@ -724,11 +723,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 { fmt::Display::fmt("invalid utf-16: lone surrogate found", f) @@ -736,11 +730,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<char> for String { fn from_iter<I: IntoIterator<Item=char>>(iter: I) -> String { let mut buf = String::new(); diff --git a/src/libcore/error.rs b/src/libcore/error.rs deleted file mode 100644 index 24035b7d9a8..00000000000 --- 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 <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 (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 3a9af50fefb..2189e2c3ad1 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 a4829ed96b3..7daa1a9f420 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 934c4515614..4c366d32718 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 */ @@ -242,16 +236,6 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str { } #[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 { match *self { diff --git a/src/libstd/error.rs b/src/libstd/error.rs new file mode 100644 index 00000000000..150ffcdd77a --- /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 <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 (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<E> for Box<Error + 'a> { + fn from(err: E) -> Box<Error + 'a> { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, E: Error + Send + 'a> From<E> for Box<Error + Send + 'a> { + fn from(err: E) -> Box<Error + Send + 'a> { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> { + fn from(err: &'b str) -> Box<Error + Send + 'a> { + #[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 41ac3d60df5..807f0c5753e 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; |
