Skip to content

Commit 262bda9

Browse files
rcseacordPLeVasseur
authored andcommitted
Revise guideline on unsafe code in macros
Updated guideline on unsafe code in macros to clarify the importance of preserving 'unsafe' token visibility. Added examples of compliant and non-compliant macro implementations.
1 parent ea44d3e commit 262bda9

File tree

1 file changed

+44
-25
lines changed

1 file changed

+44
-25
lines changed

src/coding-guidelines/macros/gui_FRLaMIMb4t3S.rst

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,72 @@
33
44
.. default-domain:: coding-guidelines
55

6-
Do not hide unsafe blocks within macro expansions
7-
=================================================
6+
Do not hide unsafe code in macros
7+
================================
88

9-
.. guideline:: Do not hide unsafe blocks within macro expansions
9+
.. guideline:: Do not hide unsafe code in macros
1010
:id: gui_FRLaMIMb4t3S
11-
:category: required
11+
:category: advisory
1212
:status: draft
13-
:release: todo
13+
:release: unclear-latest
1414
:fls: fls_4vjbkm4ceymk
15-
:decidability: todo
16-
:scope: todo
17-
:tags: reduce-human-error
15+
:decidability: decidable
16+
:scope: module
17+
:tags: safety, reduce-human-error
1818

19-
Description of the guideline goes here.
19+
Do not hide unsafe code in macro definitions.
20+
Macros that expand to unsafe code should preserve the ``unsafe`` token visibility.
2021

2122
.. rationale::
22-
:id: rat_WJubG7KuUDLW
23+
:id: rat_s7ffMlPUFt77
2324
:status: draft
2425

25-
Explanation of why this guideline is important.
26+
Macros that generate unsafe code obscure safety-critical code, making the code more difficult to review and audit.
2627

2728
.. non_compliant_example::
28-
:id: non_compl_ex_AyFnP0lJLHxi
29+
:id: non_compl_ex_YNX7AnWENTu7
2930
:status: draft
3031

31-
Explanation of code example.
32+
Macros that generate unsafe code without preserving the ``unsafe`` token visibility obscure safety-critical code.
33+
This noncompliant example defines a ``deref_ptr`` macro that performs an unsafe pointer dereference.
3234

3335
.. rust-example::
3436

35-
#[allow(dead_code)]
36-
fn example_function() {
37-
// Non-compliant implementation
37+
// This macro hides the unsafe token from callers - noncompliant
38+
macro_rules! deref_ptr {
39+
($ptr:expr) => {
40+
unsafe { *$ptr }
41+
};
42+
}
43+
44+
fn main() {
45+
let x = 42;
46+
let ptr = &x as *const i32;
47+
// The unsafe operation is hidden from the caller
48+
println!("val = {}", deref_ptr!(ptr));
3849
}
39-
#
40-
# fn main() {}
4150
4251
.. compliant_example::
43-
:id: compl_ex_pO5gP1aj2v4F
52+
:id: compl_ex_nBkfzueTWvTA
4453
:status: draft
4554

46-
Explanation of code example.
55+
This compliant example requires the caller to wrap the macro invocation in an ``unsafe`` block,
56+
making the use of unsafe code obvious at the call site.
57+
Visibility can be further improved by prefixing the identifier for each unsafe macro with the string "unsafe_".
4758

4859
.. rust-example::
4960

50-
#[allow(dead_code)]
51-
fn example_function() {
52-
// Compliant implementation
61+
// This macro requires the caller to acknowledge the unsafe operation - compliant
62+
macro_rules! unsafe_deref_ptr {
63+
($ptr:expr) => {
64+
*$ptr
65+
};
66+
}
67+
68+
fn main() {
69+
let x = 42;
70+
let ptr = &x as *const i32;
71+
// The unsafe operation is visible at the call site
72+
let val = unsafe { unsafe_deref_ptr!(ptr) };
73+
println!("val = {}", val);
5374
}
54-
#
55-
# fn main() {}

0 commit comments

Comments
 (0)