I’m having trouble using a generic function that takes a generic trait object as a parameter. When I try to call the function, the compiler complains “error: the trait Next
is not implemented for the type &'a mut Next<Type=Type> + 'a
[E0277]”. In my opinion, the Next
trait is object-safe for any parameter Type
, so Next
should be implemented by any &Next<Type>
(by my reading of Huon’s Object-Safety article); is there any way to check that it is object-safe?
Incidentally, I’m having no problem doing pretty much the same thing with an Iterator
, and I don’t know how that is different.
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());
}
I think you are adding an extra layer of indirection. The method call
self.delegate.next()
desugars intoNext::next(self.delegate)
in this case - no automatic referencing (mutable or otherwise) is needed.The error message is confusing because you have two levels of reference. Your trait is written:
Which means that you always have to pass in a
&mut Foo
. However, you were taking a second mutable reference, making the argument type&mut &mut NextImpl<Type>
. The first&mut
is matched by the function parameter, but then the rest of the type needs to implementNext
. However,&mut NextImpl<Type>
does not implement that trait, onlyNextImpl<Type>
does!Your
Sized
problem is very similar. The function is defined asThat is, it expects a mutable reference to some concrete type that implements
Iterator
. Your call passes a&mut Iterator
- a trait object. A trait object is a reference to something without a known size, it is only known to implement the methods of the trait. Since you don't care about the size of the thing being referred to, the correct option is to declare that, as you did:This is super confusing, so let me know if I need to attempt to explain it differently.