resueltos probabilidad muestrales mendenhall medicina introducción introduccion inferencial estadística estadistica ejercicios ejemplos distribuciones distribucion bioestadistica ala 13th rust

rust - probabilidad - ¿Por qué la asignación a un miembro de un puntero sigue siendo válida después de mover el puntero?



introduccion ala probabilidad y estadistica mendenhall 13th pdf (1)

¿Por qué n1_mut sigue siendo válido en este ejemplo? Se ha movido a Option::Some entonces ¿no debería ser inválido?

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)); }

Lo siguiente no se compila con el familiar error de "uso del valor movido":

#[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


Esto no tiene nada que ver con ser un puntero o no; esto funciona también:

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

Aunque no puedo encontrar la pregunta SO similar que sé que he visto antes, esta cita de nikomatsakis lo describe:

En general, los movimientos se rastrean a un nivel bastante estrecho de granularidad. Tenemos la intención de permitirle eventualmente "llenar" ambos campos nuevamente y luego usar la estructura nuevamente. Supongo que eso no funciona hoy. Tengo que volver a mirar el código de movimientos, pero creo que, en general, una de las cosas que me gustaría seguir post 1.0 es ampliar el sistema de tipos para manejar mejor las cosas que se han movido (en particular, quiero apoyar se mueve fuera de & mut punteros, siempre y cuando restaure el valor antes de hacer cualquier cosa falible). De todos modos, creo que este ejemplo más o menos deja de tratar las cosas de una manera general, aunque podrías imaginar reglas que dicen "si mueves f, nunca más podrás tocar ningún subcampo de f sin restaurar f como una unidad".

También hay discusión sobre el subreddit de Rust , que enlaza con el problema Rust 21232: "borrow-checker permite reinicio parcial de struct que se ha movido, pero no se usa"

Conceptualmente, hay una bandera para cada uno de los campos en una estructura además de la estructura misma. Me gusta pensar en la analogía de la caja de cartón de Chris Morgan . Puedes salir del campo de una estructura propiedad siempre que vuelvas a moverte antes de usar la estructura:

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

Evidentemente, desde 2014, nadie se ha molestado en esforzarse por permitir que toda la estructura vuelva a ser válida una vez que los campos se vuelvan a llenar.

De manera realista, realmente no necesita esta funcionalidad, ya que puede asignar la variable completa a la vez. La implementación actual es demasiado segura ya que Rust le impide hacer algo que parece correcto.