You should be able to just use .take() instead of invoking util::replace(), 
although the end-result should be the same.

    let root = self.levels[last].root.take();

-Kevin

On Aug 20, 2013, at 7:35 PM, Niko Matsakis <[email protected]> wrote:

> There may be another way, but one safe option is to use util::replace
> to always set the `root` field to None but preserve the old value, as
> shown below (this code compiles).
> 
> In general, the rule you are running into (which prevents mutation to
> the path that contains a borrowed &mut) is one that I have gone back
> and forth on. I have to go consult my notes as to the reason it is
> setup the way it is; it may be that we could potentially loosen the
> rule in this case, but I seem to recall that doing so had dangerous
> consequences that I cannot remember at the moment.
> 
>> /// Iterate and mutate on a tree map in an arbitrary order.
>> impl<'self, T> Iterator<(&'self Path, &'self mut T)> for
>> TreeMapMutIterator<'self, T> {
>>    /// Move to the next value contained in the tree map.
>>    fn next(&mut self) -> Option<(&'self Path, &'self mut T)> {
>>        if self.levels.len() == 0 {
>>            None
>>        } else {
>>            let last = self.levels.len() - 1;
>>            let root = util::replace(&mut self.levels[last].root, None);
>>            match root {
>>                Some(&ref mut entry) => {
>>                    let path = &entry.path;
>>                    let value = &mut entry.value;
>>                    Some((path, value))
>>                }
>>                None => {
>>                    match self.levels[last].iterator.next() {
>>                        Some((_atom, treemap)) => {
>>                            self.levels.push(fail!());
>>                        }
>>                        None => {
>>                            self.levels.pop();
>>                        }
>>                    }
>>                    self.next()
>>                }
>>            }
>>        }
>>    }
>> }
> 
> 
> Niko
> 
> 
> On Tue, Aug 20, 2013 at 05:50:31PM +0300, Oren Ben-Kiki wrote:
>> Here is the heart of the code, maybe it will be clearer why I had to use
>> unsafe (or, maybe, how I could avoid it):
>> 
>> /// A path is just an array of atoms.
>> #[deriving(Eq, TotalEq, Ord, TotalOrd, Clone, IterBytes)]
>> pub struct Path {
>>    /// The array of atoms the path consists of.
>>    pub atoms: ~[Atom],
>> }
>> 
>> /// An entry contained in the tree map.
>> #[deriving(Eq, TotalEq, Ord, TotalOrd)]
>> pub struct TreeMapEntry<T> {
>>    /// The full path of the entry.
>>    path: Path,
>> 
>>    /// The value of the entry.
>>    value: T,
>> }
>> 
>> /// A tree map holds values of some arbitrary type, indexed by a path.
>> pub struct TreeMap<T> {
>>    /// The entry of this node, if any.
>>    priv entry: Option<TreeMapEntry<T>>,
>> 
>>    /// The sub-trees under this node, if any.
>>    priv sub_trees: HashMap<Atom, ~TreeMap<T>>
>> }
>> 
>> /// Iterate and mutate on a single level of the tree map.
>> struct LevelMutIterator<'self, T> {
>>    /// The root node to return the value of (as the 1st result).
>>    root: Option<&'self mut TreeMapEntry<T>>,
>> 
>>    /// The iterator at the current level of the tree.
>>    iterator: HashMapMutIterator<'self, Atom, ~TreeMap<T>>,
>> }
>> 
>> /// Iterate and mutate on a tree map in an arbitrary order.
>> pub struct TreeMapMutIterator<'self, T> {
>>    /// The iterators of all levels we have reached so far.
>>    priv levels: ~[LevelMutIterator<'self, T>]
>> }
>> 
>> /// Iterate and mutate on a tree map in an arbitrary order.
>> impl<'self, T> Iterator<(&'self Path, &'self mut T)> for
>> TreeMapMutIterator<'self, T> {
>>    /// Move to the next value contained in the tree map.
>>    fn next(&mut self) -> Option<(&'self Path, &'self mut T)> {
>>        if self.levels.len() == 0 {
>>            None
>>        } else {
>>            unsafe {
>>                let last: *mut LevelMutIterator<'self, T> = &mut
>> self.levels[self.levels.len() - 1];
>>                match (*last).root {
>>                    Some(ref mut entry) => {
>>                        let path = &entry.path;
>>                        let value = &mut entry.value;
>>                        // TRICKY: This makes the entry inaccessible, which
>> is
>>                        // why we took the returned path and value above.
>>                        (*last).root = None;
>>                        Some((path, value))
>>                    }
>>                    None => {
>>                        match self.levels[self.levels.len() -
>> 1].iterator.next() {
>>                            Some((_atom, treemap)) => {
>>                                self.levels.push(treemap.level_mut_iter());
>>                            }
>>                            None => {
>>                                self.levels.pop();
>>                            }
>>                        }
>>                        self.next()
>>                    }
>>                }
>>            }
>>        }
>>    }
>> }
>> 
>> I tried for around a day to make this work without the unsafe, to no avail.
>> The trick is I want to take the value out of the option (leaving None
>> behind), and return the value. I'm probably missing some solution which may
>> be obvious to a non-newbie to Rust...?
> 
>> _______________________________________________
>> 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

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

Reply via email to