Why this code compiles?

Hi, guys

I expected the following code to fail to compile, but it didn't. It just crashed.
I found that if T = fn(u32), and call a(&b) failed, but if T = fn(&u32), a(&&b) is ok.
What happened? Is this a bug?

#[test]
fn test_fn() {
    use std::marker::PhantomData;
    use std::ops::Deref;
    struct Symbol<T> {
        ptr: *mut std::ffi::c_void,
        _phantom: PhantomData<T>,
    }

    impl<T> Deref for Symbol<T> {
        type Target = T;

        fn deref(&self) -> &Self::Target {
            unsafe { &*(&self.ptr as *const *mut _ as *const T) }
        }
    }

    let mut b = 0;
    let a: Symbol<fn(&u32)> = Symbol {
        ptr: &mut b as *mut _ as *mut std::ffi::c_void,
        _phantom: Default::default(),
    };

    a(&&b);
}

(Playground)

Output:


running 1 test

Errors:

   Compiling playground v0.0.1 (/playground)
    Finished test [unoptimized + debuginfo] target(s) in 2.85s
     Running unittests (target/debug/deps/playground-6f2b12ee0084dbb3)
error: test failed, to rerun pass '--lib'

Caused by:
  process didn't exit successfully: `/playground/target/debug/deps/playground-6f2b12ee0084dbb3` (signal: 11, SIGSEGV: invalid memory reference)

This is because of deref coercion. Which allows &&T to be automatically converted to &T. Or more generally, &T where T: Deref to be converted to &T::Target

Note: your code crashes because

  1. you dereferenced a null pointer. This is UB, and always wrong.
  2. You transmuted between i32 and fn(&T) which is invalid
  3. You cast in Deref is incorrect

Fixed: Rust Playground