对于给定的impl,rustc可以“推断出适当的生命周期”,但不能用于另一个

时间:2017-03-12 04:46:51

标签: rust traits lifetime

为令人困惑的标题道歉...如果有人想到更好的标题,请编辑这篇文章。

我定义了这样一个特征:

pub trait AsUrlParams
    where <Self::I as IntoIterator>::Item: Borrow<(Self::K, Self::V)>,
{
    type I: IntoIterator;
    type K: AsRef<str>;
    type V: AsRef<str>;

    fn as_url_params(&self) -> Self::I;
}

&Vec<(T, U)>实施它很简单:

impl<'a, T, U> AsUrlParams for &'a Vec<(T, U)>
    where T: AsRef<str>,
          U: AsRef<str>,
{
        type I = Self;
        type K = T;
        type V = U;

        fn as_url_params(&self) -> Self::I {
            *self
        }
}

但是,在尝试为&mut Vec<(T, U)>实施该问题时,我遇到了终身问题:

impl<'a, T, U> AsUrlParams for &'a mut Vec<(T, U)>
    where T: AsRef<str>,
          U: AsRef<str>,
{
        type I = Self;
        type K = T;
        type V = U;

        fn as_url_params(&self) -> Self::I {
            *self
        }
}

这是错误:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
   --> src/main.rs:186:13
    |
186 |             *self
    |             ^^^^^
    |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 185:43...
   --> src/main.rs:185:44
    |
185 |           fn as_url_params(&self) -> Self::I {
    |  ____________________________________________^ starting here...
186 | |             *self
187 | |         }
    | |_________^ ...ending here
note: ...so that reference does not outlive borrowed content
   --> src/main.rs:186:13
    |
186 |             *self
    |             ^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 185:43...
   --> src/main.rs:185:44
    |
185 |           fn as_url_params(&self) -> Self::I {
    |  ____________________________________________^ starting here...
186 | |             *self
187 | |         }
    | |_________^ ...ending here
note: ...so that types are compatible (expected AsUrlParams, found AsUrlParams)
   --> src/main.rs:185:44
    |
185 |           fn as_url_params(&self) -> Self::I {
    |  ____________________________________________^ starting here...
186 | |             *self
187 | |         }
    | |_________^ ...ending here

我有两个问题:

  • 有没有办法为&'a mut Vec<(T, U)>实现此特性?
  • 为什么我没有为&'a Vec<(T, U)>发出此错误?从终身的角度来看,它看起来完全一样:&self的内容是&'a Vec<(T, U)>,比&self更长。

1 个答案:

答案 0 :(得分:2)

让我们比较两个功能签名,desugared。第二个看起来像这样:

fn as_url_params<'b>(self: &'b &'a mut Vec<(T, U)>) -> &'a mut Vec<(T, U)> {
    *self
}

在这里,您取消引用self,为您提供类型&'a mut Vec<(T, U)>的对象(这是您想要的) - 但它只能在生命周期'b中生存,因为您从引用中取消引用它一生'b。由于'b可能短于'a,因此这是一个生命周期错误。

那么第一个例子究竟是如何工作的呢?

fn as_url_params<'b>(self: &'b &'a Vec<(T, U)>) -> &'a Vec<(T, U)> {
    *self
}

在这种情况下,我们得到一个类型为&'a Vec<(T, U)>且具有相同借用限制的对象 - 但由于&'a T实现了Copy,我们将返回它的新副本。 (它实现Copy的原因 - 如果中间借用结束并不重要 - 我们知道有一个带有生命期'a的不可变引用,所以在{{{{}}之前对象不能以任何方式改变1}}已经结束了。)