Wrap mlua errors as Error::Lua instead of dyn Error
The previous commit widened JobFailed::source to a dyn Error so both
Lua and Rust run-fns could land there, but that erased the type and
broke pattern-matching. Add an Error::Lua variant for mlua errors and
restore JobFailed::source to Box<Error>.
Assisted-by: Claude Opus 4.7 via Claude Code
diff --git a/src/ci/run.rs b/src/ci/run.rs
index 057f211..ca7caf3 100644
--- a/src/ci/run.rs
+++ b/src/ci/run.rs
@@ -286,8 +286,7 @@ impl Run {
self.transition(RunState::Active)?;
- let mut failed_job: Option<(String, Box<dyn std::error::Error + Send + Sync + 'static>)> =
- None;
+ let mut failed_job: Option<(String, Error)> = None;
for job_id in runtime.topo_order() {
let run_fn = runtime
.job(job_id)
@@ -296,15 +295,12 @@ impl Run {
.clone();
runtime.enter_job(job_id);
- let result: std::result::Result<
- (),
- Box<dyn std::error::Error + Send + Sync + 'static>,
- > = match run_fn {
+ let result: Result<()> = match run_fn {
RunFn::Lua(f) => f
.call::<mlua::Value>(rt_value.clone())
.map(|_| ())
- .map_err(|e| Box::new(e) as _),
- RunFn::Rust(f) => f(&runtime).map_err(|e| Box::new(e) as _),
+ .map_err(|e| Error::Lua(Box::new(e))),
+ RunFn::Rust(f) => f(&runtime),
};
runtime.leave_job();
@@ -323,7 +319,10 @@ impl Run {
if let Some((job, source)) = failed_job {
self.transition(RunState::Failed)?;
- return Err(Error::JobFailed { job, source });
+ return Err(Error::JobFailed {
+ job,
+ source: Box::new(source),
+ });
}
self.transition(RunState::Complete)?;
diff --git a/src/error.rs b/src/error.rs
index 0437018..741ef14 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -30,16 +30,14 @@ pub enum Error {
#[error("invalid run transition: {from:?} -> {to:?}")]
InvalidTransition { from: RunState, to: RunState },
+ #[error(transparent)]
+ Lua(Box<mlua::Error>),
+
#[error("job '{job}' failed")]
JobFailed {
job: String,
- // Boxed `dyn Error` rather than a concrete type so both Lua
- // and Rust run-fns can land here without an extra wrapper —
- // an mlua::Error from `RunFn::Lua`, a crate::Error from
- // `RunFn::Rust`, both walk through `display_chain` the same
- // way.
#[source]
- source: Box<dyn std::error::Error + Send + Sync + 'static>,
+ source: Box<Error>,
},
#[error("git error: {0}")]