【问题标题】:How does Rust compile this example with cyclic trait bounds?Rust 如何使用循环特征边界编译这个示例?
【发布时间】:2022-07-19 23:28:33
【问题描述】:

我无法理解从this code 提取的以下示例如何编译:

trait A: B {}
trait B {}
impl<T> B for T where T: A {}

struct Foo;
impl A for Foo {}

fn main() {}

我目前的理解是

超特征是为实现特定特征而需要实现的特征。

  • impl&lt;T&gt; B for T where T:A 为具有特征 A 的任何类型实现 B .

我预计impl A for Foo 会失败,因为在为 Foo 实现 A 之前,一揽子实现无法为 Foo 实现 B,这是必需的。

关于 rustc 在编译 sn-p 时所做的最合理的模型如下:

  • 为 Foo 实现 A,将 Foo 实现 B 的检查推迟到稍后阶段
  • 用一揽子实现为 Foo 实现 B,因为 Foo 现在实现了 A
  • 检查 Foo 是否按照 trait bound A: B 的要求实现了 B

这在某种程度上接近事实吗?是否有任何我错过的文档来解释处理实现的顺序?

【问题讨论】:

  • 只是猜测,不知道实际情况如何。但我的猜测是,您“首先实现它,然后实现它”的想法是错误的。我宁愿猜测 Rust 编译器构建了一个什么实现了什么的图表,在那个图表中,你编写的代码是一个循环。它是循环的事实并不能否定它是有效的。但同样,这只是一个猜测,我实际上并不知道。不管怎样,我很好奇这里的其他人对此有什么看法。也许@ChayimFriedman 知道更多?
  • Rust 编译器绝对不会逐行甚至逐文件考虑。编译单元是 crate,因此在解析“Does Foo 实现 B”时要考虑整个 crate 的源代码。我也知道它用泛型懒惰地评估特征实现,所以在某些代码尝试之前它甚至不会考虑“Foo 是否实现 B”。我确实想知道这是否在某处得到了适当的解释或编纂,但我在快速搜索参考或 rustc 指南时没有找到任何东西。这可以推断出来,因为没有特定于订单的文档。
  • “没有特定于订单的文档” - 我收回这一点,声明性宏是特定于订单的

标签: rust


【解决方案1】:

rustc 不能“按顺序”工作。相反,我们首先注册所有 impl,然后对每个 impl 进行类型检查,没有特定的顺序。这个想法是我们收集 义务 列表(各种类型 - 其中一个是 trait bound),然后我们将它们与 impls 进行匹配(不仅仅是;这只是一种方式解决义务,但这与此处相关)。每个义务都可以创建另一个递归义务,我们会详细说明它们,直到不再有。

它目前的工作方式是,当我们检查impl Trait for Type 时,我们添加了一个义务Type: Trait。这可能看起来很愚蠢,但我们稍后会进一步详细说明,直到满足所有要求的界限。

假设我们目前正在检查impl&lt;T&gt; B for T where T: A。我们添加一项义务T: B,并将其与impl B for T 匹配。没有什么可以进一步阐述的,所以我们成功地完成了。

然后我们检查impl A for Foo,并添加义务Foo: A。由于特征A 需要Self: B,我们添加另一个义务Foo: B。然后我们开始匹配义务:第一个义务Foo: A与当前处理的impl匹配,没有额外的义务。第二个义务Foo: Bimpl&lt;T&gt; B for T where T: A 匹配。这有一个新的义务 - T: AFoo: A - 所以我们尝试匹配它。我们成功地将其与impl A for Foo 匹配,没有额外的义务。

上面的一个有趣的含义是,如果我们将第二个impl 更改为以下内容:

impl A for Foo where Foo: B {}

然后这不再编译时出现“溢出评估需求Foo: A”错误(playground),即使它本质上是相同的,因为现在要证明Foo: A rustc 需要证明Foo: B再说一遍Foo: A,而之前它只是为Foo: B 注册了一项义务,并没有立即证明这一点。

注意:以上是过度简化:例如,还有一个缓存、格式良好的义务等等。但大体原理是一样的。

【讨论】:

    猜你喜欢
    • 2020-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多