У меня есть определение структуры, которое включает, помимо прочего, это поле:
pub struct Separated<'a, I, T>
{
..., // other fields,
separated: NonNull<dyn 'a + Iterator<Item = T>>,
}
Вскоре после этого в своем конструкторе я пытаюсь инициализировать это поле как висячий указатель:
let sep = Separated {
..., // other fields
separated: NonNull::dangling(),
};
Это, как ни странно, приводит к этой ошибке:
error[E0282]: type annotations needed
|
16 | separated: NonNull::dangling(),
| ^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
В этом поле нет ничего загадочного; его тип явно указан в определении структуры. Я не понимаю, почему средство вывода типов не может определить подходящий тип для внедрения там.
Минимальный пример из 20 строк, приводящий к этой ошибке, можно найти ниже и на игровой площадке :
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!()
}
}
Мне нужно, чтобы separated
был указателем на объект признака вместо мономорфизированного типа: объект реального признака, который он будет содержать, состоит из набора комбинаторов итераторов, включая такие, как Map
и TakeWhile
, чьи типы включают указатели на функции и поэтому не могут быть названы.
NonNull::dangling
не является параметрической c функцией: структура NonNull<T>
является параметрической c, но эта функция - нет. Поэтому я не могу просто turbofi sh мой выход из этого. Я не уверен, как бы я go вообще предоставил аннотации типов.
Контекст, если это полезно: единственная причина, по которой я иду по этому пути, в том, что я пытаюсь создать комбинатор итераторов, автоматически реализованный для всех соответствующих итераторов, который вставляет один элемент между каждым из N элементов исходного итератора. Не так сложно выполнить sh для одного итератора, но гораздо сложнее сделать это как обобщенный c комбинатор, поскольку структура IntoChunks
, создаваемая комбинатором chunks()
Itertools, сама по себе не является итератором, а просто структура, реализующая IntoIterator
. Следовательно, нам нужно отслеживать структуру IntoChunks
и ее итератор.
Подход, который я использую, заключается в создании самореференциальной структуры, Separated
, которая содержит оба из них. Это должно быть безопасно, если структура всегда закреплена. Я тогда impl Iterator for Separated
и просто откладываю next
звонки на self.separated
.