[英]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.