'Why does printing a function using the pointer formatter warn about "taking a reference to a function item does not give a function pointer"?

I wanted to create a function pointer using the reference operator:

fn main() {
    let fcn_ptr = &add;

    println!("{:p}", fcn_ptr);
    println!("{}", fcn_ptr(10, 10));
}

fn add(x: i32, y: i32) -> i32 {
    x + y
}

The compiler output:

warning: taking a reference to a function item does not give a function pointer
 --> src/main.rs:4:22
  |
4 |     println!("{:p}", fcn_ptr);
  |                      ^^^^^^^ help: cast `add` to obtain a function pointer: `add as fn(_, _) -> _`
  |
  = note: `#[warn(function_item_references)]` on by default

And the execution output:

0x55c0890fa000
20

What are the reasons behind the warning?



Solution 1:[1]

fcn_ptr contains a reference to the function item, not a function pointer.

Anything that is sensible to do with a reference to a function item can be done instead with the function item itself. So, (except perhaps for some generic code, which isn't the case here) there's no legitimate reason to take a reference to a function item, and the most sensible interpretation is that you wanted a function pointer. The warning is to alert you to this mistake (hkBst's answer shows that it is a mistake).

You will need to cast your function item into a function pointer if you want the latter, as the compiler suggests:

fn main() {
    let fcn_ptr = add as fn(_, _) -> _;

    println!("{:p}", fcn_ptr);
    println!("{}", fcn_ptr(10, 10));
}

fn add(x: i32, y: i32) -> i32 {
    x + y
}

Solution 2:[2]

Following the advice of the compiler and comparing the results shows that we get a difference:

fn main() {
    let fcn_ref = &add;
    let fcn_ptr = &(add as fn(_, _) -> _);

    // these print different values!
    println!("{:p}", fcn_ptr);
    println!("{:p}", fcn_ref); // warning: taking a reference to a function item does not give a function pointer
}

fn add(x: i32, y: i32) -> i32 {
    x + y
}

Example output:

0x56098b65a088
0x56098b64c000

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 trent
Solution 2 Shepmaster