2015-01-02 7 views
2

У меня есть некоторый код, который, когда упрощен, выглядит следующим образом:Могу ли я создать «небезопасное закрытие»?

fn foo() -> Vec<u8> { 
    unsafe { 
     unsafe_iterator().map(|n| wrap_element(n)).collect() 
    } 
} 

Итератор возвращает элементы, которые будут признаны недействительными, если исходные данные изменились. К сожалению, я не могу полагаться на обычный механизм ржавчины mut здесь (я делаю некоторые ... странные вещи).

Чтобы исправить небезопасность, я перемещаю итератор сразу и делаю копии каждого элемента (через wrap_element), а затем бросаю все это в Vec. Это работает, потому что ничто другое не имеет возможности войти и изменить базовые данные.

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

fn zap<F>(f: F) -> Vec<u8> 
    where F: FnOnce() -> UnsafeIter 
{ 
    f().map(|n| wrap_element(n)).collect() 
} 

fn foo() -> Vec<u8> { 
    zap(|| unsafe { unsafe_iterator() }) // Unsafe block 
} 

Моя проблема с этим решением является то, что вызов unsafe_iterator небезопасно, и это wrap_element/collect, что делает его безопасным снова. Способ структурирования кода не передает этого.

Я хотел бы как-то пометить свое закрытие как unsafe, а затем вернуть ответственность за безопасность.

ответ

1

Это не возможно создать unsafe замыкание в том же духе, как unsafe fn, так как закрытие просто анонимные типы с реализациями Fn, FnMut и/или FnOnce семейство черт. Поскольку эти черты не имеют методов unsafe, невозможно создать закрытие, которое должно быть вызвано unsafe.

Вы можете создать второй набор признаков закрытия с помощью методов unsafe, а затем написать для них варианты реализации, но вы потеряете большую часть сахара закрытия.

+0

Создание нового набора признаков - интересная идея! Я полагаю, что сахарирование довольно привязано к компилятору и что я ничего не могу сделать, как конечный пользователь, чтобы украсть его для новых качеств? – Shepmaster

+0

Возможно, вы сможете сделать что-то вроде одеяла, чтобы реализовать новые черты для старых черт, тогда вы получите неявное «преобразование» из синтаксиса закрытия в небезопасные черты. Я все равно не получу функциональный синтаксис вызова, но я думаю, что это прекрасный компромисс. – reem

+0

[Я дал этот снимок] (http://is.gd/OgyWaO), но это не так полезно, как могло бы быть. Проблема в том, что компилятор все еще жалуется, когда мы «вызываем» небезопасное fn в закрытии, потому что он не знает, что «небезопасный» будет передан, поэтому нет шансов использовать сахар. – Shepmaster

Смежные вопросы