简体   繁体   English

类型不匹配,将迭代器项解析为具有显式寿命的指针

[英]Type mismatch resolving iterator Item to a pointer with an explicit lifetime

I'm trying to add functions to Iterator where the associated type Item is a reference to a struct with an explicit lifetime. 我试图将函数添加到Iterator ,其中关联的类型Item是对具有显式寿命的结构的引用。

When I've wanted to modify the iterator state or return a new value I've had no problems, but when I attempt to return a new Iterator where Item is a reference with an explicit lifetime, the compiler complains. 当我想要修改迭代器状态或返回新值时,我没有任何问题,但是当我尝试返回一个新的IteratorItem是具有明确生命周期的引用,则编译器会抱怨。

Example

use std::marker::PhantomData;

/// First, an "Inner" struct to be contained in my custom iterator
pub struct Inner {
    text: String,
}

/// Then, the "CustomIterator" in question.  Notice that `Item` is `&'a Inner`.
pub struct CustomIterator<'a, I: Iterator<Item = &'a Inner>> {
    iter: I,
    _marker: PhantomData<&'a i8>,
}

/// Implementing Iterator for CustomIterator so as to define the `next()` function, as you do...
impl<'a, I: Iterator<Item = &'a Inner>> Iterator for CustomIterator<'a, I> {
    type Item = &'a Inner;
    fn next(&mut self) -> Option<Self::Item> {
        println!("Custom next called");
        self.iter.next()
    }
}

/// Now, creating a custom trait definition called IterateMore that:
///   1. inherits Iterator
///   2. includes a default method called `more` which returns a `CustomIterator`
pub trait IterateMore<'a>: Iterator {
    type Item;
    fn more(self) -> CustomIterator<'a, Self>
    where
        Self: Sized;
}

/// Implementing `IterateMore` for an iterator of the specific type `Iterator<Item=&'a Inner>`
impl<'a, I: Iterator<Item = &'a Inner>> IterateMore<'a> for I
where
    I: Iterator,
{
    type Item = &'a Inner;
    fn more(self) -> CustomIterator<'a, Self>
    where
        Self: Sized,
    {
        CustomIterator {
            iter: self,
            _marker: PhantomData,
        }
    }
}

fn main() {
    let inner = Inner {
        text: "Hello world".to_string(),
    };
    let inners = vec![&inner];
    inners.iter().more().next();
}

(See it on repl.it ) (请参阅repl.it

Error 错误

error[E0271]: type mismatch resolving `<Self as std::iter::Iterator>::Item == &'a Inner`
  --> src/main.rs:28:5
   |
28 | /     fn more(self) -> CustomIterator<'a, Self>
29 | |     where
30 | |         Self: Sized;
   | |____________________^ expected associated type, found reference
   |
   = note: expected type `<Self as std::iter::Iterator>::Item`
              found type `&'a Inner`
   = note: required by `CustomIterator`

Why is Item not being resolved here? 为什么无法在此处解决Item It is a bit frustrating as the compiler also complains if I try to set &'a Inner as the default Item type in the trait definition, saying: 这有点令人沮丧,因为如果我尝试在特征定义中将&'a Inner设置为默认的Item类型,编译器也会抱怨:

error: associated type defaults are unstable (see issue #29661)

How could this be fixed or done differently? 如何固定或以其他方式解决此问题?

It is unclear to me why you'd want to restrict the wrapped iterator to some custom type (given that you still have to write down the restriction every time you use the type, although that might change). 对我来说尚不清楚,为什么要将包装的迭代器限制为某些自定义类型(考虑到每次使用该类型,尽管这种情况可能会有所变化,但您仍然必须写下该限制)。 But perhaps your "real" next function does something funny. 但是,也许您的“真实” next功能做了一些有趣的事情。

  • PhantomData doesn't seem to be necessary (anymore) to "use" the lifetime when it is used in a where -clause. PhantomData似乎没有必要(再)以“用”,当它在使用的寿命where -clause。
  • IterateMore shouldn't have an Item associated type, given Iterator already has it. 如果Iterator已经拥有IterateMore不应具有与Item相关的类型。 (If you'd really need a new type pick a different name) (如果您确实需要新类型,请选择其他名称)
  • As IterateMore uses the CustomIterator type it needs to repeat the requirements, in this case Iterator<Item = &'a Inner> (that is what the type mismatch error is about); 因为IterateMore使用CustomIterator类型,所以它需要重复要求,在这种情况下, Iterator<Item = &'a Inner> (这就是类型不匹配错误的含义); this is not the same as saying type Item = &'a Inner in the trait definition. type Item = &'a Inner在特征定义中说type Item = &'a Inner不同。

Playground 操场

/// an "Inner" struct to be contained in my custom iterator
pub struct Inner {
    text: String,
}

pub struct CustomIterator<'a, I>
where
    I: Iterator<Item = &'a Inner>,
{
    iter: I,
}

impl<'a, I> Iterator for CustomIterator<'a, I>
where
    I: Iterator<Item = &'a Inner>,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        println!("Custom next called");
        self.iter.next()
    }
}

pub trait IterateMore<'a>: Iterator<Item = &'a Inner> + Sized {
    fn more(self) -> CustomIterator<'a, Self>;
}

impl<'a, I> IterateMore<'a> for I
where
    I: Iterator<Item = &'a Inner>,
{
    fn more(self) -> CustomIterator<'a, Self> {
        CustomIterator { iter: self }
    }
}

fn main() {
    let inner = Inner {
        text: "Hello world".to_string(),
    };
    let inners = vec![inner];
    inners.iter().more().next();
}

You could also remove the type restrictions everywhere like this (and only add it back in the place you actually need/want it): 您还可以像这样在所有地方删除类型限制(仅将其重新添加到您实际需要/想要的位置):

Playground 操场

pub struct CustomIterator<I> {
    iter: I,
}

impl<I> Iterator for CustomIterator<I>
where
    I: Iterator,
{
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        println!("Custom next called");
        self.iter.next()
    }
}

pub trait IterateMore: Iterator + Sized {
    fn more(self) -> CustomIterator<Self>;
}

impl<I> IterateMore for I
where
    I: Iterator,
{
    fn more(self) -> CustomIterator<Self>
    {
        CustomIterator { iter: self }
    }
}

fn main() {
    let inners = vec!["Hello world".to_string()];
    inners.iter().more().next();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM