Add CargoError::with_cause
authorYehuda Katz <wycats@gmail.com>
Thu, 19 Jun 2014 18:49:50 +0000 (11:49 -0700)
committerYehuda Katz <wycats@gmail.com>
Thu, 19 Jun 2014 18:49:50 +0000 (11:49 -0700)
This allows concrete implementations with a `cause` field to have a
better implementation than converting the entire original error into a
concrete representation.

src/cargo/util/errors.rs
src/cargo/util/mod.rs
src/cargo/util/result.rs

index dc5367550cad63c3c3853c747c41de0bd26e9e11..f23a329a4531c6afd2dd9172fe17a646a987d6d3 100644 (file)
@@ -28,6 +28,12 @@ pub trait CargoError {
         }
     }
 
+    fn with_cause<E: CargoError>(self, cause: E) -> Box<CargoError> {
+        let mut concrete = self.concrete();
+        concrete.cause = Some(cause.box_error());
+        box concrete as Box<CargoError>
+    }
+
     fn mark_human(self) -> Box<CargoError> {
         let mut concrete = self.concrete();
         concrete.is_human = true;
@@ -103,9 +109,7 @@ impl<T, E: CargoError> BoxError<T> for Result<T, E> {
 impl<T, E: CargoError> ChainError<T> for Result<T, E> {
     fn chain_error<E: CargoError>(self, callback: || -> E) -> CargoResult<T>  {
         self.map_err(|err| {
-            let mut update = callback().concrete();
-            update.cause = Some(err.box_error());
-            box update as Box<CargoError>
+            callback().with_cause(err)
         })
     }
 }
@@ -159,6 +163,11 @@ impl CargoError for ProcessError {
     fn cause<'a>(&'a self) -> Option<&'a CargoError> {
         self.cause.as_ref().map(|c| { let err: &CargoError = *c; err })
     }
+
+    fn with_cause<E: CargoError>(mut self, err: E) -> Box<CargoError> {
+        self.cause = Some(err.box_error());
+        box self as Box<CargoError>
+    }
 }
 
 pub struct ConcreteCargoError {
@@ -187,6 +196,11 @@ impl CargoError for ConcreteCargoError {
         self.cause.as_ref().map(|c| { let err: &CargoError = *c; err })
     }
 
+    fn with_cause<E: CargoError>(mut self, err: E) -> Box<CargoError> {
+        self.cause = Some(err.box_error());
+        box self as Box<CargoError>
+    }
+
     fn is_human(&self) -> bool {
         self.is_human
     }
@@ -215,7 +229,7 @@ impl CliError {
         let error = if error.is_human() {
             error
         } else {
-            chain(error, human("An unknown error occurred"))
+            human("An unknown error occurred").with_cause(error)
         };
 
         CliError { error: error, exit_code: code }
@@ -259,9 +273,3 @@ pub fn human<S: Str>(error: S) -> Box<CargoError> {
         is_human: true
     } as Box<CargoError>
 }
-
-pub fn chain<E: CargoError>(original: Box<CargoError>, update: E) -> Box<CargoError> {
-    let mut concrete = update.concrete();
-    concrete.cause = Some(original);
-    box concrete as Box<CargoError>
-}
index e88e9bfdc4643b905d88bc5858883e0e98bdf852..918f90a413d30393f35fc443be005237faecdcfd 100644 (file)
@@ -2,7 +2,7 @@ pub use self::config::Config;
 pub use self::process_builder::{process,ProcessBuilder};
 pub use self::result::{Wrap, Require};
 pub use self::errors::{CargoResult, CargoError, BoxError, ChainError, CliResult, CliError, ProcessError};
-pub use self::errors::{process_error, internal_error, internal, human, chain};
+pub use self::errors::{process_error, internal_error, internal, human};
 pub use self::paths::realpath;
 
 pub mod graph;
index 8e0b7b563ba821eaa529484dba71b6ccd11c6bab..d47ca51e87f7842bbc816bbb2677e797eb71ab0b 100644 (file)
@@ -1,4 +1,4 @@
-use util::errors::{CargoResult, CargoError, chain};
+use util::errors::{CargoResult, CargoError};
 
 pub trait Wrap {
     fn wrap<E: CargoError>(self, error: E) -> Self;
@@ -8,7 +8,7 @@ impl<T> Wrap for Result<T, Box<CargoError>> {
     fn wrap<E: CargoError>(self, error: E) -> CargoResult<T> {
         match self {
             Ok(x) => Ok(x),
-            Err(e) => Err(chain(e, error))
+            Err(e) => Err(error.with_cause(e))
         }
     }
 }