skip to Main Content

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


  1. Why is Sized required here?

    pub async fn query_async<C, T: FromRedisValue>(&self, con: &mut C) -> RedisResult<T>
    where
        C: crate::aio::ConnectionLike,
    

    All type parameters in Rust have an implicit Sized bound unless they opt out — the compiler acts as if C: Sized was specified.

    Possibly this code could be generalized to allow unsized types (written C: ?Sized); I don’t know.

    Isn’t a reference in Rust always Sized?

    Yes, but the implicit bound is on the referent, C.

    Is there any way to to pass a dyn ConnectionLike to this

    You need to define, or use an existing, type which implements the ConnectionLike trait and contains a dyn ConnectionLike, then pass a mutable reference to that type.

    The cleanest approach is to use Box itself, by having the implementation

    impl<C: ?Sized> ConnectionLike for Box<C>
    where
        C: ConnectionLike
    { ... }
    

    But, only the crate defining the trait can add that impl.

    Login or Signup to reply.
  2. 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 always Sized?

    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.
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search