Skip to content

Commit 2bba4d9

Browse files
x0rwgithub-actions[bot]
authored andcommitted
Add guideline for issue #21
Co-authored-by: x0rw <[email protected]>
1 parent ddd254d commit 2bba4d9

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

src/coding-guidelines/associated-items.rst

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,94 @@
55

66
Associated Items
77
================
8+
9+
.. guideline:: Guideline Test
10+
:id: gui_YhqyI9W60LsU
11+
:category: advisory
12+
:status: draft
13+
:release: 1.1.1-1.1.1
14+
:fls: fls_vjgkg8kfi93
15+
:decidability: decidable
16+
:scope: module
17+
:tags: stack-overflow
18+
19+
Any function shall not call itself directly or indirectly
20+
21+
.. rationale::
22+
:id: rat_iPa9yjwWrhyJ
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+
28+
* A list item
29+
30+
* Another sub-item
31+
* Another sub item.
32+
33+
.. non_compliant_example::
34+
:id: non_compl_ex_1b0YmpdIfvDv
35+
:status: draft
36+
37+
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.
38+
39+
.. code-block:: rust
40+
41+
// Recursive enum to represent a string or a list of `MyEnum`
42+
enum MyEnum {
43+
Str(String),
44+
List(Vec<MyEnum>),
45+
}
46+
47+
// Concatenates strings from a nested structure of `MyEnum` using recursion.
48+
fn concat_strings(input: &[MyEnum]) -> String {
49+
let mut result = String::new();
50+
for item in input {
51+
match item {
52+
MyEnum::Str(s) => result.push_str(s),
53+
MyEnum::List(list) => result.push_str(&concat_strings(list)),
54+
}
55+
}
56+
result
57+
}
58+
59+
.. compliant_example::
60+
:id: compl_ex_2aqAbFmEo0n5
61+
:status: draft
62+
63+
tete
64+
65+
.. code-block:: rust
66+
67+
// Recursive enum to represent a string or a list of `MyEnum`
68+
enum MyEnum {
69+
Str(String),
70+
List(Vec<MyEnum>),
71+
}
72+
73+
/// Concatenates strings from a nested structure of `MyEnum` without using recursion.
74+
/// Returns an error if the stack size exceeds `MAX_STACK_SIZE`.
75+
fn concat_strings_non_recursive(input: &[MyEnum]) -> Result<String, &'static str> {
76+
const MAX_STACK_SIZE: usize = 1000;
77+
let mut result = String::new();
78+
let mut stack = Vec::new();
79+
80+
// Add all items to the stack
81+
stack.extend(input.iter());
82+
83+
while let Some(item) = stack.pop() {
84+
match item {
85+
MyEnum::Str(s) => result.insert_str(0, s),
86+
MyEnum::List(list) => {
87+
// Add list items to the stack
88+
for sub_item in list.iter() {
89+
stack.push(sub_item);
90+
if stack.len() > MAX_STACK_SIZE {
91+
return Err("Too big structure");
92+
}
93+
}
94+
}
95+
}
96+
}
97+
Ok(result)
98+
}

0 commit comments

Comments
 (0)