@@ -64,7 +64,7 @@ Types and Traits
6464 current.checked_add(velocity).expect("Position calculation overflowed")
6565 }
6666
67- .. guideline :: Do Not Depend on Function Pointer Identity Across Crates
67+ .. guideline :: Do not depend on function pointer identity
6868 :id: gui_QbvIknd9qNF6
6969 :category: required
7070 :status: draft
@@ -74,40 +74,53 @@ Types and Traits
7474 :scope: system
7575 :tags: surprising-behavior
7676
77- Do not rely on the equality or stable identity of function pointers originating from different crates or that may be inlined,
78- duplicated, or instantiated differently across compilation units, codegen units, or optimization profiles.
77+ Do not rely on the equality or stable identity of function pointers.
7978
79+ .. exception ::
80+ :id: rat_kYiIiW8R2qD3
81+ :status: draft
82+
83+ ``#[no_mangle] `` functions are guaranteed to have a single instance.
84+
85+ .. rationale ::
86+ :id: rat_kYiIiW8R2qD2
87+ :status: draft
88+
89+ Functions may be instantiated multiple times.
90+ They may, for example, be instantiated every time they are referenced.
91+ Only ``#[no_mangle] `` functions are guaranteed to be instantiated a single time,
92+ but can cause undefined behavior if they share a symbol with other identifiers.
93+
8094 Avoid assumptions about low-level metadata (such as symbol addresses) unless explicitly guaranteed by the Ferrocene Language Specification (FLS).
81- Function address identity is not guaranteed by Rust and must not be treated as stable.
95+ Function address identity is not guaranteed and must not be treated as stable.
8296 Rust’s ``fn `` type is a zero-sized function item promoted to a function pointer, whose address is determined by the compiler backend.
83- When a function resides in a different crate, or when optimizations such as inlining,
84- link-time optimization, or codegen-unit partitioning are enabled,
97+ When a function resides in a different crate or codegen-unit partitioning is enabled,
8598 the compiler may generate multiple distinct code instances for the same function or alter the address at which it is emitted.
8699
87- Consequently, the following operations are not reliable :
100+ Consequently, the following operations are unreliable for functions which are not `` #[no_mangle] `` :
88101
89102 - Comparing function pointers for equality (``fn1 == fn2 ``)
90103 - Assuming a unique function address
91104 - Using function pointers as identity keys (e.g., in maps, registries, matchers)
92- - Matching behavior based on function address
105+ - Matching behavior based on function address unless you instruct the linker to put a (#[no_mangle]) function at a specific address
93106
94107 This rule applies even when the functions are semantically identical, exported as ``pub ``, or defined once in source form.
95108
96109 .. rationale ::
97110 :id: rat_xcVE5Hfnbb2u
98111 :status: draft
99112
100- Compiler optimizations may cause function pointers originating from different crates to lose stable identity.
101- Observed behaviors include:
113+ Compiler optimizations may cause function pointers to lose stable identity, for example:
102114
103- - Cross-crate inlining producing multiple code instantiations
104- - Codegen-unit separation causing function emission in multiple units
105- - Incremental builds producing variant symbol addresses
106- - Link-time optimization merging or splitting functions unpredictably
115+ - Cross-crate inlining can produce multiple code instantiations
116+ - Codegen-unit separation can cause function emission in multiple codegen units
117+ - Identical function implementations may be automatically merged as an optimization.
118+ Functions that are equivalent based only on specific hardware semantics may be merged in the machine-specific backend.
119+ Merging may also be performed as link-time optimization.
107120
108121 This behavior has resulted in real-world issues,
109122 such as the bug reported in `rust-lang/rust#117047 <https://github.com/rust-lang/rust/issues/117047 >`_,
110- where function pointer comparisons unexpectedly failed due to cross-crate inlining .
123+ where function pointer comparisons unexpectedly failed because the function in question was instantiated multiple times .
111124
112125 Violating this rule may cause:
113126
@@ -181,14 +194,14 @@ Types and Traits
181194 :id: non_compl_ex_MkAkFxjRTijy
182195 :status: draft
183196
184- Function pointer used as a key is not guaranteed to have stable identity, as shown in this noncompliant example:
197+ A function pointer used as a key is not guaranteed to have stable identity, as shown in this noncompliant example:
185198
186199 .. code-block :: rust
187200
188201 // crate A
189202 pub fn op_mul(x: i32) -> i32 { x * 2 }
190203
191- // crate B
204+ // crate B
192205 use crate_a::op_mul;
193206 use std::collections: :HashMap;
194207
@@ -226,7 +239,7 @@ Types and Traits
226239 pub const OP_MUL: Operation = Operation { id: 1, func: op_mul };
227240 pub const OP_ADD: Operation = Operation { id: 2, func: op_add };
228241
229- // crate B
242+ // crate B
230243
231244 use crate_a::{Operation, OP_MUL, OP_ADD};
232245 use std::collections: :HashMap;
0 commit comments