为什么不能将 Box<dyn Trait> 传递给以 &mut Trait 作为参数的函数
Why can't Box<dyn Trait> be pased to a function with &mut Trait as parameter
我确定之前已经有人问过这个问题,但还没有遇到能准确描述此处情况的问题。我有以下代码:
let mut pool: Box<dyn redis::aio::ConnectionLike> = <...>
redis::cmd(COMMAND)
.arg(LIST)
.arg(value)
.query_async(&mut pool)
.await
.unwrap();
这个returns错误:
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
|
问题 1 -- 为什么错误提示未为 Box<dyn redis::aio::ConnectionLike>
实现特征?至少不应该说 &Box...
吗?
无论如何,如果我改为尝试将 pool.as_mut()
传递给 query_async
,我会收到此错误:
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`
问题 2 -- 为什么这里需要 Sized
? Rust 中的引用不总是 Sized
吗?
问题 3 -- 有什么方法可以将 dyn ConnectionLike
传递给这个
query_async
方法,参考如下:
#[inline]
#[cfg(feature = "aio")]
pub async fn query_async<C, T: FromRedisValue>(&self, con: &mut C) -> RedisResult<T>
where
C: crate::aio::ConnectionLike,
{
...
}
Why is Sized required here?
pub async fn query_async<C, T: FromRedisValue>(&self, con: &mut C) -> RedisResult<T>
where
C: crate::aio::ConnectionLike,
Rust 中的所有类型参数都有一个隐式的 Sized
绑定,除非它们选择退出 — 编译器就像指定了 C: Sized
一样。
可能可以将此代码泛化为允许未确定大小的类型(写作 C: ?Sized
);我不知道。
Isn't a reference in Rust always Sized?
是的,但隐式绑定在所指对象上,C
。
Is there any way to to pass a dyn ConnectionLike to this
您需要定义或使用现有类型,该类型实现了 ConnectionLike
特征并且 包含 和 dyn ConnectionLike
,然后将可变引用传递给那种。
最干净的方法是使用 Box 本身,通过实现
impl<C: ?Sized> ConnectionLike for Box<C>
where
C: ConnectionLike
{ ... }
但是,只有定义特征的箱子才能添加 impl
。
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
...?
不,因为引用不是泛型类型的一部分C
。 Rust 不命名 entire 类型,它只命名两个类型不匹配的部分。该函数接受 &mut C
并且 C
是匹配的通用部分。 Box
类型是 C
的替代类型,它不实现此特征。
Question 2 -- Why is Sized
required here? Isn't a reference in Rust always Sized
?
引用确实是 Sized
,但如上所述,我们正在将类型 &mut dyn redis::aio::ConnectionLike
与 &mut C
进行匹配。这导致 C
为 dyn redis::aio::ConnectionLike
。
在 Rust 中,泛型类型默认有 Sized
绑定 。 你必须显式指定 ?Sized
绑定来放宽这个,作者这个功能没做。因此,C
必须实现Sized
,而dyn redis::aio::ConnectionLike
则不需要。
Question 3 -- Is there any way to to pass a dyn ConnectionLike
to this
可能,但不是直接的。您需要实现一种包装 reference-to-dyn ConnectionLike
或 Box<dyn ConnectionLike>
的类型,然后传递它。类似于:
struct BoxedConnectionLike(Box<dyn ConnectionLike>);
impl ConnectionLike for BoxedConnectionLike {
// Implement proxy functions for the trait.
}
我确定之前已经有人问过这个问题,但还没有遇到能准确描述此处情况的问题。我有以下代码:
let mut pool: Box<dyn redis::aio::ConnectionLike> = <...>
redis::cmd(COMMAND)
.arg(LIST)
.arg(value)
.query_async(&mut pool)
.await
.unwrap();
这个returns错误:
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
|
问题 1 -- 为什么错误提示未为 Box<dyn redis::aio::ConnectionLike>
实现特征?至少不应该说 &Box...
吗?
无论如何,如果我改为尝试将 pool.as_mut()
传递给 query_async
,我会收到此错误:
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`
问题 2 -- 为什么这里需要 Sized
? Rust 中的引用不总是 Sized
吗?
问题 3 -- 有什么方法可以将 dyn ConnectionLike
传递给这个
query_async
方法,参考如下:
#[inline]
#[cfg(feature = "aio")]
pub async fn query_async<C, T: FromRedisValue>(&self, con: &mut C) -> RedisResult<T>
where
C: crate::aio::ConnectionLike,
{
...
}
Why is Sized required here?
pub async fn query_async<C, T: FromRedisValue>(&self, con: &mut C) -> RedisResult<T>
where
C: crate::aio::ConnectionLike,
Rust 中的所有类型参数都有一个隐式的 Sized
绑定,除非它们选择退出 — 编译器就像指定了 C: Sized
一样。
可能可以将此代码泛化为允许未确定大小的类型(写作 C: ?Sized
);我不知道。
Isn't a reference in Rust always Sized?
是的,但隐式绑定在所指对象上,C
。
Is there any way to to pass a dyn ConnectionLike to this
您需要定义或使用现有类型,该类型实现了 ConnectionLike
特征并且 包含 和 dyn ConnectionLike
,然后将可变引用传递给那种。
最干净的方法是使用 Box 本身,通过实现
impl<C: ?Sized> ConnectionLike for Box<C>
where
C: ConnectionLike
{ ... }
但是,只有定义特征的箱子才能添加 impl
。
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
...?
不,因为引用不是泛型类型的一部分C
。 Rust 不命名 entire 类型,它只命名两个类型不匹配的部分。该函数接受 &mut C
并且 C
是匹配的通用部分。 Box
类型是 C
的替代类型,它不实现此特征。
Question 2 -- Why is
Sized
required here? Isn't a reference in Rust alwaysSized
?
引用确实是 Sized
,但如上所述,我们正在将类型 &mut dyn redis::aio::ConnectionLike
与 &mut C
进行匹配。这导致 C
为 dyn redis::aio::ConnectionLike
。
在 Rust 中,泛型类型默认有 Sized
绑定 。 你必须显式指定 ?Sized
绑定来放宽这个,作者这个功能没做。因此,C
必须实现Sized
,而dyn redis::aio::ConnectionLike
则不需要。
Question 3 -- Is there any way to to pass a
dyn ConnectionLike
to this
可能,但不是直接的。您需要实现一种包装 reference-to-dyn ConnectionLike
或 Box<dyn ConnectionLike>
的类型,然后传递它。类似于:
struct BoxedConnectionLike(Box<dyn ConnectionLike>);
impl ConnectionLike for BoxedConnectionLike {
// Implement proxy functions for the trait.
}