繁体   English   中英

Rust 如何使用循环特征边界编译这个示例?

[英]How does Rust compile this example with cyclic trait bounds?

我无法理解从这段代码中提取的以下示例如何编译:

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

struct Foo;
impl A for Foo {}

fn main() {}

我目前的理解是

Supertraits 是为实现特定 trait 的类型需要实现的特征。

  • impl<T> B for T where T:A为具有特征 A 的任何类型实现 B 。

我希望impl A for Foo会失败,因为在为 Foo 实现 A 之前,一揽子实现不能为 Foo 实现 B,这是必需的。

对于 rustc 在编译代码段时所做的工作,我最合理的模型如下:

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

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

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

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

因此,假设我们目前正在检查impl<T> 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<T> B for T where T: A匹配。 这有一个新的义务 - T: AFoo: A - 所以我们尝试匹配它。 我们成功地impl A for Foo匹配,没有额外的义务。

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

impl A for Foo where Foo: B {}

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM