Modifying a moved field

Hello!

Why am I allowed to do this?:

I assume the Foo struct has been shallow copied so I can overwrite the contents in the stack without a segfault, but I thought the ownership had moved and that rustc would stop me from doing this.

Cheers,

Phil

if you try to use the move value, for example printing f.name, then it will not work.

I guess because you can not ‘use’ the moved value, so its not like it matters that you can change the field?

This seems nonsensical to me. There’s no utility to being able to assign a field of a moved value, and it certainly doesn’t do what a casual reader would think it does.

I agree, this should be disallowed.

I thought this would actually “re-validate” the structure and allow you to use it again, but it doesn’t, so this seems like a borrowck bug.

In general moves are tracked at a pretty narrow level of granularity. We intend to eventually permit you to “fill” both fields back in and then use the structure again. I guess that doesn’t work today. I have to go look again at the moves code, but I think in general one of the things I’d like to pursue post 1.0 is extending the type system to deal better with things that have been moved from (in particular I want to support moves out of &mut pointers, so long as you restore the value before doing anything fallible). Anyway I think this example more-or-less falls out of treating things in a general way, though you could imagine rules that say “if you move f, you can never again touch any subfields of f without restoring f as a unit”.

> In general moves are tracked at a pretty narrow level of granularity.

That makes sense, and it would make closures a lot nicer (rather than individually borrowing members of a struct), but I notice it doesn’t seem to work that way right now:

#[deriving(Show)]

struct Bar;

struct Foo {

pub foo: Bar,

pub bar: Bar,

}

fn main() {

let mut x = Foo { foo: Bar, bar: Bar };

let c = || {

x.foo = Bar;

};

println!("{}", x.bar); // error: cannot borrow x.bar as immutable because x is also borrowed as mutable

}

> you could imagine rules that say “if you move f, you can never again touch any subfields of f w ithout restoring f as a unit”.

I like this as a nice middle ground. Restoring the individual fields of f seems error prone and difficult to read - I’d be very inclined to have the definition of the struct open in another tab, just to make sure all the fields really are being restored. Restoring as a unit makes sure it all happens in one sane place, and helps assure the reader that all the fields really are restored at that point.

Oops, sorry, aside from the broken code sample, @cgaebel showed me that move closures totally do this.

That is correct, closures always borrow (or move) the variables they touch. This may change in the future. This is separate from the tracking within a single fn body, however, which is done at a finer level of granularity.

Actually, that surprises me. I’ll have to look again, but I thought we always modeled closure captures at the variable level at the moment, not subpaths.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.