简体   繁体   English

为什么 Rust “From”特征实现会给出生命周期错误,而自定义特征却不会?

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

The following code can work when I use a custom trait.当我使用自定义特征时,以下代码可以工作。 But I don't understand why it fails when trying to use the builtin "From" trait.但我不明白为什么在尝试使用内置“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:错误:

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`


Since you do not provide any lifetimes to your From<&SimpleEnum> impl, the compiler assigns to &SimpleEnum (and hence the parameter value ) a different lifetime than the lifetime of Self (or &A ).由于您没有为From<&SimpleEnum> impl 提供任何生命周期,因此编译器为&SimpleEnum (以及参数value )分配的生命周期与Self (或&A )的生命周期不同 Desugared, the impl would be as follows:脱糖后, 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!();
        }
    }
}

This would not work as Self has a different lifetime 'b compared to value 's lifetime 'a .这是行不通的,因为Self的生命周期'bvalue的生命周期'a不同。 You have to explicitly tell the compiler that the two lifetimes are the same:您必须明确告诉编译器这两个生命周期是相同的:

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

Playground 操场

The difference has to do with inferred lifetimes.差异与推断的寿命有关。

Your custom trait has references in both the parameter and return type;您的自定义特征在参数和返回类型中都有引用; due to lifetime elision rules , your trait is equivalent to the following:由于生命周期省略规则,您的特征等同于以下内容:

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

So by the signature alone, the return type is bound to the lifetime of the parameter.因此仅通过签名,返回类型就绑定到参数的生命周期。

In contrast, the From trait is written as such:相反, From特征是这样写的:

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

There is no implicit linking of lifetimes between T and Self since there are no obvious lifetimes in use. TSelf之间没有生命周期的隐式链接,因为没有明显的生命周期在使用中。 And thus when you write your implementation, the &SimpleEnum and &A have distinct lifetimes, as if written like so:因此,当您编写实现时, &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!();
        }
    }
}

What is inferred is that a &SimpleEnum of any lifetime can be used to create a &A with any lifetime, which is untrue.推断的是,任何生命周期的&SimpleEnum都可以用来创建具有任何生命周期的&A ,这是不正确的。 You instead need to communicate that a &SimpleEnum with a particular lifetime can be used to create a &A with that lifetime.相反,您需要传达具有特定生命周期的&SimpleEnum可用于创建具有该生命周期的&A You can do that by linking the lifetimes together yourself:您可以通过自己将生命周期链接在一起来做到这一点:

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