Why is assigning to a member of a pointer still valid after the pointer is moved?

前端 未结 1 640
广开言路
广开言路 2021-01-17 10:35

Why is n1_mut still valid in this example? It has been moved into Option::Some so shouldn\'t it be invalid?

struct MyRecordRec2<         


        
相关标签:
1条回答
  • 2021-01-17 11:19

    This doesn't have anything to do with being a pointer or not; this works as well:

    #[derive(Debug)]
    struct NonCopy;
    
    #[derive(Debug)]
    struct Example {
        name: NonCopy,
    }
    
    fn main() {
        let mut foo = Example {
            name: NonCopy,
        };
    
        drop(foo);
    
        foo.name = NonCopy;
    }
    

    Although I can't find the similar SO question that I know I've seen before, this quote from nikomatsakis describes it:

    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".

    There's also discussion on the Rust subreddit, which links to Rust issue 21232: "borrow-checker allows partial reinit of struct that has been moved away, but no use of it"

    Conceptually, there's a flag for each of the fields in a struct in addition to the struct itself — I like to think of Chris Morgan's cardboard box analogy. You can move out of an owned struct's field so long as you move back in before using the struct:

    drop(foo.name);
    foo.name = NonCopy;
    
    println!("{:?}", foo);
    

    Evidently, since 2014, no one has bothered to put in the effort to enable marking the entire struct as valid again once the fields are re-filled.

    Realistically, you don't really need this functionality as you can just assign the entire variable at once. The current implementation is overly-safe as Rust is preventing you from doing something that seems OK.

    0 讨论(0)
提交回复
热议问题