簡體   English   中英

為什么 Rust “From”特征實現會給出生命周期錯誤,而自定義特征卻不會?

[英]Why does Rust "From" trait implementation give lifetime error, but custom trait does not?

當我使用自定義特征時,以下代碼可以工作。 但我不明白為什么在嘗試使用內置“From”特征時它會失敗。

struct A {
    x: isize,
}

enum SimpleEnum {
    A(A),
    B(u8),
}

trait FromCustom {
    fn from_custom(value: &SimpleEnum) -> &A;
}

impl FromCustom for &SimpleEnum {
    fn from_custom(value: &SimpleEnum) -> &A {
        if let SimpleEnum::A(value) = value {
            value // NO error
        } else {
            panic!();
        }
    }
}

impl From<&SimpleEnum> for &A {
    fn from(value: &SimpleEnum) -> Self {
        if let SimpleEnum::A(value) = value {
            value // error
        } else {
            panic!();
        }
    }
}

錯誤:

error: lifetime may not live long enough
  --> rust_pst_bin/src/main.rs:55:13
   |
53 |     fn from(value: &SimpleEnum) -> Self {
   |                    -               ---- return type is &'2 A
   |                    |
   |                    let's call the lifetime of this reference `'1`
54 |         if let SimpleEnum::A(value) = value {
55 |             value // error
   |             ^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`


由於您沒有為From<&SimpleEnum> impl 提供任何生命周期,因此編譯器為&SimpleEnum (以及參數value )分配的生命周期與Self (或&A )的生命周期不同 脫糖后, impl將如下所示:

impl<'a, 'b> From<&'a SimpleEnum> for &'b A {
    fn from(value: &'a SimpleEnum) -> Self {
        if let SimpleEnum::A(value) = value {
            value
        } else {
            panic!();
        }
    }
}

這是行不通的,因為Self的生命周期'bvalue的生命周期'a不同。 您必須明確告訴編譯器這兩個生命周期是相同的:

impl<'a> From<&'a SimpleEnum> for &'a A {
    fn from(value: &'a SimpleEnum) -> Self {
        if let SimpleEnum::A(value) = value {
            value
        } else {
            panic!();
        }
    }
}

操場

差異與推斷的壽命有關。

您的自定義特征在參數和返回類型中都有引用; 由於生命周期省略規則,您的特征等同於以下內容:

trait FromCustom {
    fn from_custom<'a>(value: &'a SimpleEnum) -> &'a A;
}

因此僅通過簽名,返回類型就綁定到參數的生命周期。

相反, From特征是這樣寫的:

pub trait From<T>: Sized {
    fn from(value: T) -> Self;
}

TSelf之間沒有生命周期的隱式鏈接,因為沒有明顯的生命周期在使用中。 因此,當您編寫實現時, &SimpleEnum&A具有不同的生命周期,就像這樣寫:

impl<'a, 'b> From<&'b SimpleEnum> for &'a A {
    fn from(value: &'b SimpleEnum) -> Self {
        if let SimpleEnum::A(value) = value {
            value // error
        } else {
            panic!();
        }
    }
}

推斷的是,任何生命周期的&SimpleEnum都可以用來創建具有任何生命周期的&A ,這是不正確的。 相反,您需要傳達具有特定生命周期的&SimpleEnum可用於創建具有該生命周期的&A 您可以通過自己將生命周期鏈接在一起來做到這一點:

impl<'a> From<&'a SimpleEnum> for &'a A {
    fn from(value: &'a SimpleEnum) -> Self {
        if let SimpleEnum::A(value) = value {
            value
        } else {
            panic!();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM