Today I think the only way you could do this is like so:

  fn extendH(v:&mut HasList) {
       let w = util::replace(&mut v.l, ~MT);
       v.l = ~Cons(3, w);
  }

Or, written using the swap operator:

  fn extendH(v:&mut HasList) {
       let mut w = ~MT;
       v.l<->  w;
       v.l = ~Cons(3, w);
  }

This unfortunately requires a temporary allocation of ~MT to "plug into" v.l in the 
interim before you have updated its value.  You could avoid this by using an Option type, which at 
least wouldn't require allocation.  However, I think we could also add a helper like 
`util::replace()` that updates the value "in-place", as you originally wanted.  I imagine 
something like this:

    fn update<T>(v: &mut T, f: &fn(T) -> T) { unsafe { ... } }

and then you would write:

  fn extendH(v:&mut HasList) {
        util::update(&mut v.l, |l| ~Cons(3, l));
  }




Niko

John Clements wrote:
I'm trying to figure out a clean way to juggle ownership to rearrange the parts 
of a mutable structure.  Specifically, in the example below, I want to take a 
field containing an owned pointer and mutate it to point to a different 
structure that contains the original value. After the move, the pointer is 
again owned by the same structure, but the borrow checker is unhappy with me.

I've tried a bunch of variations using intermediate variables and 'match'ing, 
but none of them have worked. Actually, it seems like I need an atomic 
operation like the one described by Tucker Taft, where I move and 
simultaneously set-to-null….

Is there some way to make this happen?[*]


// a list that uses owned pointers
pub enum IntList {
     MT,
     Cons(int,~IntList)
}

// a structure containing a list
pub struct HasList {
     a : ~str,
     l : ~IntList
}

// add a '3' at the head of the contained list
fn extendH(v:&mut HasList) {
     v.l = ~Cons(3,v.l);
}

#[test] fn t1() {
     let h = ~mut HasList {a:~"bogus",l:~MT};
     extendH(h);
}

==>

rustc --test foo.rs
Running /usr/local/bin/rustc:
foo.rs:13:4: 13:5 error: use of partially moved value: `v`
foo.rs:13     v.l = ~Cons(3,v.l);
               ^
foo.rs:13:18: 13:21 note: field of `v` moved here because the field has type 
~IntList, which is moved by default (use `copy` to override)
foo.rs:13     v.l = ~Cons(3,v.l);
                             ^~~
foo.rs:13:4: 13:5 error: use of partially moved value: `v`
foo.rs:13     v.l = ~Cons(3,v.l);
               ^
foo.rs:13:18: 13:21 note: field of `v` moved here because the field has type 
~IntList, which is moved by default (use `copy` to override)
foo.rs:13     v.l = ~Cons(3,v.l);
                             ^~~
error: aborting due to 2 previous errors



John


[*] Naturally, I could just use a vector rather than the cons-pair 
representation; I'm not looking for that answer.

_______________________________________________
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