2017-10-19 24 views
14

Tại sao n1_mut vẫn hợp lệ trong ví dụ này? Nó đã được chuyển vào Option::Some vì vậy nó không phải là không hợp lệ?Tại sao việc gán cho một thành viên của một con trỏ vẫn hợp lệ sau khi con trỏ được di chuyển?

struct MyRecordRec2<'a> { 
    pub id: u32, 
    pub name: &'a str, 
    pub next: Box<Option<MyRecordRec2<'a>>> 
} 

#[test] 
fn creating_circular_recursive_data_structure() { 
    let mut n1_mut = MyRecordRec2 { 
     id: 1, 
     name: "n1", 
     next: Box::new(None) 
    }; 

    let n2 = MyRecordRec2 { 
     id: 2, 
     name: "n2", 
     next: Box::new(Some(n1_mut)) 
    }; 

    //Why is n1_mut still valid? 
    n1_mut.next = Box::new(Some(n2)); 
} 

Sau đây không biên dịch với các "sử dụng các giá trị chuyển" quen thuộc lỗi:

#[test] 
fn creating_and_freezing_circular_recursive_data_structure() { 
    let loop_entry = { 
     let mut n1_mut = MyRecordRec2 { 
      id: 1, 
      name: "n1", 
      next: Box::new(None), 
     }; 

     let n2 = MyRecordRec2 { 
      id: 2, 
      name: "n2", 
      next: Box::new(Some(n1_mut)), 
     }; 

     n1_mut.next = Box::new(Some(n2)); 

     n1_mut 
    }; 
} 
error[E0382]: use of moved value: `n1_mut` 
    --> src/main.rs:44:9 
    | 
39 |    next: Box::new(Some(n1_mut)), 
    |         ------ value moved here 
... 
44 |   n1_mut 
    |   ^^^^^^ value used here after move 
    | 
    = note: move occurs because `n1_mut` has type `MyRecordRec2<'_>`, which does not implement the `Copy` trait 
+0

Thú vị. Không chắc chắn nếu điều này được coi là một lỗi - Tôi không nghĩ rằng bạn có thể gây ra an toàn vì không có cách nào để đọc bộ nhớ sau đó. Nhưng nếu bạn giữ một con trỏ thô vào ngăn xếp, bạn có thể nói rằng 'n1Mut.next' thực sự được thiết lập: https://play.rust-lang.org/?gist=d41422bfd142c289667e7c2fb3183be0&version=undefined – trentcl

+0

Thật thú vị, thậm chí không thể sử dụng 'n1_mut.next' sau. Ngoài ra, thêm một 'Drop' thực hiện nguyên nhân:" lỗi [E0383]: một phần reinitialization của uninitialized cấu trúc 'n1_mut'" –

Trả lời

8

này không có bất cứ điều gì để làm với được một con trỏ hay không; này hoạt động cũng như:

#[derive(Debug)] 
struct NonCopy; 

#[derive(Debug)] 
struct Example { 
    name: NonCopy, 
} 

fn main() { 
    let mut foo = Example { 
     name: NonCopy, 
    }; 

    drop(foo); 

    foo.name = NonCopy; 
} 

Mặc dù tôi không thể tìm thấy câu hỏi tương tự SO mà tôi biết tôi đã nhìn thấy trước, đây quote from nikomatsakis mô tả nó:

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

Ngoài ra còn có cuộc thảo luận về the Rust subreddit, mà liên kết tới Rust issue 21232: "borrow-checker allows partial reinit of struct that has been moved away, but no use of it"

Về mặt khái niệm, có một lá cờ cho mỗi trường trong cấu trúc ngoài cấu trúc - tôi thích nghĩ đến Chris Morgan's cardboard box analogy. Bạn có thể di chuyển ra khỏi lĩnh vực một struct thuộc sở hữu của quá lâu như bạn di chuyển trở lại trước khi sử dụng các cấu trúc:

drop(foo.name); 
foo.name = NonCopy; 

println!("{:?}", foo); 

Rõ ràng, kể từ năm 2014, không ai làm phiền để đưa vào các nỗ lực để cho phép đánh dấu toàn bộ cấu trúc như hợp lệ một lần nữa khi các trường được điền lại.

Thực tế, bạn không thực sự cần chức năng này vì bạn chỉ có thể gán toàn bộ biến cùng một lúc. Việc triển khai hiện tại quá an toàn vì Rust đang ngăn cản bạn làm điều gì đó có vẻ OK.

Các vấn đề liên quan