如何定义允许任意数量的 Deref::deref 调用的 Deref 特征边界

问题描述 投票:0回答:1

我有一个

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
generics rust
1个回答
0
投票

不可能编写执行这种递归的特征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
) 为该特征的其他实现者提供了更多空间。

© www.soinside.com 2019 - 2024. All rights reserved.