0

Apologies for the confusing title... If someone thinks of a better one, please edit this post.

I defined a trait like this:

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;
}

Implementing it for &Vec<(T, U)> is straightforward:

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
        }
}

However, I hit a lifetime issue when trying to implemented it for &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
        }
}

Here is the error:

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

I have two questions:

  • Is there a way to implement this trait for &'a mut Vec<(T, U)> ?
  • Why am I not hitting this error for &'a Vec<(T, U)> ? It looks exactly the same to me from a lifetime perspective: the content of &self is &'a Vec<(T, U)>, which outlives &self.
little-dude
  • 1,544
  • 2
  • 17
  • 33
  • Does the linked question help you? I *think* it's the same problem in both questions. However, you have another problem: you want to get a `&mut Vec<_>` (the `I` type in the second impl) from a `&&mut T` (the type of `self` in the method of the second impl) which is impossible. The answer to both problems is: take `self` by value in the method. If this all isn't helping you, please let us know! – Lukas Kalbertodt Mar 12 '17 at 09:09
  • @LukasKalbertodt thanks for the link. I think it boild down to the same problem indeed. I did solve my problem the way you suggested: by taking `self` instead of `&self`. Thanks a lot! – little-dude Mar 12 '17 at 17:28

1 Answers1

2

Let's compare the two function signatures, desugared. The second one looks like this:

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

Here you dereference self, giving you an object of type &'a mut Vec<(T, U)> (which is what you want) - but it can live only for lifetime 'b since you dereferenced it from a reference of lifetime 'b. Since 'b is potentially shorter than 'a, this is a lifetime error.

So how on earth does the first example work, then?

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

In this case, we get an object of type &'a Vec<(T, U)> with the same borrowing restriction - but since &'a T implements Copy, we return a new copy of it. (The reason it implements Copy - it doesn't matter if the intermediate borrow ends - we know there is an immutable reference with lifetime 'a, so the object cannot change in any way until 'a has ended.)

Djzin
  • 1,148
  • 9
  • 11