Являются ли сырые указатели во временном порядке в Rust?

У меня есть такая функция:

extern {
    fn foo(layout: *const RawLayout) -> libc::uint8_t;
}

fn bar(layout: Layout) -> bool {
    unsafe {
        foo(&layout.into() as *const _) != 0
    }
}

Где Layout - тип с возможностью копирования, который может быть преобразован .into() a RawLayout.

Я хочу убедиться, что я понимаю, что происходит, поскольку это небезопасно. Как я понимаю, layout.into() создает временную RawLayout, тогда & берет ссылку на нее, а as *const _ преобразует ее в необработанный указатель (*const RawLayout). Затем вызывается функция foo() и возвращается, и, наконец, временная RawLayout отбрасывается.

Это правильно? Или есть какая-то сложная причина, почему я не должен этого делать?

Ответ 1

Вы правы. В этом случае foo вызывается первым, а затем RawLayout. Это объясняется в Ссылка на ржавчину (перейдите по ссылке, чтобы увидеть конкретные примеры того, как это получается на практике):

Время жизни временных значений, как правило, является самым внутренним Заявление

Однако я предпочел бы следовать совету Шеммастера. Явное введение локальной переменной помогло бы читателю сконцентрироваться на более важных вещах, например, убедиться, что небезопасный код верен (вместо того, чтобы определить точную семантику временных переменных).

Как проверить этот

Вы можете использовать приведенный ниже код, чтобы проверить это поведение:

struct Layout;
struct RawLayout;

impl Into<RawLayout> for Layout {
    fn into(self) -> RawLayout {
        RawLayout
    }
}

impl Drop for RawLayout {
    fn drop(&mut self) {
        println!("Dropping RawLayout");
    }
}

unsafe fn foo(layout: *const RawLayout) -> u8 {
    println!("foo called");
    1
}

fn bar(layout: Layout) -> bool {
    unsafe {
        foo(&layout.into() as *const _) != 0
    }
}

fn main() {
    bar(Layout);    
}

Вывод:

foo called
Dropping RawLayout