I’m trying to understand the issue here, so I decided to write some FFI code:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
struct UninhabitedTest {
uint64_t data;
};
struct UninhabitedTest* uninhabited_test_new(uint64_t d) {
struct UninhabitedTest* ut = malloc(sizeof(struct UninhabitedTest));
ut->data = d;
puts("new");
return ut;
}
void uninhabited_test_delete(struct UninhabitedTest* ut) {
puts("delete");
free(ut);
}
uint64_t uninhabited_test_get_data(struct UninhabitedTest* ut) {
puts("get_data");
return ut->data;
}
extern crate libc;
mod ut {
mod ffi {
#[repr(C)]
pub struct UninhabitedTestImpl {
_priv: u8,
}
extern {
pub fn uninhabited_test_new(d: ::libc::uint64_t) -> *mut UninhabitedTestImpl;
pub fn uninhabited_test_delete(ut: *mut UninhabitedTestImpl) -> ::libc::c_void;
pub fn uninhabited_test_get_data(ut: *mut UninhabitedTestImpl) -> ::libc::uint64_t;
}
}
pub struct UninhabitedTest {
data: *mut ffi::UninhabitedTestImpl,
}
impl UninhabitedTest {
pub fn new(d: u64) -> UninhabitedTest {
let ut = unsafe { ffi::uninhabited_test_new(d) };
if ut.is_null() { panic!("ran out of memory"); }
UninhabitedTest { data: ut }
}
pub fn data(&self) -> u64 {
unsafe { ffi::uninhabited_test_get_data(self.data) }
}
}
impl Drop for UninhabitedTest {
fn drop(&mut self) {
unsafe { ffi::uninhabited_test_delete(self.data) };
}
}
}
fn main() {
use ut::UninhabitedTest;
let input = 4;
let ut = UninhabitedTest::new(input);
let output = ut.data();
println!("input: {}", input);
println!("output: {}", output);
}
I’d admit that having to use a u8 as a member in order to stop lints from giving me warnings is a bit annoying, but as far as I can tell, this code is correct?
Rust isn’t allowed to dereference a *mut _ automatically and this code never does it manually, so only the C code will ever do it.
The only problem would be if the author of the ut module leaks a *mut UninhabitedTestImpl or *const UninhabitedTestImpl or creates &UninhabitedTestImpl or &mut UninhabitedTestImpl. I.e. authors of unsafe code have to be careful and know what they are doing. I don’t see why that is an unreasonable burden, unless I’m missing something?