How to remove a lifetime requirement for an application in pyo3

180 Views Asked by At

Here's a reduced form of problem: I have a trait

pub trait GetIter {
    type IntoIter: IntoIterator<Item=usize>;
    fn get_iter( &self ) -> Self::IntoIter;
}

There are several use cases where I can implement GetIter on a reference &'a T, but not on T. This is fine for pure Rust, but lately I've needed to build a python interface with pyo3.

Since pyo3 wrappers are incompatible with lifetime parameters, I'd like to do something like the following

pub struct  NoRef< T > { inner: T }

impl <T> GetIter for NoRef< T > 
    where &T: GetIter
{
    type IntoIter = Vec<usize>;
    fn get_iter( &self )-> Vec<usize> { 
        (&self.inner).get_iter().into_iter().collect() 
    }
}

That is, we create a temporary reference internally, just long enough to dump the contents of the iterator to a vector, the drop the reference. The problem is that Rust doesn't like the constraint &T: GetIter -- it wants a lifetime parameter.

1

There are 1 best solutions below

0
Chayim Friedman On

Use an HRTB:

impl < T > GetIter for NoRef< T > 
    where for <'a>  &'a T: GetIter,
{
    type IntoIter = Vec<usize>;
    fn get_iter( & self )-> Vec<usize> { 
        (&self.inner).get_iter().into_iter().collect() 
    }
}

Just for added detail, you can check that this compiles/executes correctly with an example:

impl <'a> GetIter for &'a Vec<usize> { 
    type IntoIter=Vec<usize>; 
    
    fn get_iter(&self)->Self::IntoIter { 
        (*self).clone() 
    } 
}