為帶有生命週期標註的 struct 實現 trait 的問題

linghuyichong發表於2019-12-31

問題來自於Rust中文社群,連結:https://rust.cc/article?id=c8c9e40a-b27c-4... ,錯誤程式碼如下:

use std::str::FromStr;

pub struct Wrapper<'a>(&'a str);

impl FromStr for Wrapper<'_> {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Wrapper(s))
    }
}

在《Rust程式設計語言》中第10.3節中,講到 “編譯器採用三條規則來判斷引用何時不需要明確的註解。第一條規則適用於輸入生命週期,後兩條規則適用於輸出生命週期。如果編譯器檢查完這三條規則後仍然存在沒有計算出生命週期的引用,編譯器將會停止並生成錯誤。這些規則適用於 fn 定義,以及 impl 塊。
第一條規則是每一個是引用的引數都有它自己的生命週期引數。
第二條規則是如果只有一個輸入生命週期引數,那麼它被賦予所有輸出生命週期引數:fn foo<'a>(x: &'a i32) -> &'a i32
第三條規則是如果方法有多個輸入生命週期引數,不過其中之一因為方法的緣故為 &self 或 &mut self,那麼 self 的生命週期被賦給所有輸出生命週期引數。第三條規則使得方法更容易讀寫,因為只需更少的符號。
在上述例子中,fn from_str函式顯然是符合第二條規則,也就是說入參s: &str的生命週期被賦予為輸出的生命週期。但是,輸出引數中的Self對應的型別為結構體Wrapper,而Wrapper是有生命週期的限制的,此時編譯器不知道如何判斷,因此報錯。
問題題主的原意是要為自定義型別實現FromStr trait,但是此處很顯然是不可以的(我分析的結果是這樣,如果有高手能直接在此處實現FromStr trait也請積極留言,不勝感激),可以考慮用其它的辦法來實現類似的功能(如透過方法)。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
令狐一衝

相關文章