Casting a function reference producing an invalid pointer?

This answer is based on the replies on the bug report motivated by this question.

Each function in Rust has its individual function item type, which is distinct from the function item type of every other function. For this reason, an instance of the function item type does not need to store any information at all – what function it points to is clear from its type. So the variable x in

let x = foo;

is a variable of size 0.

Function item types implicitly coerce to function pointer types where necessary. The variable

let x: fn() = foo;

is a generic pointer to any function with signature fn(), and thus needs to store a pointer to the function it actually points to, so the size of x is the size of a pointer.

If you take the address of a function, &foo, you are actually taking the address of a zero-sized temporary value. Before this commit to the rust repo, zero-sized temporaries used to create an allocation on the stack, and &foo returned the address of that allocation. Since this commit, zero-sized types don't create allocations anymore, and instead use the magic address 1. This explains the difference between the different versions of Rust.


What is the _ getting inferred to and why has the behaviour changed?

Each time you do a raw pointer cast, you can only change one piece of information (reference or raw pointer; mutability; type). Therefore, if you do this cast:

let ptr = &foo as *const _

since you've changed from a reference to a raw pointer, the type inferred for _ must be unchanged and is therefore the type of foo, which is some inexpressible type for the function foo.

Instead of doing that, you can directly cast to a function pointer, which is expressible in Rust syntax:

let ptr = foo as *const fn() as *const c_void;

As for why it has changed, that's hard to say. It could be a bug in the nightly build. It is worth reporting it — even if it is not a bug, you will likely get a good explanation from the compiler team about what is actually going on!