为何Rust中From trait实现出现生命周期错误,自定义trait却不会?
自定义FromCustom trait可正常运行,为何标准From trait会报错?
先看代码示例:
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 // 无错误 } else { panic!(); } } } impl From<&SimpleEnum> for &A { fn from(value: &SimpleEnum) -> Self { if let SimpleEnum::A(value) = value { value // 错误 } else { panic!(); } } }
对应的错误信息:
error: lifetime may not live long enough --> rust_pst_bin/src/main.rs:55:13 | 53 | fn from(value: &SimpleEnum) -> Self { | - ---- 返回类型为&'2 A | | | 我们将此引用的生命周期称为`'1` 54 | if let SimpleEnum::A(value) = value { 55 | value // 错误 | ^^^^^ 关联函数应返回生命周期为`'2`的数据,但实际返回生命周期为`'1`的数据
原因分析
自定义trait的情况:
Rust的生命周期省略规则在这里生效了:当方法的输入参数是一个引用,返回值也是引用时,编译器会自动将返回值的生命周期和输入参数的生命周期绑定,相当于把from_custom方法的签名隐式推导为:fn from_custom<'a>(value: &'a SimpleEnum) -> &'a A;这样返回的
&A引用和输入的&SimpleEnum引用生命周期一致,编译器能确认引用的有效性,所以不会报错。标准From trait的情况:
标准库的Fromtrait是泛型定义,当你实现From<&SimpleEnum> for &A时,编译器无法自动推导输入引用和返回引用之间的生命周期关系。你写的代码里,输入的&SimpleEnum有自己的生命周期'1,返回的&A被推导为另一个独立的生命周期'2,编译器不知道'2应该依赖'1,所以认为返回的引用生命周期不够长,抛出错误。
解决方法
显式标注生命周期,让输入和返回的引用共享同一个生命周期:
impl<'a> From<&'a SimpleEnum> for &'a A { fn from(value: &'a SimpleEnum) -> Self { if let SimpleEnum::A(value) = value { value } else { panic!(); } } }
这样编译器就能明确,返回的&A引用的生命周期和输入的&SimpleEnum完全一致,不会再出现生命周期不匹配的问题。
内容的提问来源于stack exchange,提问作者Sharpiro
相关产品推荐
相关产品推荐

