# `ffi_pure`

The `#[ffi_pure]` attribute applies clang's `pure` attribute to foreign functions declarations.

That is, `#[ffi_pure]` functions shall have no effects except for its return value, which shall not change across two consecutive function calls with the same parameters.

Applying the `#[ffi_pure]` attribute to a function that violates these requirements is undefined behavior.

This attribute enables Rust to perform common optimizations, like sub-expression elimination and loop optimizations. Some common examples of pure functions are `strlen` or `memcmp`.

These optimizations are only applicable when the compiler can prove that no program state observable by the `#[ffi_pure]` function has changed between calls of the function, which could alter the result. See also the `#[ffi_const]` attribute, which provides stronger guarantees regarding the allowable behavior of a function, enabling further optimization.

## Pitfalls

A `#[ffi_pure]` function can read global memory through the function parameters (e.g. pointers), globals, etc. `#[ffi_pure]` functions are not referentially-transparent, and are therefore more relaxed than `#[ffi_const]` functions.

However, accesing global memory through volatile or atomic reads can violate the requirement that two consecutive function calls shall return the same value.

A `pure` function that returns unit has no effect on the abstract machine's state.

A `#[ffi_pure]` function must not diverge, neither via a side effect (e.g. a call to `abort`) nor by infinite loops.

When translating C headers to Rust FFI, it is worth verifying for which targets the `pure` attribute is enabled in those headers, and using the appropriate `cfg` macros in the Rust side to match those definitions. While the semantics of `pure` are implemented identically by many C and C++ compilers, e.g., clang, GCC, ARM C/C++ compiler, IBM ILE C/C++, etc. they are not necessarily implemented in this way on all of them. It is therefore also worth verifying that the semantics of the C toolchain used to compile the binary being linked against are compatible with those of the `#[ffi_pure]`.