about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-04-01 15:25:47 -0400
committerNiko Matsakis <niko@alum.mit.edu>2015-04-01 15:25:47 -0400
commit19d3dab31b1fca3abc3ba00173b9148bd70d24b0 (patch)
tree1be2f77b15b0c96a7021aa4fe360390f173c4284
parent15b58fedcacba7d10a9f7d460a83da645a09ad3e (diff)
downloadrust-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.rs53
-rw-r--r--src/libcollections/string.rs11
-rw-r--r--src/libcore/error.rs56
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/num/mod.rs41
-rw-r--r--src/libcore/str/mod.rs16
-rw-r--r--src/libstd/error.rs152
-rw-r--r--src/libstd/lib.rs2
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;