I'm sure this has been asked previously but haven't encountered a question that captures the precise scenario here. I have the following code:
let mut pool: Box<dyn redis::aio::ConnectionLike> = <...>
redis::cmd(COMMAND)
.arg(LIST)
.arg(value)
.query_async(&mut pool)
.await
.unwrap();
This returns the error:
error[E0277]: the trait bound `std::boxed::Box<dyn redis::aio::ConnectionLike>: redis::aio::ConnectionLike` is not satisfied
--> svix-server/src/queue/redis.rs:66:30
|
66 | .query_async(&mut pool)
| ----------- ^^^^^^^^^ the trait `redis::aio::ConnectionLike` is not implemented for `std::boxed::Box<dyn redis::aio::ConnectionLike>`
| |
| required by a bound introduced by this call
|
Question 1 -- Why does the error say the trait is not implemented for Box<dyn redis::aio::ConnectionLike>
? Shouldn't it at least say &Box...
?
Regardless, if I instead try to pass pool.as_mut()
to query_async
, I get this error:
error[E0277]: the size for values of type `dyn redis::aio::ConnectionLike` cannot be known at compilation time
--> svix-server/src/queue/redis.rs:66:30
|
66 | .query_async(pool.as_mut())
| ----------- ^^^^^^^^^^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn redis::aio::ConnectionLike`
Question 2 -- Why is Sized
required here? Isn't a reference in Rust always Sized
?
Question 3 -- Is there any way to to pass a dyn ConnectionLike
to this
The query_async
method, for reference looks like this:
#[inline]
#[cfg(feature = "aio")]
pub async fn query_async<C, T: FromRedisValue>(&self, con: &mut C) -> RedisResult<T>
where
C: crate::aio::ConnectionLike,
{
...
}
Question 1 -- Why does the error say the trait is not implemented for
Box<dyn redis::aio::ConnectionLike>
? Shouldn't it at least say&Box
...?
No, because the reference is not part of the generic type C
. Rust doesn't name the entire type, it only names the parts of the two types that don't match. The function accepts &mut C
and C
is the generic part being matched. The Box
type is what is substituted for C
, and it doesn't implement this trait.
Question 2 -- Why is
Sized
required here? Isn't a reference in Rust alwaysSized
?
A reference is indeed Sized
, but as noted above we are matching the type &mut dyn redis::aio::ConnectionLike
against &mut C
. This results in C
being dyn redis::aio::ConnectionLike
.
In Rust, generic types have the Sized
bound by default. You have to explicitly specify the ?Sized
bound to relax this, which the author of this function did not do. Therefore, C
must implement Sized
, and dyn redis::aio::ConnectionLike
does not.
Question 3 -- Is there any way to to pass a
dyn ConnectionLike
to this
Possibly, but not directly. You would need to implement a type that wraps either a reference-to-dyn ConnectionLike
or a Box<dyn ConnectionLike>
and pass that instead. Something like:
struct BoxedConnectionLike(Box<dyn ConnectionLike>);
impl ConnectionLike for BoxedConnectionLike {
// Implement proxy functions for the trait.
}