Why is c_void a thing at all?

FWIW, this makes fun things happen when someone gets their argument order wrong and passes &some_int as this pointer. There's nothing the compiler can do to warn about such things (beyond the heuristics based on argument names not matching with variable names) :confused: . Having dealt with that, I think it is far better to just forward declare a type and use a pointer to it (and never define the type; just C-cast in the impl as needed).

FWIW, fn pointers are an existing type of Rust pointer without a meaningful pointee type. They're also annoying to deal with, since you can't just cast them like normal pointers -- e.g. a pointer from dlsym has to go through transmute to get a Rust fn pointer.

6 Likes

I meant that a void * object is used in some C interface, that is, its address is taken (or of a structure that contains it) and passed to C code. In this case, the object must be of type void *, any other pointer type is distinct.

(I'm surprised that Rust doesn't do type-based aliasing—I would assume it's exposed to it via cross-language LTO.)

We set noalias where we can according to & and &mut exclusivity, but not TBAA. I think as long as we don't attach tbaa metadata on Rust parts, cross-language optimization should be fine. Of course, you should follow those rules in FFI calls to a language that cares.

Indeed, even when cross-language optimization is involved, the optimizer treats Rust loads and stores as potentially aliasing anything. However, there has been some discussion about wanting more precise types for C FFI for a different purpose, namely cross-language control flow integrity protection.