[英]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() {}
我目前的理解是
trait A: B
用超特征 B 声明了一个特征 A。Rust 对特征的引用指出Supertraits 是为实现特定 trait 的类型需要实现的特征。
impl<T> B for T where T:A
为具有特征 A 的任何类型实现 B 。 我希望impl A for Foo
会失败,因为在为 Foo 实现 A 之前,一揽子实现不能为 Foo 实现 B,这是必需的。
对于 rustc 在编译代码段时所做的工作,我最合理的模型如下:
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: B
与impl<T> B for T where T: A
匹配。 这有一个新的义务 - T: A
或Foo: 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.