Lifetimeception - Trait usage with lifetime in trait and impl

I need a lifetime parameter for the following trait because I want the actual type of the Iterator (e.g. Iter of slice contains has a lifetime parameter). It can't be a method lifetime parameter, because the return type depends on it.

pub trait Iterable<'a> {
    type Iter: Iterator;

    fn iterate(&'a self) -> Self::Iter;
}

To simplify things, I will use the following trait:

trait Test<'a> {}

I want to use this trait in a function like this function:

fn test<I>(t: I)
where
    for<'a> I: Test<'a>,
{
    {
        // First use of t
    }
    {
        // Second use of t
    }
}

So far so good, if I impl this trait for any normal type the function works as expected.
But if I try to use a type containing a reference, the compiler complains that it needs to borrow the value for 'static.
This is kinda unexpected since I don't even use the value nor return anything. The problem is obviously for<'a> but I see no other way to tell the compiler "I implements the trait for every lifetime that is within the function scope" since I can't restrict the lifetime 'a. Furthermore, I can't make 'a a lifetime parameter of test because this would mean I would be borrowed for 'a after the first use, which is longer than the scope of the function.

Minimal failing example would be

struct ContainingReference<'a>(&'a i32);

// Implement the trait for every lifetime that is at most as long as 'a
impl<'a: 'b, 'b> Test<'b> for ContainingReference<'a> {}

fn main() {
     let i = 0;
     test(ContainingReference(&i));
}
error[E0597]: `i` does not live long enough
    |
    |         t(ContainingReference(&i));
    |         ----------------------^^--
    |         |                     |
    |         |                     borrowed value does not live long enough
    |         argument requires that `i` is borrowed for `'static`
...
    |     }
    |     - `i` dropped here while still borrowed

Consider whether you actually want IntoIterator from the standard library. You can implement this for a reference type (&'a T) to replace your troublesome Iterable trait, and such implementations exist for all the usual collections.

If you really go as far as declaring your own replacement trait for IntoIterator, I'd at least recommend you to go all in for it to be worth it. I don't have much time, right now, so I'll just drop this here and come back later to this issue:

/// Conversion into an `Iterator`.
pub trait Iterable<'a> {
    /// The type of the elements being iterated over.
    type Element: 'a;

    /// Which kind of iterator are we turning this into?
    type Iterator: Iterator<Item = &'a Self::Element>;

    /// Creates an iterator from a reference.
    fn iterator(&'a self) -> Self::Iterator;
}

/// Conversion into an `Iterator`.
pub trait IterableMut<'a>: Iterable<'a> {
    /// Which kind of iterator are we turning this into?
    type IteratorMut: Iterator<Item = &'a mut Self::Element>;

    /// Creates an iterator from a mutable reference.
    fn iterator_mut(&'a mut self) -> Self::IteratorMut;
}

/// Conversion into an `Iterator`.
pub trait IterableOnce<'a>: IterableMut<'a> {
    /// Which kind of iterator are we turning this into?
    type IntoIterator: Iterator<Item = Self::Element>;

    /// Creates an iterator from a value.
    fn into_iterator(self) -> Self::IntoIterator;
}

Thanks for the reply, I did try this and it removed a lot of lifetime parameters from my code:

trait Test {}

fn test<I>(t: I)
where
   for<'a> &'a I: Test,
{
}

struct ContainingReference<'a>(&'a i32);

impl<'a, 'b: 'a> Test for &'a ContainingReference<'b> {}

Sadly, this has the same problem, I still can't name a type that satisfies the trait for free usage in a method (here test) because 'a = 'static follows from the code.

Sticking with IntoIterator, how do I name a type T that implements IntoIterator for &T inside a function?

I found an article with essentially the same problem, and this is impossible right now since GAT is still not a thing.

Sorry I couldn't be of more help! I hope you're able to find a workaround.