我在使用将通用特征对象作为参数的泛型函数时遇到了麻烦。当我尝试调用该函数时,编译器会抱怨“错误:未对类型Next
[E0277]”实现特征&'a mut Next<Type=Type> + 'a
。在我看来,Next
特征对于任何参数Type
都是对象安全的,所以Next
应由任何&Next<Type>
实现(通过我阅读Huon’s Object-Safety article );有没有办法检查它是否是对象安全的?
顺便说一句,我对使用Iterator
做同样的事情没有任何问题,我不知道这有什么不同。
trait Next {
type Type;
fn next(&mut self) -> Option<Self::Type>;
}
struct NextImpl<Type> {
next: Option<Type>,
}
impl<Type> Next for NextImpl<Type> {
type Type = Type;
fn next(&mut self) -> Option<Self::Type> {
let mut ret = None;
std::mem::swap(&mut self.next, &mut ret);
ret
}
}
struct DelegatingNext<'a, Type> {
delegate: &'a mut Next<Type=Type>,
}
impl<'a, Type> Next for DelegatingNext<'a, Type> {
type Type = Type;
fn next(&mut self) -> Option<Self::Type> {
self.delegate.next()
// error: the trait `Next` is not implemented for the type `&'a mut Next<Type=Type> + 'a` [E0277]
// Next::next(&mut self.delegate)
// ^~~~~~~~~~
// error: the trait `Next` is not implemented for the type `&'a mut Next<Type=Type> + 'a` [E0277]
// if (true) {
// next_next1(&mut self.delegate)
// ^~~~~~~~~~
// error: the trait `Next` is not implemented for the type `&'a mut Next<Type=Type> + 'a` [E0277]
// next_next2(&mut self.delegate)
// ^~~~~~~~~~~~~~~~~~
}
}
fn next_next1<'a, NextType: Next + ?Sized>(m: &'a mut NextType) -> Option<NextType::Type> {
m.next()
}
fn next_next2<'a, Type>(m: &'a mut Next<Type=Type>) -> Option<Type> {
m.next()
}
struct DelegatingIterator<'b, T> {
iter: &'b mut Iterator<Item=T>,
}
impl<'b, T> DelegatingIterator<'b, T> {
fn next(&mut self) -> Option<T> {
let iter: &mut Iterator<Item=T> = self.iter;
iterator_next1(iter)
// error: the trait `core::marker::Sized` is not implemented for the type `core::iter::Iterator<Item=T>` [E0277]
// note: `core::iter::Iterator<Item=T>` does not have a constant size known at compile-time
// iterator_next2(iter)
// ^~~~~~~~~~~~~~
// OK
// iterator_next3(iter)
// OK
// iterator_next4(iter)
}
}
fn iterator_next1<'a, T>(iter: &mut Iterator<Item=T>) -> Option<T> {
iter.next()
}
fn iterator_next2<It: Iterator>(iter: &mut It) -> Option<It::Item> {
iter.next()
}
fn iterator_next3<It: Iterator + ?Sized>(iter: &mut It) -> Option<It::Item> {
iter.next()
}
fn iterator_next4<'a, Item>(iter: &mut Iterator<Item=Item>) -> Option<Item> {
iter.next()
}
fn main() {
let mut m = NextImpl {next: Some("hi")};
let mut delegating_model = DelegatingNext {delegate: &mut m};
assert!(Some("hi") == delegating_model.next());
let v: Vec<i32> = vec!(1, 2, 3);
let mut iter = v.iter();
assert_eq!(Some(&1), (DelegatingIterator {iter: &mut iter }).next());
}
答案 0 :(得分:3)
我认为你正在添加一个额外的间接层。在这种情况下,方法调用self.delegate.next()
desugars into Next::next(self.delegate)
- 不需要自动引用(可变或其他)。
错误消息令人困惑,因为您有两个级别的引用。你的特质是:
trait Next {
fn next(&mut self)
}
这意味着您必须传递&mut Foo
。但是,您正在使用第二个可变引用,使参数类型为&mut &mut NextImpl<Type>
。第一个&mut
与函数参数匹配,但其余类型需要实现Next
。但是,&mut NextImpl<Type>
没有实现该特征,只有NextImpl<Type>
可以实现!
您的Sized
问题非常相似。该函数定义为
fn iterator_next2<It: Iterator>(iter: &mut It) -> Option<It::Item>
也就是说,它期望对某些实现Iterator
的具体类型的可变引用。您的来电通过&mut Iterator
- 特征对象。特征对象是对没有已知大小的东西的引用,只知道实现特征的方法。既然你不关心被引用的东西的大小,正确的选择就是像你一样声明:
fn iterator_next3<It: Iterator + ?Sized>(iter: &mut It) -> Option<It::Item> {
iter.next()
}
这非常令人困惑,所以如果我需要尝试以不同的方式解释它,请告诉我。