Hi all,

The problem I'm writing about in this message follows from the one I
have described in my other message:
https://mail.mozilla.org/pipermail/rust-dev/2013-August/005281.html .
I believe I'm now able to formulate it more clearly.

Consider the following example code:

trait Walker {  // Some business-logic trait
    fn walk(&mut self);
}

// 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 }
    }
}

// Here is the problem: we cannot implement Walker trait!
impl<'self> Walker for ReaderContainer<'self> {
    // See below for concrete errors description
    fn walk(&mut 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();
}


This program does not compile with the following error:

temp.rs:52:17: 52:30 error: cannot infer an appropriate lifetime due
to conflicting requirements
temp.rs:52         for b in self.iter() {
                            ^~~~~~~~~~~~~
temp.rs:52:17: 52:22 note: first, the lifetime cannot outlive the
expression at 52:17...
temp.rs:52         for b in self.iter() {
                            ^~~~~
temp.rs:52:17: 52:22 note: ...due to the following expression
temp.rs:52         for b in self.iter() {
                            ^~~~~
temp.rs:52:17: 52:30 note: but, the lifetime must be valid for the
method call at 52:17...
temp.rs:52         for b in self.iter() {
                            ^~~~~~~~~~~~~
temp.rs:52:17: 52:22 note: ...due to the following expression
temp.rs:52         for b in self.iter() {
                            ^~~~~
error: aborting due to previous error

This is somewhat expected, because `self` in `walk()` method
implementation does not have 'self lifetime, so it is impossible to
call `iter()` method which needs concrete 'self lifetime. But I cannot
mark it with 'self lifetime either! If I do mark it with 'self:

    fn walk(&'self mut self) {  // <<<
        for b in self.iter() {
            println(fmt!("byte %?", b));
        }
    }

Then the program fails to compile with another message:

temp.rs:51:4: 55:5 error: method `walk` has an incompatible type:
expected concrete lifetime, but found bound lifetime parameter &
temp.rs:51     fn walk(&'self mut self) {  // <<<
temp.rs:52         for b in self.iter() {
temp.rs:53             println(fmt!("byte %?", b));
temp.rs:54         }
temp.rs:55     }
temp.rs:51:29: 55:5 note: expected concrete lifetime is the lifetime
&'self  as defined on the block at 51:29
temp.rs:51     fn walk(&'self mut self) {  // <<<
temp.rs:52         for b in self.iter() {
temp.rs:53             println(fmt!("byte %?", b));
temp.rs:54         }
temp.rs:55     }
error: aborting due to previous error

This is also expected: adding 'self lifetime violates `Walker` trait
signature, in which `walk()` method has plain `&mut self` parameter.

So, this is kind of dead end. I think this problem may be formulated
in short as follows: how to implement generic traits for structures
which have lifetime parameters which are used for `self` parameter in
structure methods implementations?

How to do what I want to do? Is it possible at all?

Regards,
Vladimir.
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to