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
.