[英]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. 当我想要修改迭代器状态或返回新值时,我没有任何问题,但是当我尝试返回一个新的Iterator
, Item
是具有明确生命周期的引用,则编译器会抱怨。
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[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) (如果您确实需要新类型,请选择其他名称) 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
不同。 /// 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): 您还可以像这样在所有地方删除类型限制(仅将其重新添加到您实际需要/想要的位置):
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.