Yes, this is what I have observed too, see issue
https://github.com/mozilla/rust/issues/9597. I didn't know that using
extra parameter with lifetime will help though. It indeed works. But I
think that polluting traits-interfaces with lifetime annotation is
wrong. Why the trait should have lifetime annotation? It is
implementation detail.
I just managed to do what I wanted with some kind of hack. The
following code compiles and works:
// Some business-logic trait
trait Walker {
fn walk(self); // Just self, without pointers
}
// ReaderContainer implementation remains the same
// A struct which is intended to be an implementor of Walker trait
// Note that it has lifetime parameter in order to work for any kind
// of pointer to a Reader
struct ReaderContainer<'self> {
priv reader: &'self Reader,
priv counter: int
}
// Some auxiliary structure for ReaderContainer
// It may be anything but it should have a reference to ReaderContainer
// We have to use lifetime parameter because this structure is 'attached'
// to ReaderContainer, hence it must be of the same lifetime
struct ReaderContainerIterator<'self> {
priv container: &'self mut ReaderContainer<'self>
}
// Some made-up implementation of iterator protocol for our
// auxiliary structure, it does not really matter
impl<'self> Iterator<u8> for ReaderContainerIterator<'self> {
fn next(&mut self) -> Option<u8> {
if self.container.counter < 10 {
self.container.counter += 1;
Some(self.container.reader.read_byte() as u8)
} else {
None
}
}
}
impl<'self> ReaderContainer<'self> {
// A constructor for ReaderContainer, nothing special
fn new<'a>(reader: &'a Reader) -> ReaderContainer<'a> {
ReaderContainer { reader: reader, counter: 0 }
}
// A method which returns our auxiliary structure, i.e. iterator
// Note that self parameter has lifetime 'self, otherwise this naturally
// does not compile
fn iter(&'self mut self) -> ReaderContainerIterator<'self> {
ReaderContainerIterator { container: self }
}
}
// And here are the changes
// We implement Walker for a reference of the specific type!
impl<'self> Walker for &'self mut ReaderContainer<'self> {
// Here self automatically is &'self mut reference, so we can safely
// use iter() method
fn walk(self) {
for b in self.iter() {
println(fmt!("byte %?", b));
}
}
}
fn main() {
use std::io;
let r = io::stdin();
let mut c = ReaderContainer::new(r);
c.walk(); // No extra parameters
}
In short, I'm implementing `Walker` trait not for
`ReaderContainer<'self>` but for `&'self mut ReaderContainer<'self>`.
This does not feel right, but I do not see immediate problems with
this solution. Maybe someone who knows more about lifetimes could
comment on this.
2013/9/29 David Renshaw <[email protected]>:
> If I drop the unused parameter, I get an internal compiler error:
> 'assertion failed: self.variance.is_some()'
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev