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
