I have a function like this:
extern {
fn foo(layout: *const RawLayout) -> libc::uint8_t;
}
fn bar(layout: Layout) -> bool {
unsafe {
foo(&layout.into() as *const _) != 0
}
}
Where Layout
is a copyable type that can be converted .into()
a RawLayout
.
I want to make sure I understand what is happening as it is unsafe. As I understand it, layout.into()
creates a temporary RawLayout
, then &
takes a reference to it, and as *const _
converts it to a raw pointer (*const RawLayout
). Then the foo()
function is called and returns, and finally the temporary RawLayout
is dropped.
Is that correct? Or is there some tricky reason why I shouldn't do this?
You are right. In this case, foo
is called first and RawLayout
is dropped afterwards. This is explained in The Rust Reference (follow the link to see concrete examples of how this works out in practice):
The lifetime of temporary values is typically the innermost enclosing statement
However, I would rather follow Shepmaster's advice. Explicitly introducing a local variable would help the reader of the code concentrate in more important things, like ensuring that the unsafe code is correct (instead of having to figure out the exact semantics of temporary variables).
You can use the code below to check this behavior:
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);
}
The output is:
foo called
Dropping RawLayout
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With