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,
{
...
}
2
Answers
All type parameters in Rust have an implicit
Sized
bound unless they opt out — the compiler acts as ifC: Sized
was specified.Possibly this code could be generalized to allow unsized types (written
C: ?Sized
); I don’t know.Yes, but the implicit bound is on the referent,
C
.You need to define, or use an existing, type which implements the
ConnectionLike
trait and contains adyn ConnectionLike
, then pass a mutable reference to that type.The cleanest approach is to use Box itself, by having the implementation
But, only the crate defining the trait can add that
impl
.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
andC
is the generic part being matched. TheBox
type is what is substituted forC
, and it doesn’t implement this trait.A reference is indeed
Sized
, but as noted above we are matching the type&mut dyn redis::aio::ConnectionLike
against&mut C
. This results inC
beingdyn 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 implementSized
, anddyn redis::aio::ConnectionLike
does not.Possibly, but not directly. You would need to implement a type that wraps either a reference-to-
dyn ConnectionLike
or aBox<dyn ConnectionLike>
and pass that instead. Something like: