Редактировать: В более ранней версии этого я сделал ссылку на GAT, что могло отвлечь внимание от цели вопроса.Я отредактировал код, чтобы удалить один из связанных типов и упростить его в целом.Что я хотел бы понять из этого вопроса:
Почему rustc
принимает объект в штучной упаковке как конкретный тип, но жалуется, когда тот же объект приведен к признаку в штучной упаковке?Какие изменения я могу сделать, чтобы версия в штучной упаковке была принята?
Черта, которую я пытаюсь определить, примерно равна:
То, что может создать итераторнекоторого вида, который заимствует вещь и перебирает значения, у которых время жизни больше, чем у вещи, но не обязательно столь же велико, как 'static
.
После некоторой ухищрения я в конечном итоге смог закодировать это (см.CreatesIterator
) вместе с простой структурой ссылочной реализации (см. IteratorWithRef
).Эта конкретная реализация работает - она создает итератор указанного стиля, который может повторяться.Если я приведу эту реализацию к объекту черты, средство проверки заимствований отключит меня:
error[E0597]: `*creates_iterator_dyn` does not live long enough
--> src/main.rs:17:17
|
17 | let _ = creates_iterator_dyn.iterate().count();
| ^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
18 | }
| -
| |
| `*creates_iterator_dyn` dropped here while still borrowed
| borrow might be used here, when `creates_iterator_dyn` is dropped and runs the destructor for type `std::boxed::Box<dyn CreatesIterator<'_, '_, IteratorWithRef<'_, '_>>>`
Rust Playground
И код также ниже.
type LongTraitObjType<'collection, 'data> =
Box<dyn CreatesIterator<'collection, 'data, IteratorWithRef<'collection, 'data>> + 'data>;
fn main() {
let data = 1;
// Works: concrete implementation:
{
let creates_iterator_impl = Box::new(CreatesIteratorImpl(vec![Wrapper(&data)]));
let _ = creates_iterator_impl.iterate().count();
}
// Doesn't work: same as above, but cast to a trait object.
{
let creates_iterator_dyn: LongTraitObjType =
Box::new(CreatesIteratorImpl(vec![Wrapper(&data)]));
let _ = creates_iterator_dyn.iterate().count();
}
}
#[derive(Clone)]
struct Wrapper<'data>(&'data u32);
struct IteratorWithRef<'collection, 'data: 'collection> {
reference: &'collection CreatesIteratorImpl<'data>,
i: usize,
}
impl<'collection, 'data: 'collection> Iterator for IteratorWithRef<'collection, 'data> {
type Item = Wrapper<'data>;
fn next(&mut self) -> Option<Self::Item> {
if self.i < self.reference.0.len() {
let ret = Some(self.reference.0[self.i].clone());
self.i += 1;
ret
} else {
None
}
}
}
trait CreatesIterator<'collection, 'data, E>
where
'data: 'collection,
E: Iterator + 'collection,
<E as Iterator>::Item: 'data,
{
fn iterate(&'collection self) -> E;
}
struct CreatesIteratorImpl<'data>(Vec<Wrapper<'data>>);
impl<'collection, 'data: 'collection>
CreatesIterator<'collection, 'data, IteratorWithRef<'collection, 'data>>
for CreatesIteratorImpl<'data>
{
fn iterate(&'collection self) -> IteratorWithRef<'collection, 'data> {
IteratorWithRef {
reference: self,
i: 0,
}
}
}