I have a struct definition which includes, among other things, this field:
pub struct Separated<'a, I, T>
{
..., // other fields,
separated: NonNull<dyn 'a + Iterator<Item = T>>,
}
Shortly after, in its constructor, I attempt to initialize that field as a dangling pointer:
let sep = Separated {
..., // other fields
separated: NonNull::dangling(),
};
This, weirdly, produces this error:
error[E0282]: type annotations needed
|
16 | separated: NonNull::dangling(),
| ^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
There's nothing mysterious about that field; its type is explicitly set in the struct definition. I do not understand why the type inferencer cannot infer an appropriate type to inject there.
A minimal 20-line example producing this error can be found below and on the playground:
use std::pin::Pin;
use std::ptr::NonNull;
pub struct Separated<'a, T> {
t: &'a T,
separated: NonNull<dyn 'a + Iterator<Item = T>>,
}
impl<'a, T> Separated<'a, T>
where
T: 'a + Copy + PartialEq,
{
fn new(t: &'a T) -> Pin<Box<Self>> {
let sep = Separated {
t,
separated: NonNull::dangling(),
};
unimplemented!()
}
}
I do need separated to be a pointer to a trait object instead of a monomorphized type: the real trait object which it will contain is composed of a bunch of iterator combinators, including ones like Map and TakeWhile, whose types include function pointers and are therefore unnameable.
NonNull::dangling is not a parametric function: the NonNull<T> struct is parametric, but this function is not. Therefore, I can't just turbofish my way out of this. I'm not sure how I'd go about providing type annotations at all.
Context, if useful: the whole reason I'm going down this path is I am attempting to create an iterator combinator, auto-implemented for all appropriate iterators, which injects a single element between each N elements of the origin iterator. It's not all that hard to accomplish for a single iterator, but much harder to do as a generic combinator, because the IntoChunks struct produced by Itertools' chunks() combinator is not itself an iterator, just a struct implementing IntoIterator. Therefore, we need to keep track of the IntoChunks struct as well as the iterator it produces.
The approach I'm taking is to create a self-referential struct, Separated, which contains both of those. This should be safe assuming the struct is always pinned. I then impl Iterator for Separated and just defer the next calls to self.separated.