I find a solution by removing the ~ to Base trait.
The code

//(First and Second think as defined earlier)


enum BaseImpl    {
    FirstThinkImpl(FirstThink),
    SecondThinkImpl(SecondThink),
}


struct Container    {
    nodeList: Vec<~BaseImpl>,
}

impl<'a> Container    {

    fn iter_base(&'a self) -> BaseItems<'a> {
           let iter = self.nodeList.iter();
           BaseItems{ iter : iter }
    }

}


struct BaseItems<'a> {
    iter : Items<'a, ~BaseImpl>
}

impl<'a> Iterator<&'a Base> for BaseItems<'a> {
    fn next(&mut self) -> Option<&'a Base>    {
        match self.iter.next() {
            Some(ref baseimpl) => {
                Some(match ***baseimpl{
                    FirstThinkImpl(ref first) => first as &'a Base,
                    SecondThinkImpl(ref second)=> second as &'a Base,
                })
            },
            None => None,
        }
    }
}

Now it compile.

So I try to define a mutable iterator like the immuable and with similar code I have again the lifetime compile error :


struct BaseMutItems<'a> {
    iter : MutItems<'a, ~BaseImpl>
}

impl<'a> Iterator<&'a mut Base> for BaseMutItems<'a> {
    fn next(&mut self) -> Option<&'a mut Base> {
        match self.iter.next() {
            Some(ref mut baseimpl) => {
                Some(match ***baseimpl{
                    FirstThinkImpl(ref mut first) => first as &'a mut Base,
SecondThinkImpl(ref mut second)=> second as &'a mut Base,
                })
            },
            None => None,
        }
    }
}

error :
test_enum.rs:125:36: 125:49 error: lifetime of `baseimpl` is too short to guarantee its contents can be safely reborrowed test_enum.rs:125 FirstThinkImpl(ref mut first) => first as &'a mut Base,

I can't see what's going wrong.


I put all the code if someone want to test :

use std::iter::Iterator;
use std::slice::{Items, MutItems};

trait Base    {
  fn set_something(&mut self);
  fn isSecondThink(&self) -> bool;
}

struct FirstThink{
    count1: int,
}

impl Base for FirstThink    {
fn set_something(&mut self) {println!("ici First count:{:?}", self.count1); self.count1+=1;}
    fn isSecondThink(&self) -> bool  {false}
}

struct SecondThink{
    count2: int,
}

impl Base for SecondThink    {
fn set_something(&mut self) {println!("ici Second count:{:?}", self.count2); self.count2+=1;}
    fn isSecondThink(&self) -> bool  {true}
}

enum BaseImpl    {
    FirstThinkImpl(FirstThink),
    SecondThinkImpl(SecondThink),
}

fn some_second_process(think: &mut SecondThink)    {
    think.set_something();
}

struct Container    {
    nodeList: Vec<~BaseImpl>,
}

impl<'a> Container    {
    fn add_FirstThink(&mut self, think: FirstThink)    {
        self.nodeList.push(~FirstThinkImpl(think));
    }
    fn add_SecondThink(&mut self, think: SecondThink)    {
        self.nodeList.push(~SecondThinkImpl(think));
    }


    fn iter_base(&'a self) -> BaseItems<'a> {
           let iter = self.nodeList.iter();
           BaseItems{ iter : iter }
    }

    fn iter_second(&'a self) -> SecondItems<'a> {
           let iter = self.nodeList.iter();
           SecondItems{ iter : iter }
    }

    fn mut_iter_base(&'a mut self) -> BaseMutItems<'a> {
           let iter = self.nodeList.mut_iter();
           BaseMutItems{ iter : iter }
    }

fn appli_secondthink_someprocess(&mut self, fct : fn (&mut SecondThink)) {
        for think in self.nodeList.mut_iter() {
            match **think {
                FirstThinkImpl(first) => println!(""),
                SecondThinkImpl(ref mut second)=> fct(second),
            }
        }

    }

}

struct BaseItems<'a> {
    iter : Items<'a, ~BaseImpl>
}

impl<'a> Iterator<&'a Base> for BaseItems<'a> {
    fn next(&mut self) -> Option<&'a Base>    {
        match self.iter.next() {
            Some(ref baseimpl) => {
                Some(match ***baseimpl{
                    FirstThinkImpl(ref first) => first as &'a Base,
                    SecondThinkImpl(ref second)=> second as &'a Base,
                })
            },
            None => None,
        }
    }
}


struct SecondItems<'a> {
    iter : Items<'a, ~BaseImpl>
}

impl<'a> Iterator<&'a SecondThink> for SecondItems<'a> {
    fn next(&mut self) -> Option<&'a SecondThink>    {
        match self.iter.next() {
            Some(ref baseimpl) => {
                match ***baseimpl{
                    FirstThinkImpl(ref first) => self.next(),
                    SecondThinkImpl(ref second)=> Some(second),
                }
            },
            None => None,
        }
    }
}


struct BaseMutItems<'a> {
    iter : MutItems<'a, ~BaseImpl>
}

impl<'a> Iterator<&'a mut Base> for BaseMutItems<'a> {
    fn next(&mut self) -> Option<&'a mut Base> {
        match self.iter.next() {
            Some(ref mut baseimpl) => {
                Some(match ***baseimpl{
                    FirstThinkImpl(ref mut first) => first as &'a mut Base,
SecondThinkImpl(ref mut second)=> second as &'a mut Base,
                })
            },
            None => None,
        }
    }
}



#[main]
fn main() {
    let first = FirstThink{count1:0};
    let second = SecondThink{count2:0};

    let mut container = Container{nodeList: Vec::new()};
    container.add_FirstThink(first);
    container.add_SecondThink(second);
    container.appli_secondthink_someprocess(some_second_process);
    container.appli_secondthink_someprocess(some_second_process);
    for think in container.iter_base()    {
        println!("ici Second count:{:?}", think.isSecondThink());
    }

    for think in container.iter_second()    {
        println!("ici Second count:{:?}", think.isSecondThink());
    }
    container.appli_secondthink_someprocess(some_second_process);
}

Le 07/04/2014 13:17, Philippe Delrieu a écrit :
I try to implement the iterator like that:


struct BaseItems<'a> {
    iter : Items<'a, ~BaseImpl>
}

impl<'a> Iterator<&'a ~Base> for BaseItems<'a> {
    fn next(&mut self) -> Option<&'a ~Base>    {
        match self.iter.next() {
                Some(ref baseimpl) => {
                    Some(&'a match ***baseimpl{
                        FirstThinkImpl(ref first) => *first as ~Base,
                        SecondThinkImpl(ref second)=> *second as ~Base,
                    })
                },
                None => None,
        }
    }
}

But I have a lifetime problem. The error is : borrowed value does not live long enough and reference must be valid for the lifetime &'a as defined on the block
and :
cannot move out of dereference of `&`-pointer SecondThinkImpl(ref second)=> *second as ~Base,

Another possibility:
    fn next(&mut self) -> Option<&'a ~Base>    {
        match self.iter.next() {
                Some(ref baseimpl) => {
                    Some(match ***baseimpl{
                        FirstThinkImpl(ref first) => first as &'a ~Base,
SecondThinkImpl(ref second)=> second as &'a ~Base,
                    })
                },
                None => None,
        }
    }
generate the error: non-scalar cast: `&~FirstThink` as `&'a ~Base<no-bounds>`

I try different possibility but I didn't find how to return a <'a> lifetime ~Base or Base

I remove the mut to simplify the test of the different lifetime possibilities.

Philippe

Le 07/04/2014 10:27, Rodrigo Rivas a écrit :
On Sun, Apr 6, 2014 at 7:50 PM, Philippe Delrieu
<[email protected]> wrote:
I need some more help.

The impl Iterator<&mut ~Base> for Container declaration generate the error:
error: missing lifetime specifier
So I had it but I can't manage to return the next value with the specified
life time.
The code :
impl<'a> Iterator<&'a mut  ~Base> for Container {
/// Advance the iterator and return the next value. Return `None` when
the end is reached.
     fn next(&mut self) -> Option<&'a mut ~Base>    {
         if self.iter_counter == self.nodeList.len()   {
             None
         } else  {
             self.iter_counter += 1;
             Some(&'a mut match **self.nodeList.get(self.iter_counter){
                 FirstThinkImpl(first) => first as ~Base,
                 SecondThinkImpl(second)=> second as ~Base,
             })
         }
     }
}

Generate these errors :
test_enum.rs:58:18: 61:14 error: borrowed value does not live long enough
test/test_enum.rs:58             Some(&'a mut match
Oh, I think I may have misleaded you... You cannot implement the
iterator directly in Container, because the iterator must handle the
current position, while the Container just holds the values. You need
a intermediate struct that implements the Iterator traits. That's what
the `iter()` and ' move_iter()` functions do for vectors and other
standard containers. So you'll need something along the lines of this
(disclaimer: totally untested!!):

struct Container {
     //....
     fn iter(&'a self) -> BaseItems<'a> {
            let iter = nodeList.iter();
            BaseItems{ iter : iter }
     }
}

struct BaseItems<'a> {
     iter : Items<'a, ~Base>
}

impl<'a> Iterator<&'a mut  ~Base> for BaseItems<'a> {
     //....
}

BTW, why all the double pointer in all the "&mut ~Base" instead of
just "&mut Base"?


_______________________________________________
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