Calling consuming methods on a raw pointer

I am wrapping some Rust code into C FFI and I got code roughly like this:

pub struct Foo { ... }

impl Foo {
    fn new() -> Self { ... }
    fn consume(self) -> u32 { ... }
}

impl Drop for Foo {
    fn drop(&mut self) { ... }
}

#[no_mangle]
pub unsafe extern "C" fn foo_new(foo: *mut Foo) {
    *foo = Foo::new();
}

#[no_mangle]
pub unsafe extern "C" fn foo_consume(foo: *mut Foo) -> u32 {
    core::ptr::read(foo).consume()
}

Obviously, the foo_consume method is not ideal. Not only it's inefficient (compiler can not optimize the read, since data behind the input pointer is considered potentially observable), but also may cause security issues if the drop implementation involves secure erasure of sensitive information (e.g. cryptographic keys).

Is it possible to somehow call a consuming method on a raw pointer? For large enough structs compiler generates code which passes self via pointer, so ABI-wise it can be compatible. If not, would it be reasonable to add something like intrinsic for it to the language?

Methods that take self by value inherently need you to actually pass the value, not just a pointer.

1 Like

You can't count on the destructor running on every place a struct has resided (or at all, but let's say you know it runs). Every move (assignment, passing to a function, returning from one, inserted by the optimizer for whatever reason, ...) can be a copy of memory with no destruction. So if you need to securely erase the memory, you must take extra steps anyway.

You could put the struct in a box and go to/from a pointer without moving the backing memory.