Небезопасный код

Ü по умолчанию не допускает ряд операций, считающимися небезопасными:

  • явное обращение к конструкторам или деструкторам
  • обращение к глобальным изменяемым переменным
  • разыменование сырого указателя
  • оператор cast_ref_unsafe
  • оператор cast_mut
  • инициализатор ununitialized
  • вызов unsafe функции

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

fn Foo()
{
    unsafe
    {
        var i32 mut x= uninitialized;
        x= 42;
    }
}

Внутри unsafe блока также можно объявить safe блок, чтобы на время запретить небезопасные операции

fn Bar() unsafe;
fn Foo()
{
    unsafe
    {
        Bar(); // Ок, можно звать "unsafe" функцию
        safe
        {
            Bar(); // Ошибка, здесь звать "unsafe" нельзя
        }
        Bar(); // Ок, теперь снова можно
    }
}

Кроме unsafe блоков существуют также unsafe выражения. По поведению они схожи с unsafe блоками, но действуют на уровне выражений. Аналогично с safe блоками существует и safe выражения.

fn Bar() unsafe : i32;
fn Foo()
{
   var i32 x= 2 * unsafe(Bar()); // Ок - unsafe контекст распространяется только на вызов unsafe функции.
}

Небезопасные функции

Небезопасные функции - функции, которые просто так звать не безопасно и перед вызовом которых обычно требуется соблюсти ряд условий. Небезопасные функции помечаются ключевым словом unsafe после списка аргументов функции и списка связывания ссылок. Такие функции можно звать только внутри unsafe блока. Тело unsafe функции не является unsafe блоком, если внутри неё нужно выполнить небезопасные операции, их нужно обернуть в unsafe блок.

fn Bar( i32 d ) unsafe : i32
{
    unsafe
    {
        var i32 mut x= uninitialized;
        x= 100 / d;
        return x;
    }
}

fn Foo()
{
    unsafe
    {
        Bar( 7 );
    }
}