Estou implementando incorretamente o IntoIterator para fazer referência a uma implementação LazyList ou isso é um bug do Rust?

Ao implementar uma versão de um LazyList (uma lista vinculada memorizada imutável, computada preguiçosamente, memorizada e imutável, como as listas de Haskell), deparei-me com um problema de implementaçãoIntoIterator em que o código não descarta a referência quando penso que deveria. O código a seguir foi simplificado para mostrar apenas o problema; portanto, não é genérico e não inclui todos os métodos não relacionados à implementaçãoIntoIterator:

use std::cell::UnsafeCell;
use std::mem::replace;
use std::rc::Rc;

// only necessary because Box<FnOnce() -> R> doesn't yet work...
trait Invoke<R = ()> {
    fn invoke(self: Box<Self>) -> R;
}

impl<'a, R, F: 'a + FnOnce() -> R> Invoke<R> for F {
    #[inline(always)]
    fn invoke(self: Box<F>) -> R {
        (*self)()
    }
}

// not thread safe
struct Lazy<'a, T: 'a>(UnsafeCell<LazyState<'a, T>>);

enum LazyState<'a, T: 'a> {
    Unevaluated(Box<Invoke<T> + 'a>),
    EvaluationInProgress,
    Evaluated(T),
}

use self::LazyState::*;

impl<'a, T: 'a> Lazy<'a, T> {
    #[inline]
    fn new<F: 'a + FnOnce() -> T>(func: F) -> Lazy<'a, T> {
        Lazy(UnsafeCell::new(Unevaluated(Box::new(func))))
    }
    #[inline]
    pub fn evaluated(val: T) -> Lazy<'a, T> {
        Lazy(UnsafeCell::new(Evaluated(val)))
    }
    #[inline]
    fn value(&'a self) -> &'a T {
        unsafe {
            match *self.0.get() {
                Evaluated(_) => (), // nothing required; already Evaluated
                EvaluationInProgress => panic!("Lazy::force called recursively!!!"),
                _ => {
                    let ue = replace(&mut *self.0.get(), EvaluationInProgress);
                    if let Unevaluated(thnk) = ue {
                        *self.0.get() = Evaluated(thnk.invoke());
                    } // no other possiblity!
                }
            } // following just gets evaluated, no other state possible
            if let Evaluated(ref v) = *self.0.get() {
                return v;
            } else {
                unreachable!();
            }
        }
    }
}

enum LazyList<'a> {
    Empty,
    Cons(i32, RcLazyListNode<'a>),
}

type RcLazyListNode<'a> = Rc<Lazy<'a, LazyList<'a>>>;

impl<'a> LazyList<'a> {
    fn iter(&self) -> Iter<'a> {
        Iter(self)
    }
}

struct Iter<'a>(*const LazyList<'a>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a i32;

    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            if let LazyList::Cons(ref v, ref r) = *self.0 {
                self.0 = r.value();
                Some(v)
            } else {
                None
            }
        }
    }
}

impl<'a> IntoIterator for &'a LazyList<'a> {
    type Item = &'a i32;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

fn main() {
    let test2 = LazyList::Cons(2, Rc::new(Lazy::evaluated(LazyList::Empty)));
    let test = LazyList::Cons(1, Rc::new(Lazy::new(move || test2)));
    // let itr = Iter(&test); // works
    // let itr = (&test).iter(); // works
    let itr = IntoIterator::into_iter(&test); // not working
    for v in itr {
        println!("{}", v);
    }
}

O código acima falha com:

rustc 1.13.0 (2c6933acc 2016-11-07)
error: `test` does not live long enough
   --> <anon>:103:40
    |
103 |     let itr = IntoIterator::into_iter(&test); // not working
    |                                        ^^^^ does not live long enough
...
107 | }
    | - borrowed value dropped before borrower
    |
    = note: values in a scope are dropped in the opposite order they are created

Conforme observado nos comentários emmain(), o código é utilizávelexceto quando chamado como referência através da característica IntoIterator. Isso pode ser um bug na implementação de características para referências em que a propriedade do iterador retornado que contém um ponteiro não é transferida para o mesmo escopo que a chamada paraIntoIterator::into_itermas sim para o'static vida útil, portanto, não é descartada quando esperado.

Como faço para implementar isso, se possível? Eu tentei adicionar umstd::marker::PhantomData<> campo marcador para oIter estrutura, mas parece que também é atribuído um'static tempo de vida.

questionAnswers(2)

yourAnswerToTheQuestion