Преобразование ссылок

Ü позволяет преобразовывать ссылки одного вида в ссылки другого вида, явным или неявным образом.

Преобразование изменяемости

Изменяемую (mut) ссылку можно неявно преобразовать в неизменяемую (imut) ссылку.

fn Bar( i32 &imut x );
struct S{ i32 &imut r; }
fn Foo()
{
    var i32 mut x= 0;
    var i32 &mut r= x;
    Bar( r ); // Неявное преобразование изменяемой ссылки "r" в неизменяемую ссылку - аргумент функции.
    var S s{ .r= r }; // Неявное преобразование изменяемой ссылки "r" в неизменяемую ссылку - поле структуры.
    var i32 &imut r2= r;// Неявное преобразование изменяемой ссылки "r" в неизменяемую локальную ссылку.
}

Преобразование типа в void

Ссылку любого типа можно преобразовать в ссылку на void. Это может быть необходимо в низкоуровневом коде и при в взаимодействии с C кодом.

fn Bar( void & v );
struct S{ void & r; }
fn Foo()
{
    var i32 x= 0;
    var i32 & r= x;
    Bar( r ); // Неявное преобразование изменяемой ссылки "r" в ссылку типа "void" - аргумент функции.
    var S s{ .r= r }; // Неявное преобразование изменяемой ссылки "r" в ссылку типа "void" - поле структуры.
    var void & r2= r;// Неявное преобразование изменяемой ссылки "r" в локальную ссылку типа "void".
}

Преобразование в ссылку на предковый тип

Ссылку на полиморфный класс возможно преобразовать в ссылку на любого из его предков.

class A interface {}
class B interface : A {}
class C polymorph {}
class D : C, B {}

fn FooA( A& a );
fn FooB( B& b );
fn FooC( C& c );

fn Foo()
{
    var D d;
    FooA(d); // Преобразование ссылки в ссылку на непрямого предка (дедушку).
    FooB(d); // Преобразование ссылки в ссылку на реализуемый интерфейс.
    FooC(d); // Преобразование ссылки в ссылку на базовый класс.
}

Явные преобразования ссылок

Иногда бывает необходимо явно преобразовать ссылку. Для этих целей служат операторы явного преобразования.

Оператор cast_ref используется для явного преобразования типа ссылки. Для этого оператора надо указать тип назначения.

class A polymorph {}
class B : A {}

fn Foo( A& a );
fn Foo( B& b );

fn Foo()
{
    var B b;
    Foo( cast_ref</ A />(b) ); // Ссылка на "b" будет преобразована в ссылку на "A", после чего вызовется функция fn Foo( A& a );
}

Оператор cast_imut используется для преобразования изменяемых ссылок в неизменяемые.

fn Foo( i32 &mut i );
fn Foo( i32 &imut i );

fn Foo()
{
    var i32 mut x=0;
    Foo( cast_imut(x) ); // Изменяемая ссылка на "x" будет преобразована неизменяемую ссылку, после чего вызовется функция fn Foo( i32 &imut i );
    var i32 imut y= 0;
    var i32 &imut y_ref= cast_imut(y); // Оператор "cast_imut" в данном случае оставит модификатор изменяемойсти ссылки, т. к. выражение внутри него - неизменяемая ссылка.
}

Оператор cast_ref_unsafe , аналогично оператору cast_ref, используется для явного преобразования типа ссылки. Но в отличие от последнего им можно преобразовать ссылку в неродственный тип. Из-за этого данный оператор можно использовать только в unsafe коде.

fn Foo()
{
    var i32 mut x= 0;
    var void &x_ref_v= x;
    unsafe
    {
        var i32 &x_ref_i= cast_ref_unsafe</i32/>(x_ref_v); // Ссылка на "void" пребразована в ссылку на "i32"
    }
}

Оператор cast_mut , используется для преобразования неизменяемых ссылок в изменяемые. Использовать этот оператор можно только в unsafe коде.

fn Foo()
{
    var i32 imut x= 0;
    unsafe
    {
        ++ cast_mut(x); // Неизменяемая ссылка на "x" преобразуется в изменяемую ссылку, с помощью которой изменяется значение, на которое указывает ссылка.
    }
}