Подтвердить что ты не робот

Почему Cell in Rust может использоваться только для типов Copy, а не для клонирования?

Документация стандартной библиотеки Rust утверждает, что Cell может использоваться только для типов Copy и что во всех остальных случаях следует использовать RefCell, но не объясняет, почему именно.

Изучив документацию и код как Cell, так и RefCell, единственной точкой, которая кажется важной, является функция get Cell. Если значение является типом Copy, то можно просто вернуть такую ​​копию. Но почему клон недостаточно хорош?

Можно непосредственно реализовать функцию set поверх RefCell:

fn set<T>(r: &RefCell<T>, v: T) {
    *r.borrow_mut() = v
}

Это работает только до тех пор, пока никто другой не держит ссылку на значение. Но если значение может быть клонировано, можно просто сделать это:

fn get<T: Clone>(r: &RefCell<T>) -> T {
    r.borrow().clone()
}

Наличие типа Cell, работающего с типами Clone, позволит избежать накладных расходов на проверку времени выполнения. Я что-то пропустил здесь?

4b9b3361

Ответ 1

Это необоснованно. Комментарий ДК. находится на правильном пути, но вам даже не нужна паника, чтобы вызвать хаос. Одним из проблемных сценариев является следующее:

  • Ячейки (вместе с Option) позволяют создавать циклы, т.е. самореферентные типы
  • Реализация Clone получает ссылку &self
  • При наличии цикла реализация Clone может, таким образом, получить доступ к клеточке, которая клонируется
  • Поэтому клонируемый объект может перезаписывать себя, в то время как он имеет обычный заимствование для себя (а именно &self)
  • Переписывание во время заимствования является необоснованным, поскольку оно допускает произвольное произвольное наказание и другое плохое поведение. Например, предположим, что поле Result<T, E>, изначально Ok(T), возьмите ссылку на T внутри и перезапишите Result с помощью Err(R). Затем &T внезапно ссылается на значение E.

Кредит для этого примера относится к Huon Wilson, см. thread.rust-lang.org Почему Cell требует Copy вместо Clone?. Его рецензия касается более структурных причин ограничений и включает полный пример кода.

Ответ 2

Вот мое мнение, но я не могу привязать его прямо к реальной причине, что такое ограничение существует.

Я думаю о копии как "дешевой" (например, копировании нескольких бит), а клон - "дорогой" (например, вызов функции или изменение данных). Если бы такая ячейка использовала Clone, ей было бы поручено дублировать базовое значение при каждом использовании (cell.get()). Например, использование CloneCell<Vec<T>> будет означать, что для каждого cell.get() требуется вызвать вызов распределителя памяти. Это не очень хорошая идея.

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