You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _sources/coding-guidelines/associated-items.rst.txt
+85Lines changed: 85 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,3 +5,88 @@
5
5
6
6
Associated Items
7
7
================
8
+
9
+
.. guideline:: Recursive function are not allowed
10
+
:id: gui_ot2Zt3dd6of1
11
+
:category: required
12
+
:status: draft
13
+
:release: 1.3.0-latest
14
+
:fls: fls_vjgkg8kfi93
15
+
:decidability: undecidable
16
+
:scope: system
17
+
:tags: stack-overflow
18
+
19
+
Any function shall not call itself directly or indirectly
20
+
21
+
.. rationale::
22
+
:id: rat_gvoKeVSKK8fD
23
+
:status: draft
24
+
25
+
Recursive functions can easily cause stack overflows, which may result in exceptions or, in some cases, undefined behavior (typically some embedded systems). Although the Rust compiler supports `tail call optimization <https://en.wikipedia.org/wiki/Tail_call>`_\ , this optimization is not guaranteed and depends on the specific implementation and function structure. There is an `open RFC to guarantee tail call optimization in the Rust compiler <https://github.com/phi-go/rfcs/blob/guaranteed-tco/text/0000-explicit-tail-calls.md>`_\ , but this feature has not yet been stabilized. Until tail call optimization is guaranteed and stabilized, developers should avoid using recursive functions to prevent potential stack overflows and ensure program reliability.
26
+
27
+
.. non_compliant_example::
28
+
:id: non_compl_ex_MxqhjfkStJJy
29
+
:status: draft
30
+
31
+
The below function ``concat_strings`` is not complaint because it call itself and depending on depth of data provided as input it could generate an stack overflow exception or undefine behavior.
32
+
33
+
.. code-block:: rust
34
+
35
+
// Recursive enum to represent a string or a list of `MyEnum`
36
+
enum MyEnum {
37
+
Str(String),
38
+
List(Vec<MyEnum>),
39
+
}
40
+
41
+
// Concatenates strings from a nested structure of `MyEnum` using recursion.
The following code implements the same functionality using iteration instead of recursion. The ``stack`` variable is used to maintain the processing context at each step of the loop. This approach provides explicit control over memory usage. If the stack grows beyond a predefined limit due to the structure or size of the input, the function returns an error rather than risking a stack overflow or out-of-memory exception. This ensures more predictable and robust behavior in resource-constrained environments.
58
+
59
+
.. code-block:: rust
60
+
61
+
// Recursive enum to represent a string or a list of `MyEnum`
62
+
enum MyEnum {
63
+
Str(String),
64
+
List(Vec<MyEnum>),
65
+
}
66
+
67
+
/// Concatenates strings from a nested structure of `MyEnum` without using recursion.
68
+
/// Returns an error if the stack size exceeds `MAX_STACK_SIZE`.
Copy file name to clipboardExpand all lines: _sources/coding-guidelines/expressions.rst.txt
+133Lines changed: 133 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -82,6 +82,139 @@ Expressions
82
82
83
83
fn with_base(_: &Base) { ... }
84
84
85
+
.. guideline:: Do not use integer type as divisor
86
+
:id: gui_7y0GAMmtMhch
87
+
:category: advisory
88
+
:status: draft
89
+
:release: latest
90
+
:fls: fls_Q9dhNiICGIfr
91
+
:decidability: decidable
92
+
:scope: module
93
+
:tags: numerics, subset
94
+
95
+
This guideline applies when a `DivisionExpression
96
+
<https://rust-lang.github.io/fls/expressions.html#syntax_divisionexpression>`_ or `RemainderExpression
97
+
<https://rust-lang.github.io/fls/expressions.html#syntax_remainderexpression>`_ is used with a RightOperand of
98
+
`integer type <https://rust-lang.github.io/fls/types-and-traits.html#integer-types>`_.
99
+
100
+
.. rationale::
101
+
:id: rat_vLFlPWSCHRje
102
+
:status: draft
103
+
104
+
The built-in semantics for these expressions can result in panics when division by zero occurs. It is
105
+
recommended to either:
106
+
107
+
* Use checked division functions, which ensure the programmer handles the case when the divisor is zero, or
108
+
* To create divisors using :std:`std::num::NonZero`, which then allows the programmer to perform those
109
+
operations knowing that their divisor is not zero.
110
+
111
+
**Note:** since the compiler can assume the value of a :std:`std::num::NonZero`
112
+
variable to not be zero, checks for zero when dividing by it can be elided in the
113
+
final binary, increasing overall performance beyond what normal division can have.
114
+
115
+
.. non_compliant_example::
116
+
:id: non_compl_ex_0XeioBrgfh5z
117
+
:status: draft
118
+
119
+
When either the division or remainder are performed, the right operand is evaluated to zero and the
120
+
program panics.
121
+
122
+
.. code-block:: rust
123
+
124
+
let x = 0;
125
+
let y = 5 / x; // This line will panic.
126
+
let z = 5 % x; // This line would also panic.
127
+
128
+
.. compliant_example::
129
+
:id: compl_ex_k1CD6xoZxhXb
130
+
:status: draft
131
+
132
+
There is no compliant way to divide with an integer type. Here, instead, the developer explicitly:
133
+
134
+
* Uses a checked division function, which ensures a zero divisor is handled separately, and
135
+
* Creates a divisor using :std:`std::num::NonZero`, which outsources the check for zero to the
136
+
construction of that struct. It's worth noting that such a divisor can be used multiple times after it's been created, whilst keeping the guarantee that such divisions will be safe.
137
+
138
+
.. code-block:: rust
139
+
140
+
let x = 0;
141
+
if let Some(divisor) = match NonZero::<u32>::new(x) {
142
+
let result = 5 / divisor;
143
+
}
144
+
let result = match 5u32.checked_rem(x) {
145
+
None => 0,
146
+
Some(r) => r,
147
+
}
148
+
149
+
150
+
.. guideline:: Do not divide by 0
151
+
:id: gui_kMbiWbn8Z6g5
152
+
:category: required
153
+
:status: draft
154
+
:release: latest
155
+
:fls: fls_Q9dhNiICGIfr
156
+
:decidability: undecidable
157
+
:scope: system
158
+
:tags: numerics, defect
159
+
160
+
This guideline applies when unsigned integer or two’s complement division is performed during the
0 commit comments