Skip to content

Commit 09c8b65

Browse files
authored
Refactor overflow handling and function pointer notes
cleaned up some links and stuff
1 parent 870d218 commit 09c8b65

File tree

1 file changed

+33
-23
lines changed

1 file changed

+33
-23
lines changed

src/coding-guidelines/types-and-traits.rst

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,21 @@ Types and Traits
2525
:status: draft
2626

2727
In debug builds, Rust performs runtime checks for integer overflow and will panic if detected.
28-
However, in release builds (with optimizations enabled), unless the flag `overflow-checks`_ is
29-
turned on, integer operations silently wrap around on overflow, creating potential for silent
30-
failures and security vulnerabilities. Note that overflow-checks only brings the default panic
31-
behavior from debug into release builds, avoiding potential silent wrap arounds. Nonetheless,
32-
abrupt program termination is usually not suitable and, therefore, turning this flag on must
33-
not be used as a substitute of explicit handling. Furthermore, the behavior in release mode is
34-
under consideration by the The Rust Language Design Team and in the future overflow checking
28+
However, in release builds (with optimizations enabled),
29+
unless the flag `overflow-checks`_ is turned on, integer operations silently wrap around on overflow,
30+
creating potential for silent failures and security vulnerabilities.
31+
Note that overflow-checks only brings the default panic behavior from debug into release builds,
32+
avoiding potential silent wrap arounds.
33+
Nonetheless, abrupt program termination is not suitable and, therefore, turning this flag on must
34+
not be used as a substitute of explicit handling.
35+
Furthermore, the behavior in release mode is under consideration by the The Rust Language Design Team and in the future overflow checking
3536
may be turned on by default in release builds (it is a `frequently requested change`_).
3637

37-
.. _overflow-checks: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/codegen-options/index.md#overflow-checks
38-
.. _frequently requested change: https://lang-team.rust-lang.org/frequently-requested-changes.html#numeric-overflow-checking-should-be-on-by-default-even-in-release-mode
38+
.. `overflow-checks <https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/codegen-options/index.md#overflow-checks>`_
39+
.. `frequently requested change <https://lang-team.rust-lang.org/frequently-requested-changes.html#numeric-overflow-checking-should-be-on-by-default-even-in-release-mode>`_
3940
40-
Safety-critical software requires consistent and predictable behavior across all build
41-
configurations. Explicit handling of potential overflow conditions improves code clarity,
41+
Safety-critical software requires consistent and predictable behavior across all build configurations.
42+
Explicit handling of potential overflow conditions improves code clarity,
4243
maintainability, and reduces the risk of numerical errors in production.
4344

4445
.. non_compliant_example::
@@ -73,9 +74,15 @@ Types and Traits
7374
:scope: system
7475
:tags: surprising-behavior
7576

76-
Do not rely on the equality or stable identity of function pointers originating from different crates or that may be inlined, 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 originating from different crates or that may be inlined,
78+
duplicated, or instantiated differently across compilation units, codegen units, or optimization profiles.
7779

78-
Avoid assumptions about low-level metadata (such as symbol addresses) unless explicitly guaranteed by the Ferrocene Language Specification (FLS). Function address identity is not guaranteed by Rust and must not be treated as stable. Rust’s fn type is a zero-sized function item promoted to a function pointer, whose address is determined by the compiler backend. When a function resides in a different crate, or when optimizations such as inlining, link-time optimization, or codegen-unit partitioning are enabled, the compiler may generate multiple distinct code instances for the same function or alter the address at which it is emitted.
80+
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.
82+
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,
85+
the compiler may generate multiple distinct code instances for the same function or alter the address at which it is emitted.
7986

8087
Consequently, the following operations are not reliable:
8188

@@ -90,33 +97,36 @@ Types and Traits
9097
:id: rat_xcVE5Hfnbb2u
9198
:status: draft
9299

93-
Compiler optimizations may cause function pointers originating from different crates to lose stable identity. Observed behaviors include:
100+
Compiler optimizations may cause function pointers originating from different crates to lose stable identity.
101+
Observed behaviors include:
94102

95103
- Cross-crate inlining producing multiple code instantiations
96104
- Codegen-unit separation causing function emission in multiple units
97105
- Incremental builds producing variant symbol addresses
98106
- Link-time optimization merging or splitting functions unpredictably
99107

100-
This behavior has resulted in real-world issues, such as the bug reported in rust-lang/rust#117047,
101-
where function pointer comparisons unexpectedly failed due to cross-crate inlining.
108+
This behavior has resulted in real-world issues,
109+
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.
102111

103112
Violating this rule may cause:
104113

105114
- Silent logic failures: callbacks not matching, dispatch tables misbehaving.
106115
- Inappropriate branching: identity-based dispatch selecting wrong handler.
107116
- Security issues: adversary-controlled conditions bypassing function-based authorization/dispatch logic.
108117
- Nondeterministic behavior: correctness depending on build flags or incremental state.
109-
- Test-only correctness: function pointer equality passing in debug builds but failing in release/LTO builds.
118+
- Test-only correctness: function pointer equality passing in debug builds but failing in release/link-time optimization builds.
110119

111-
In short, dependence on function address stability introduces non-portable, build-profile-dependent behavior, which is incompatible with high-integrity Rust.
120+
In short, dependence on function address stability introduces non-portable, build-profile-dependent behavior,
121+
which is incompatible with high-integrity Rust.
112122

113123
.. non_compliant_example::
114124
:id: non_compl_ex_MkAkFxjRTijx
115125
:status: draft
116126

117127
Due to cross-crate inlining or codegen-unit partitioning,
118-
the address of ``handler_a`` in crate ``B`` may differ from its address in crate A,
119-
causing comparisons to fail as shown in this noncompliant code example:
128+
the address of ``handler_a`` in crate ``B`` may differ from its address in crate A,
129+
causing comparisons to fail as shown in this noncompliant code example:
120130

121131
.. code-block:: rust
122132
@@ -187,15 +197,15 @@ Types and Traits
187197

188198
let f = op_mul;
189199

190-
// Lookup may fail if `op_mul` has multiple emitted instances.
200+
// Error: Lookup may fail if `op_mul` has multiple emitted instances.
191201
assert_eq!(registry.get(&f), Some(&"double"));
192202

193203
.. compliant_example::
194204
:id: compl_ex_oiqSSclTXmIj
195205
:status: draft
196206

197207
This compliant example uses a stable identity wrappers as identity keys.
198-
The ``id`` is a stable, programmer-defined identity, immune to compiler optimizations.
208+
The ``id`` is a stable, programmer-defined identity, immune to compiler optimizations.
199209
The function pointer is preserved for behavior (``func``) but never used as the identity key.
200210

201211
.. code-block:: rust
@@ -254,7 +264,7 @@ Types and Traits
254264
}
255265
}
256266
257-
register(handler); // Error: may be inserted twice under some builds
267+
register(handler); // Error: may be inserted twice under some builds
258268
259269
.. compliant_example::
260270
:id: compl_ex_oiqSSclTXmIk

0 commit comments

Comments
 (0)