rustc 无法推断特征实现中的生命周期

问题描述 投票:0回答:1

我有以下代码:

use anyhow;

struct InnerValue;

enum Value {
    Int(i32),
    Other(InnerValue),
}

impl TryFrom<&Value> for &InnerValue {
    type Error = anyhow::Error;
    
    fn try_from(value: &Value) -> Result<Self, Self::Error> {
        match value {
            Value::Int(..) => anyhow::bail!("Ignore this case"),
            Value::Other(inner) => Ok(inner)
        }
    }
}

rustc
告诉我:

   Compiling playground v0.0.1 (/playground)
error: lifetime may not live long enough
  --> src/lib.rs:16:36
   |
13 |     fn try_from(value: &Value) -> Result<Self, Self::Error> {
   |                        -          ------------------------- return type is Result<&'2 InnerValue, <&'2 InnerValue as TryFrom<&Value>>::Error>
   |                        |
   |                        let's call the lifetime of this reference `'1`
...
16 |             Value::Other(inner) => Ok(inner)
   |                                    ^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error: could not compile `playground` (lib) due to previous error

尽管

try_from
应该能够推断生命周期,但
rustc
却无法做到这一点。最直接的方法是添加显式的生命周期签名;然而,在这种情况下,这是一个特征实现(
std::convert::TryFrom
),所以我无法更改函数签名。有办法解决这个问题吗?

rust traits lifetime
1个回答
0
投票

虽然您无法更改

try_from()
的函数签名,但您 可以 在实现
TryFrom
时指定显式的生命周期,如下所示:

impl<'a> TryFrom<&'a Value> for &'a InnerValue {
    type Error = anyhow::Error;
    
    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
        match value {
            Value::Int(..) => anyhow::bail!("Ignore this case"),
            Value::Other(inner) => Ok(inner)
        }
    }
}

这将按照您的预期进行编译(请参阅playground)。

预计

rustc
不能将
&Value
&InnerValue
的生命周期消除到相同的生命周期;请参阅 Rustonomicon 的 Lifetime Elision 部分,特别是以下行:“对于
impl
标头,所有类型都是输入。因此
impl Trait<&T> for Struct<&T>
在输入位置中省略了两个生命周期,而
impl Struct<&T>
则省略了一个。”因此,如果两个生命周期要相同,则必须明确提供它们。

© www.soinside.com 2019 - 2024. All rights reserved.