[英]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
的生命周期'b
与value
的生命周期'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!();
}
}
}
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. T
和Self
之间没有生命周期的隐式链接,因为没有明显的生命周期在使用中。 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.