编辑:在此的较早版本中,我提到了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<'_, '_>>>`
以及下面的代码。
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,
}
}
}