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