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