В действительности, вам не нужны эти функции, так как вы можете просто назначить всю переменную сразу. Текущая реализация чрезмерно безопасна, поскольку Rust не позволяет вам делать что-то, что кажется нормальным.

уn1_mut все еще действителен в этом примере? Он был перенесен вOption::Some так не должно ли это быть недействительным?

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

Следующее не компилируется со знакомой ошибкой «использования перемещенного значения»:

#[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
 Matthieu M.19 окт. 2017 г., 19:19
Интересно, что даже невозможно использоватьn1_mut.next после. Кроме того, добавивDrop причины реализации: "ошибка [E0383]: частичная повторная инициализация неинициализированной структурыn1_mut"
 trentcl19 окт. 2017 г., 19:00
Интересно. Не уверен, что это считается ошибкой - я не думаю, что вы можете вызвать небезопасность, потому что потом невозможно прочитать память. Но если вы сохраняете необработанный указатель на стек, вы можете сказать, чтоn1Mut.next действительно установлено:play.rust-lang.org/...

Ответы на вопрос(1)

Решение Вопроса

это работает также:

#[derive(Debug)]
struct NonCopy;

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

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

    drop(foo);

    foo.name = NonCopy;
}

Хотя я не могу найти аналогичный вопрос SO, который я знаю, я видел раньше, этоцитата из Никомацакис описывает это:

В целом ходы отслеживаются на довольно узком уровне детализации. Мы намерены в конечном итоге разрешить вам «заполнить» оба поля обратно, а затем снова использовать структуру. Я думаю, это не работает сегодня. Мне нужно еще раз взглянуть на код шагов, но я думаю, что в целом одна из вещей, которую я хотел бы продолжить, начиная с версии 1.0, - расширение системы типов, чтобы лучше справляться с вещами, которые были перемещены (в частности, я хочу поддержать). выходит за пределы указателей & mut, пока вы восстанавливаете значение, прежде чем делать что-либо ошибочное). В любом случае, я думаю, что этот пример более или менее выпадает из общего подхода к вещам, хотя вы можете представить правила, которые говорят: «если вы переместите f, вы никогда больше не сможете прикоснуться к каким-либо подполям f, не восстанавливая f как единое целое».

Там также обсуждениеРжавчина субреддит, который ссылается на Rustвыпуск 21232: «заемщик проверяет возможность частичного повторного создания структуры, которая была удалена, но не используется»

Концептуально, есть флаг для каждого из полей в структуре в дополнение к самой структуре - мне нравится думать оАналогия картонной коробки Криса Моргана, Вы можете выйти из поля собственной структуры, если вы вернетесь назад перед использованием структуры:

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

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

Очевидно, что с 2014 года никто не удосужился приложить усилия для того, чтобы пометить всю структуру как действительную после повторного заполнения полей.

В действительности, вам не нужны эти функции, так как вы можете просто назначить всю переменную сразу. Текущая реализация чрезмерно безопасна, поскольку Rust не позволяет вам делать что-то, что кажется нормальным.

Ваш ответ на вопрос