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

Reply via email to