簡體   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