如何高效地遍历Rust中的trait实现图?

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

我刚刚开始学习 Rust,读了一些书,做了一些事情,现在为了获得一些经验,我正在浏览 Rust 项目,试图理解他们的代码,我经常看到这样的代码:

fn execute_test() {
    let my_struct = MyStruct { value: 42 };

    use_trait_one(my_struct);
}

fn use_trait_one<T: TraitOne>(target: T) {
    target.do_something();
}

trait TraitOne {
    fn do_something(&self);
}

trait TraitTwo {
    fn do_something_ex(&self);
}

trait TraitThree {
    fn do_something(&self);
}

trait TraitFour {
    fn do_something(&self);
}

struct MyStruct {
    value: i32,
}

impl TraitFour for MyStruct {
    fn do_something(&self) {
        println!("{}", self.value);
    }
}

impl<T: TraitFour> TraitThree for T {
    fn do_something(&self) {
        self.do_something();
    }
}

impl<T: TraitFour> TraitTwo for T {
    fn do_something_ex(&self) {
        self.do_something();
    }
}

impl<T: TraitTwo + TraitFour + Send + Sync + 'static> TraitOne for T {
    fn do_something(&self) {
        self.do_something();
        self.do_something_ex();
    }
}

如果我想了解“MyStruct”如何实现“TraitOne”,是否有一种快速自动化的方法(IDE、rustc、第三方工具?)来遍历这个有向特征实现图? 手动执行此操作非常困难,因为这些特征实现可能来自不同的模块和包。

rust
1个回答
0
投票

使用 rustdoc(例如,在 docs.rs 上),最有效的方法是:

  1. 打开您感兴趣的类型 (
    MyStruct
    ) 以及您知道它实现的特征 (
    TraitOne
    )。
  2. 查看
    MyStruct
    的实现中是否提到了
    TraitOne
    。如果
    MyStruct
    TraitOne
    的依赖项,则检查
    TraitOne
    的实现中是否提到了
    MyStruct
    。如果是,则图表结束。否则,继续。
  3. 转到TraitOne
    一揽子实施
    。这表示
    impl<T: TraitTwo + TraitFour + Send + Sync + 'static> TraitOne for T
    。一次一个,每次跳跃重复步骤 2 和 3。它们都需要连接到
    MyStruct
    ,所以如果您愿意,您只能查看其中的一些。

在这种情况下,

Send + Sync + 'static
都直接为
MyStruct
,所以这些立即结束。 rustdoc 中没有提到
'static
,但你可以看出这是真的,因为
MyStruct
没有生命周期。
Send
Sync
出现在
MyStruct
的自动特征实现部分。

TraitTwo
有一个使用
TraitFour
的全面实现。
TraitFour
是为
MyStruct
明确实现的。

回到

T: TraitTwo + TraitFour + Send + Sync + 'static
TraitFour
是唯一剩下的,我们只是在
TraitTwo
的路径中查看了那个。

在简单的情况下这就足够了。但是,如果您想了解为什么“特征方法是可调用的”,那么您将需要考虑方法解析可以访问的任何类型。这意味着检查 &MyStruct

&mut MyStruct
,以及
MyStruct
是否实现了
Deref
MyStruct
的 deref 目标类型,以及所有这些递归方式。特征还允许具有
T
&T
&mut T
的一揽子实现,但幸运的是,它们只允许每个包装器有一个一揽子实现。类型和特征中的泛型也会使事情变得更加复杂,类型别名也无济于事。我想我永远不会知道
sha2::Sha256
 实现了什么特征。
举一个现实世界的例子,假设您具有特征

rand::Rng

rand_xoshiro::Xoshiro256StarStar

打开
    Rng
  1. 的实现:
    https://docs.rs/rand/latest/rand/trait.Rng.html#implementors
    打开Xoshiro256StarStar的实现:
    https://docs.rs/rand_xoshiro /latest/rand_xoshiro/struct.Xoshiro256StarStar.html#trait-implementations
  2. Xoshiro256StarStar
  3. 没有提到
    Rng
    ,所以继续。
    查看 
  4. Rng
  5. 的全面实施:
    impl<R: RngCore + ?Sized> Rng for R
    。它需要
    RngCore
    ,因此请参阅文档获取
    RngCore
  6. Xoshiro256StarStar
  7. 实现
    RngCore
    。搜索完成。
  8. 找到的路径是
Xoshiro256StarStar

->

RngCore
->
Rng
    

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