История изменений
Исправление Siborgium, (текущая версия) :
Речь о части одной глобальной проблемы с move в расте. Код по ссылке прячет реализацию в hashbrown::hash_map as base;
, никакой реализации реально там не приведено.
В расте move осуществляется всегда. Я не могу написать код вида
let v: V = ...;
let k: K = ...;
let inserted = map.insert(&k, v);
if !inserted {
foo(v);
}
потому что владение v безусловно передается в insert. Расту приходится обходить это повсеместно, возвращая v обратно в случае неудачи. Это, мягко говоря, субоптимальное решение. Решения этой проблемы без unsafe не существует – это ограничение базовой модели.
Нельзя осуществлять доступ к глобальным переменным без unsafe. Это ограничение бывает оправдано, но никакого анализа не осуществляется, и абсолютно безопасные случаи оказываются заблокированными. Либо программист анализирует свой код сам и расставляет unsafe там, где он уверен, что все будет в порядке, либо… Заворачивает все в написанные поверх unsafe чьи-то обертки.
И так далее, и так далее. Rc
, кстати, нельзя написать без unsafe.
struct Rc<T> {
t: T,
c: u32,
}
impl<T> Clone for Rc<T> {
fn clone(r: &Self) {
// r иммутабельный, не могу увеличить счетчик ссылок
}
}
Хотя vertexua, конечно, прав – сделать плохо там сильно сложнее, особенно программисту, мало знакомому с низкоуровневыми языками. Сделать хорошо, впрочем, тоже.
Исходная версия Siborgium, :
Речь о части одной глобальной проблемы с move в расте. Код по ссылке прячет реализацию в hashbrown::hash_map as base;
, никакой реализации реально там не приведено.
В расте move осуществляется всегда. Я не могу написать код вида
let v: V = ...;
let k: K = ...;
let inserted = map.insert(&k, v);
if !inserted {
foo(v);
}
потому что владение v безусловно передается в insert. Расту приходится обходить это повсеместно, возвращая v обратно в случае неудачи. Это, мягко говоря, субоптимальное решение. Решения этой проблемы без unsafe не существует – это ограничение базовой модели.
Нельзя осуществлять доступ к глобальным переменным без unsafe. Это ограничение бывает оправдано, но никакого анализа не осуществляется, и абсолютно безопасные случаи оказываются заблокированными. Либо программист анализирует свой код сам и расставляет unsafe там, где он уверен, что все будет в порядке, либо… Заворачивает все в написанные поверх unsafe чьи-то обертки.
И так далее, и так далее. Rc
, кстати, нельзя написать без unsafe.
struct Rc<T> {
t: T,
c: u32,
}
impl<T> Clone for Rc<T> {
fn clone(r: &Self) {
// r иммутабельный, не могу увеличить счетчик ссылок
}
}