I think I should have put my code to gist to track changes easily.
Amending: https://gist.github.com/dpx-infinity/6751843

2013/9/29 Vladimir Matveev <[email protected]>:
> 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