diff --git a/README.rst b/README.rst index caa24342d9..621217f888 100644 --- a/README.rst +++ b/README.rst @@ -92,10 +92,6 @@ called `hashmap_core` is pulled in (only in `no_std` builds). This is mostly the same as `std::collections::HashMap`, except that it doesn't have DOS protection. Just something to think about. -Lastly, to support `std::error`, which isn't is `std` or `alloc` for -an inexplicable reason, the `error_core` crate is also used in `no_std` builds. -You might need it, as well, when interfacing with `CtonError`. - Building the documentation -------------------------- diff --git a/lib/cretonne/Cargo.toml b/lib/cretonne/Cargo.toml index c1c666fa77..09d3a7dd7b 100644 --- a/lib/cretonne/Cargo.toml +++ b/lib/cretonne/Cargo.toml @@ -17,19 +17,17 @@ name = "cretonne" # Please don't add any unless they are essential to the task of creating binary # machine code. Integration tests that need external dependencies can be # accomodated in `tests`. +failure = { version = "0.1.1", default-features = false, features = ["derive"] } +failure_derive = { version = "0.1.1", default-features = false } [dependencies.hashmap_core] version = "0.1.1" optional = true -[dependencies.error_core] -version = "0.1.0" -optional = true - [features] # The "std" feature enables use of libstd. The "no_std" feature enables use # of some minimal std-like replacement libraries. At least one of these two # features to be enabled. default = ["std"] std = [] -no_std = ["hashmap_core", "error_core"] +no_std = ["hashmap_core"] diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index 0952969bb1..ddb391852d 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -8,11 +8,12 @@ // Include the `hashmap_core` crate if no_std #[cfg(feature = "no_std")] extern crate hashmap_core; -#[cfg(feature = "no_std")] -extern crate error_core; #[cfg(not(feature = "std"))] #[macro_use] extern crate alloc; +extern crate failure; +#[macro_use] +extern crate failure_derive; pub use context::Context; pub use legalizer::legalize_function; @@ -69,7 +70,4 @@ mod std { pub use hashmap_core::map as hash_map; pub use alloc::BTreeSet; } - pub mod error { - pub use error_core::Error; - } } diff --git a/lib/cretonne/src/result.rs b/lib/cretonne/src/result.rs index 387eaa9a2a..2b89c774d3 100644 --- a/lib/cretonne/src/result.rs +++ b/lib/cretonne/src/result.rs @@ -1,25 +1,28 @@ //! Result and error types representing the outcome of compiling a function. use verifier; -use std::error::Error as StdError; -use std::fmt; /// A compilation error. /// /// When Cretonne fails to compile a function, it will return one of these error codes. -#[derive(Debug, PartialEq, Eq)] +#[derive(Fail, Debug, PartialEq, Eq)] pub enum CtonError { /// The input is invalid. /// /// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly /// code. This should never happen for validated WebAssembly code. + #[fail(display = "Invalid input code")] InvalidInput, /// An IL verifier error. /// /// This always represents a bug, either in the code that generated IL for Cretonne, or a bug /// in Cretonne itself. - Verifier(verifier::Error), + #[fail(display = "Verifier error: {}", _0)] + Verifier( + #[cause] + verifier::Error + ), /// An implementation limit was exceeded. /// @@ -27,48 +30,20 @@ pub enum CtonError { /// limits][limits] that cause compilation to fail when they are exceeded. /// /// [limits]: http://cretonne.readthedocs.io/en/latest/langref.html#implementation-limits + #[fail(display = "Implementation limit exceeded")] ImplLimitExceeded, /// The code size for the function is too large. /// /// Different target ISAs may impose a limit on the size of a compiled function. If that limit /// is exceeded, compilation fails. + #[fail(display = "Code for function is too large")] CodeTooLarge, } /// A Cretonne compilation result. pub type CtonResult = Result<(), CtonError>; -impl fmt::Display for CtonError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - CtonError::Verifier(ref e) => write!(f, "Verifier error: {}", e), - CtonError::InvalidInput | - CtonError::ImplLimitExceeded | - CtonError::CodeTooLarge => f.write_str(self.description()), - } - } -} - -impl StdError for CtonError { - fn description(&self) -> &str { - match *self { - CtonError::InvalidInput => "Invalid input code", - CtonError::Verifier(ref e) => &e.message, - CtonError::ImplLimitExceeded => "Implementation limit exceeded", - CtonError::CodeTooLarge => "Code for function is too large", - } - } - fn cause(&self) -> Option<&StdError> { - match *self { - CtonError::Verifier(ref e) => Some(e), - CtonError::InvalidInput | - CtonError::ImplLimitExceeded | - CtonError::CodeTooLarge => None, - } - } -} - impl From for CtonError { fn from(e: verifier::Error) -> CtonError { CtonError::Verifier(e) diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index 117de2f38b..821bc3d623 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -70,7 +70,6 @@ use self::flags::verify_flags; use settings::{Flags, FlagsOrIsa}; use std::cmp::Ordering; use std::collections::BTreeSet; -use std::error as std_error; use std::fmt::{self, Display, Formatter, Write}; use std::result; use std::vec::Vec; @@ -104,7 +103,7 @@ mod liveness; mod locations; /// A verifier error. -#[derive(Debug, PartialEq, Eq)] +#[derive(Fail, Debug, PartialEq, Eq)] pub struct Error { /// The entity causing the verifier error. pub location: AnyEntity, @@ -118,12 +117,6 @@ impl Display for Error { } } -impl std_error::Error for Error { - fn description(&self) -> &str { - &self.message - } -} - /// Verifier result. pub type Result = result::Result<(), Error>; diff --git a/lib/filecheck/Cargo.toml b/lib/filecheck/Cargo.toml index aec22b0f51..b29eaa5c53 100644 --- a/lib/filecheck/Cargo.toml +++ b/lib/filecheck/Cargo.toml @@ -12,3 +12,5 @@ name = "filecheck" [dependencies] regex = "0.2.6" +failure = "0.1.1" +failure_derive = "0.1.1" diff --git a/lib/filecheck/src/error.rs b/lib/filecheck/src/error.rs index 5580cc4c3c..af9657cdcc 100644 --- a/lib/filecheck/src/error.rs +++ b/lib/filecheck/src/error.rs @@ -1,21 +1,21 @@ use std::result; use std::convert::From; -use std::error::Error as StdError; -use std::fmt; use regex; /// A result from the filecheck library. pub type Result = result::Result; /// A filecheck error. -#[derive(Debug)] +#[derive(Fail, Debug)] pub enum Error { /// A syntax error in a check line. + #[fail(display = "{}", _0)] Syntax(String), /// A check refers to an undefined variable. /// /// The pattern contains `$foo` where the `foo` variable has not yet been defined. /// Use `$$` to match a literal dollar sign. + #[fail(display = "{}", _0)] UndefVariable(String), /// A pattern contains a back-reference to a variable that was defined in the same pattern. /// @@ -26,40 +26,19 @@ pub enum Error { /// check: Hello $(world=[^ ]*) /// sameln: $world /// ``` + #[fail(display = "{}", _0)] Backref(String), /// A pattern contains multiple definitions of the same variable. + #[fail(display = "{}", _0)] DuplicateDef(String), /// An error in a regular expression. /// /// Use `cause()` to get the underlying `Regex` library error. - Regex(regex::Error), -} - -impl StdError for Error { - fn description(&self) -> &str { - use Error::*; - match *self { - Syntax(ref s) | - UndefVariable(ref s) | - Backref(ref s) | - DuplicateDef(ref s) => s, - Regex(ref err) => err.description(), - } - } - - fn cause(&self) -> Option<&StdError> { - use Error::*; - match *self { - Regex(ref err) => Some(err), - _ => None, - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{}", self.description()) - } + #[fail(display = "{}", _0)] + Regex( + #[cause] + regex::Error + ), } impl From for Error { diff --git a/lib/filecheck/src/lib.rs b/lib/filecheck/src/lib.rs index a189acebdb..b29377f9ac 100644 --- a/lib/filecheck/src/lib.rs +++ b/lib/filecheck/src/lib.rs @@ -243,6 +243,9 @@ pub use variable::{VariableMap, Value, NO_VARIABLES}; pub use checker::{Checker, CheckerBuilder}; extern crate regex; +extern crate failure; +#[macro_use] +extern crate failure_derive; mod error; mod variable; diff --git a/lib/wasm/Cargo.toml b/lib/wasm/Cargo.toml index 3bd2b36aa8..7954ebc209 100644 --- a/lib/wasm/Cargo.toml +++ b/lib/wasm/Cargo.toml @@ -19,14 +19,10 @@ cretonne-frontend = { path = "../frontend", version = "0.1.0", default_features version = "0.1.1" optional = true -[dependencies.error_core] -version = "0.1.0" -optional = true - [dev-dependencies] tempdir = "0.3.5" [features] default = ["std"] std = ["cretonne/std", "cretonne-frontend/std"] -no_std = ["hashmap_core", "error_core", "cretonne/no_std", "cretonne-frontend/no_std"] +no_std = ["hashmap_core", "cretonne/no_std", "cretonne-frontend/no_std"] diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index de941f3b9a..102e83ef79 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -9,7 +9,6 @@ use cretonne::ir::types::*; use cretonne::cursor::FuncCursor; use cretonne::settings; use wasmparser; -use std::error::Error; use std::vec::Vec; use std::string::String; @@ -387,7 +386,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { let reader = wasmparser::BinaryReader::new(body_bytes); self.trans .translate_from_reader(reader, &mut func, &mut func_environ) - .map_err(|e| String::from(e.description()))?; + .map_err(|e| format!("{}", e))?; func }; self.func_bytecode_sizes.push(body_bytes.len()); diff --git a/lib/wasm/src/lib.rs b/lib/wasm/src/lib.rs index 76e69887d9..ae5c99e05e 100644 --- a/lib/wasm/src/lib.rs +++ b/lib/wasm/src/lib.rs @@ -20,8 +20,6 @@ extern crate alloc; #[cfg(feature = "no_std")] extern crate hashmap_core; -#[cfg(feature = "no_std")] -extern crate error_core; extern crate wasmparser; extern crate cton_frontend; @@ -50,7 +48,4 @@ mod std { pub mod collections { pub use hashmap_core::{HashMap, map as hash_map}; } - pub mod error { - pub use error_core::Error; - } }