Module std::prim_fn1.0.0[][src]

Expand description

Function pointers, like fn(usize) -> bool.

See also the traits Fn, FnMut, and FnOnce.

Function pointers are pointers that point to code, not data. They can be called just like functions. Like references, function pointers are, among other things, assumed to not be null, so if you want to pass a function pointer over FFI and be able to accommodate null pointers, make your type Option<fn()> with your required signature.


Plain function pointers are obtained by casting either plain functions, or closures that don’t capture an environment:

fn add_one(x: usize) -> usize {
    x + 1

let ptr: fn(usize) -> usize = add_one;
assert_eq!(ptr(5), 6);

let clos: fn(usize) -> usize = |x| x + 5;
assert_eq!(clos(5), 10);

In addition to varying based on their signature, function pointers come in two flavors: safe and unsafe. Plain fn() function pointers can only point to safe functions, while unsafe fn() function pointers can point to safe or unsafe functions.

fn add_one(x: usize) -> usize {
    x + 1

unsafe fn add_one_unsafely(x: usize) -> usize {
    x + 1

let safe_ptr: fn(usize) -> usize = add_one;

//ERROR: mismatched types: expected normal fn, found unsafe fn
//let bad_ptr: fn(usize) -> usize = add_one_unsafely;

let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
let really_safe_ptr: unsafe fn(usize) -> usize = add_one;


On top of that, function pointers can vary based on what ABI they use. This is achieved by adding the extern keyword before the type, followed by the ABI in question. The default ABI is “Rust”, i.e., fn() is the exact same type as extern "Rust" fn(). A pointer to a function with C ABI would have type extern "C" fn().

extern "ABI" { ... } blocks declare functions with ABI “ABI”. The default here is “C”, i.e., functions declared in an extern {...} block have “C” ABI.

For more information and a list of supported ABIs, see the nomicon’s section on foreign calling conventions.

Variadic functions

Extern function declarations with the “C” or “cdecl” ABIs can also be variadic, allowing them to be called with a variable number of arguments. Normal Rust functions, even those with an extern "ABI", cannot be variadic. For more information, see the nomicon’s section on variadic functions.

Creating function pointers

When bar is the name of a function, then the expression bar is not a function pointer. Rather, it denotes a value of an unnameable type that uniquely identifies the function bar. The value is zero-sized because the type already identifies the function. This has the advantage that “calling” the value (it implements the Fn* traits) does not require dynamic dispatch.

This zero-sized type coerces to a regular function pointer. For example:

use std::mem;

fn bar(x: i32) {}

let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
assert_eq!(mem::size_of_val(&not_bar_ptr), 0);

let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());

let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`

The last line shows that &bar is not a function pointer either. Rather, it is a reference to the function-specific ZST. &bar is basically never what you want when bar is a function.


Function pointers implement the following traits:

Due to a temporary restriction in Rust’s type system, these traits are only implemented on functions that take 12 arguments or less, with the "Rust" and "C" ABIs. In the future, this may change.

In addition, function pointers of any signature, ABI, or safety are Copy, and all safe function pointers implement Fn, FnMut, and FnOnce. This works because these traits are specially known to the compiler.