If I add an unused parameter of type Option<&'self ()> to the walk()
method, I can get your example to compile:
https://gist.github.com/dwrensha/29ed998566e2f9218c18

On Sat, Sep 28, 2013 at 4:42 PM, Vladimir Matveev
<[email protected]> wrote:
> 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
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to