rustc 可以 "infer the appropriate lifetime" 用于给定的 impl,但不能用于另一个

rustc can "infer the appropriate lifetime" for a given impl, but not for another one

为混乱的标题道歉...如果有人想到更好的,请编辑此 post。

我定义了这样一个特征:

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

我有两个问题:

让我们比较一下两个脱糖的函数签名。第二个看起来像这样:

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,我们 return 的一个新副本它。 (它实现 Copy 的原因 - 中间借用是否结束并不重要 - 我们知道有一个生命周期为 'a 的不可变引用,所以对象不能以任何方式改变,直到 'a已经结束。)