What type instead of _?

I fixed but in my code recently but I can not understand what I fixed.

At first I wrote:

let my_data: &RustStruct = *(cdata.native_handle as *const _);

and this was wrong, then I fixed with:
let my_data2: &RustStruct = &*(cdata.native_handle as *const RustStruct);

but what exactly type rustc calculate for _ to cause bug, any idea?

use std::ffi::c_void;

#[repr(C)]
struct CStruct {
    native_handle: *mut c_void,
}

struct RustStruct {
    a: i32,
}

unsafe extern "C" fn foo(cdata: *mut CStruct) {
    let cdata: &mut CStruct = &mut *cdata;

    let my_data: &RustStruct = *(cdata.native_handle as *const _);
    println!("BUG: my_data addr {:?}", my_data as *const RustStruct);

    let my_data2: &RustStruct = &*(cdata.native_handle as *const RustStruct);
    println!("FIX: my_data2 addr {:?}", my_data2 as *const RustStruct);
}

fn main() {
    let mut my_data = RustStruct { a: 17 };
    println!("my_data addr {:?}", &my_data as *const RustStruct);
    let mut x = CStruct {
        native_handle: &mut my_data as *mut RustStruct as *mut c_void,
    };
    unsafe { foo(&mut x) };
}

It would have to be *const &RustStruct for the bare * dereference to work. In the second example, you used &* which forms a new reference to that pointer-dereferenced place.

3 Likes

The first line only dereferences cdata.native_handle while the second one converts the pointer into a reference.