我有一个
Rc<Box<dyn MyTrait>>
,我想编写一个函数,该函数需要一个可以取消引用到 &MyTrait
的类型。
以下是我尝试过的以及收到的错误。这可以用 Rust 实现吗?
use std::rc::Rc;
use std::ops::Deref;
trait MyTrait {
}
struct Foo {
}
impl MyTrait for Foo {
}
fn bar<T : Deref<Target = dyn MyTrait>>(obj: &T) {
}
fn main() {
let foo = Rc::new(Box::new(Foo {}) as Box<dyn MyTrait>);
bar(&foo)
}
这是我遇到的错误:
Compiling playground v0.0.1 (/playground)
error[E0271]: type mismatch resolving `<Rc<Box<dyn MyTrait>> as Deref>::Target == dyn MyTrait`
--> src/main.rs:21:9
|
21 | bar(&foo)
| --- ^^^^ expected `dyn MyTrait`, found `Box<dyn MyTrait>`
| |
| required by a bound introduced by this call
|
= note: expected trait object `(dyn MyTrait + 'static)`
found struct `Box<dyn MyTrait>`
note: required by a bound in `bar`
--> src/main.rs:15:18
|
15 | fn bar<T : Deref<Target = dyn MyTrait>>(obj: &T) {
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `bar`
For more information about this error, try `rustc --explain E0271`.
error: could not compile `playground` (bin "playground") due to 1 previous error
不可能编写执行这种递归的特征bound。 (部分正因为如此,
Deref
特征边界并不经常有用。)但是,您可以递归地实现特定特征,也就是说,这可以编译:
use std::ops::Deref;
use std::rc::Rc;
trait MyTrait {}
struct Foo {}
impl MyTrait for Foo {}
impl<T: ?Sized> MyTrait for T
where
T: Deref,
T::Target: MyTrait,
{
// delegate operations to `*self`
}
fn bar<T: MyTrait>(obj: &T) {}
fn main() {
let foo = Rc::new(Box::new(Foo {}) as Box<dyn MyTrait>);
bar(&foo)
}
特征
MyTrait
的实现用于定义递归操作的两种情况:MyTrait
的每个实现者要么是Foo
,要么是对另一个实现者的取消引用。
不过,更常见的是,不是根据
Deref
而是针对特定的指针类型(&T
、&mut T
、Box<T>
...)编写这样的递归实现,这是因为避免编写 blanket 实现 (impl<T...> MyTrait for T
) 为该特征的其他实现者提供了更多空间。