Skip to content

Commit 1759db6

Browse files
committed
Properly downcast swirl::EnqueueError
The return type of `enqueue` is `Box<dyn Error + Send + Sync>`. Unfortunately, `Box<dyn Error>` does not implement `Error`, so our from impl doesn't apply. We're also not able to add an explicit `From` impl either (which is odd, coherence rules should let us write that impl). I've opted to just add an explicit converstion function that we can use here. We should probably check that there's nowhere else we're passing an error object to `human` or `internal`, but that will come in a separate PR
1 parent 52862fa commit 1759db6

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

src/git.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use url::Url;
1212
use crate::background_jobs::Environment;
1313
use crate::models::{DependencyKind, Version};
1414
use crate::schema::versions;
15-
use crate::util::errors::{internal, std_error_no_send, CargoResult};
15+
use crate::util::errors::{std_error_no_send, CargoError, CargoResult};
1616

1717
#[derive(Serialize, Deserialize, Debug)]
1818
pub struct Crate {
@@ -159,7 +159,9 @@ impl Job for AddCrate {
159159
}
160160

161161
pub fn add_crate(conn: &PgConnection, krate: Crate) -> CargoResult<()> {
162-
AddCrate { krate }.enqueue(conn).map_err(|e| internal(&e))
162+
AddCrate { krate }
163+
.enqueue(conn)
164+
.map_err(|e| CargoError::from_std_error(e))
163165
}
164166

165167
#[derive(Serialize, Deserialize)]
@@ -239,5 +241,5 @@ pub fn yank(conn: &PgConnection, krate: String, version: Version, yanked: bool)
239241
yanked,
240242
}
241243
.enqueue(conn)
242-
.map_err(|e| internal(&e))
244+
.map_err(|e| CargoError::from_std_error(e))
243245
}

src/util/errors.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ impl dyn CargoError {
4949
pub fn is<T: Any>(&self) -> bool {
5050
self.get_type_id() == TypeId::of::<T>()
5151
}
52+
53+
pub fn from_std_error(err: Box<dyn Error + Send>) -> Box<dyn CargoError> {
54+
Self::try_convert(&*err).unwrap_or_else(|| internal(&err))
55+
}
56+
57+
fn try_convert(err: &(dyn Error + Send + 'static)) -> Option<Box<Self>> {
58+
match err.downcast_ref() {
59+
Some(DieselError::NotFound) => Some(Box::new(NotFound)),
60+
Some(DieselError::DatabaseError(_, info))
61+
if info.message().ends_with("read-only transaction") =>
62+
{
63+
Some(Box::new(ReadOnlyMode))
64+
}
65+
_ => None,
66+
}
67+
}
5268
}
5369

5470
impl CargoError for Box<dyn CargoError> {
@@ -155,17 +171,9 @@ impl<E: Error + Send + 'static> CargoError for E {
155171
}
156172
}
157173

158-
impl<E: Any + Error + Send + 'static> From<E> for Box<dyn CargoError> {
174+
impl<E: Error + Send + 'static> From<E> for Box<dyn CargoError> {
159175
fn from(err: E) -> Box<dyn CargoError> {
160-
match Any::downcast_ref::<DieselError>(&err) {
161-
Some(DieselError::NotFound) => Box::new(NotFound),
162-
Some(DieselError::DatabaseError(_, info))
163-
if info.message().ends_with("read-only transaction") =>
164-
{
165-
Box::new(ReadOnlyMode)
166-
}
167-
_ => Box::new(err),
168-
}
176+
CargoError::try_convert(&err).unwrap_or_else(|| Box::new(err))
169177
}
170178
}
171179
// =============================================================================

0 commit comments

Comments
 (0)