> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust Function Pointer

A function pointer in Rust is a primitive, statically sized type that represents a memory address pointing to a function's machine code. Denoted by the lowercase `fn` keyword, it implements the `Sized` trait, has a fixed size known at compile time (occupying the exact same memory footprint as a `usize`), and does not capture any surrounding lexical environment.

## Syntax and Type Signature

The type signature of a function pointer consists of the `fn` keyword, a parenthesized list of parameter types, and an optional return type.

```rust theme={"dark"}
// Type signature for a function taking an i32 and returning a bool
let ptr: fn(i32) -> bool;

// Type signature for a function taking no arguments and returning nothing (unit type)
let ptr_unit: fn();
```

## Safe and Unsafe Function Pointers

In Rust, function pointers distinguish between safe and unsafe contexts at the type level. An `unsafe fn` is a completely distinct type from a safe `fn` pointer. Calling an `unsafe fn` pointer requires an `unsafe` block. Safe function pointers can implicitly coerce into unsafe function pointers, but the reverse is strictly prohibited.

```rust theme={"dark"}
fn safe_func() {}
unsafe fn unsafe_func() {}

let safe_ptr: fn() = safe_func;
let unsafe_ptr: unsafe fn() = unsafe_func;

// Safe function pointers coerce to unsafe function pointers
let coerced_ptr: unsafe fn() = safe_ptr;

// ERROR: Unsafe function pointers cannot coerce to safe function pointers
// let invalid_ptr: fn() = unsafe_ptr;
```

## Function Items vs. Function Pointers

In Rust, defining a function does not immediately create a function pointer. Instead, it creates a **Function Item**.

A function item is a unique, zero-sized type (ZST) that uniquely identifies that specific function. Because it is zero-sized, passing a function item around incurs no runtime overhead. However, function items automatically coerce into function pointers (`fn`) when required by the type context.

```rust theme={"dark"}
fn add_one(x: i32) -> i32 { x + 1 }

// `f_item` is a zero-sized function item type specific to `add_one`.
let f_item = add_one; 

// `f_ptr` is explicitly typed as a function pointer. 
// The function item implicitly coerces to a function pointer.
let f_ptr: fn(i32) -> i32 = add_one; 

// Explicit casting is also valid
let f_ptr_cast = add_one as fn(i32) -> i32;
```

## Relationship with Closures

Function pointers are distinct from closures, but they interact closely with Rust's closure traits (`Fn`, `FnMut`, and `FnOnce`).

1. **Trait Implementation:** The `fn` type automatically implements all three closure traits. Any generic function bounded by `impl Fn()`, `impl FnMut()`, or `impl FnOnce()` will accept a function pointer.
2. **Closure Coercion:** A closure that **does not** capture any variables from its environment can be coerced into a function pointer. A capturing closure cannot.

```rust theme={"dark"}
// Non-capturing closure coerces to a function pointer
let non_capturing: fn(i32) -> i32 = |x| x * 2;

let y = 10;
// ERROR: Capturing closure cannot be coerced to a function pointer
// let capturing: fn(i32) -> i32 = |x| x * y; 
```

## ABI and Foreign Function Interface (FFI)

Function pointers can specify an Application Binary Interface (ABI) string to dictate how arguments and return values are passed at the assembly level. This is strictly required when interfacing with code written in other languages, such as C. Because calling foreign code often falls outside Rust's safety guarantees, FFI function pointers are typically marked `unsafe`.

```rust theme={"dark"}
// A safe function pointer using the standard C ABI
let c_ptr: extern "C" fn(i32) -> i32;

// An unsafe function pointer using the C ABI (the standard for FFI)
let unsafe_c_ptr: unsafe extern "C" fn(i32) -> i32;

// A function pointer using the "stdcall" ABI (often used in Windows APIs)
let win_ptr: extern "stdcall" fn() -> i32;
```

If no ABI is specified, the function pointer defaults to the `"Rust"` ABI.

## Memory Layout and Null-Pointer Optimization

Function pointers in Rust are strictly non-nullable; they must always point to a valid function address. Because of this guarantee, the Rust compiler applies the **null-pointer optimization** when a function pointer is wrapped in an `Option`.

```rust theme={"dark"}
use std::mem::size_of;

// Both types occupy the exact same amount of memory (e.g., 8 bytes on a 64-bit system).
// The `None` variant is represented by a null memory address (0x0).
assert_eq!(
    size_of::<fn()>(),
    size_of::<Option<fn()>>()
);
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Rust Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
