naive attempt to add the misra c++ mapping - #1226
Conversation
❌ Deploy Preview for scrc-coding-guidelines failed.
|
|
While this has warnings the only real error is fls validation, which i don't think has anything to do with this PR. So it does appear to work. |
4dc42e4 to
c23ea45
Compare
|
Thank you for the typo fixes. I copied them into the google sheet, because i think we are going to delete some columns and then do another export. |
| - | ||
| - | ||
| - Rust doesn't allow explicitly specifying the variables captured by a closure. Issues arising from this are also caught by the borrow checker. (similar caveat to Rule 8.1.1 applies here). Capturing raw pointers is not checked, but using them in the closure requires unsafe code, therefore this does map to unsafe rust. | ||
| * - Rule 8.2.1 |
There was a problem hiding this comment.
Closest is the Any trait which can be downcast. Not really apples-to-apples in the same way, but this is applicable under the presence of unsafe.
| - | ||
| - | ||
| - Rust and Cpp have similar a number of operators and while some footguns are less of a problem (assignment returns (), < and > return bool, which can't be directly compared to integers) it is still possible to write unclear code using operator precedence. There is a warn by default clippy lint about this: https://rust-lang.github.io/rust-clippy/master/#precedence | ||
| * - Rule 8.2.2 |
There was a problem hiding this comment.
MISRA C++ rule is fairly long, has multiple points.
We agree that only point 2 applies.
| - | ||
| - | ||
| - The exact case doesn't map as rust doesn't have class hierarchies like C++ does, but the general issue can occur in unsafe code with trait objects. Casting trait objects to a concrete type should use the "Any" trait, which checks that the conversion is correct (similar to "dynamic\_cast" in C++). | ||
| * - Rule 8.2.3 |
There was a problem hiding this comment.
We agree with this reasoning.
Consider signaling of intent on mutability and using specific functions to communicate it.
| - | ||
| - | ||
| - Creating a mutable reference from a constant reference isn't possible in safe code. On raw pointers removing (or adding) constness is possible in safe code, but this can only cause UB in the presence of unsafe code. This guideline applies to unsafe code as the mutation permissions of a pointer need to be taken into account when writing unsafe code. (discussion on zulip about safe rust status: https://rust-lang.zulipchat.com/#narrow/channel/579369-safety-critical-consortium.2Fcoding-guidelines/topic/MISRA.20C.2B.2B.20Mapping.20Interest/near/599857174) | ||
| * - Rule 8.2.4 |
There was a problem hiding this comment.
Does seem relevant to unsafe. We agreed.
| - | ||
| - | ||
| - Casting of pointer types (including function pointers) by itself can't cause UB. creating function pointers in safe code is only possible by taking the address of a function, not by casting from a pointer. In unsafe code care must be taken to only call valid function pointers and to not cast a function pointer to a reference to a struct/enum (which can easily lead to UB). | ||
| * - Rule 8.2.5 |
| - :need:`gui_ADHABsmK9FXz` | ||
| - Advisory | ||
| - Point 2 of the rationale about missing intent applies to rust "as" casts. specific functions should be used instead. | ||
| * - Rule 8.2.6 |
There was a problem hiding this comment.
While this is possible in safe Rust, actually causing an issue with it requires unsafe, we think.
Propose moving to the only unsafe bucket.
| - | ||
| - | ||
| - Just like in C++ roundtripping pointers through pointers to void (union) is allowed, therefore the rationale fully applies. Casting from integer to pointer requires additional care to not create a pointer without provenance. Casting from integers or pointers to void (union in rust) to pointers is allowed in safe rust. | ||
| * - Rule 8.2.7 |
There was a problem hiding this comment.
Can see the logic for why this could apply to safe, but we felt this could really only bite you under the presence of unsafe when dereferencing.
Suggest moving to the only unsafe bucket below.
There was a problem hiding this comment.
Yes i think you could argue that without unsafe rust you don't need a pointer tracking tool and therefore doing something that hinders pointer tracking is no problem.
Same for rule 8.2.6 probably.
| - | ||
| - | ||
| - Rationale mentions tools that track pointers. This applies to rust as for example miri misses UB when exposed provenance is used. Casting pointers to integers and back is allowed in safe rust, so this rule also applies to safe rust. | ||
| * - Rule 8.2.8 |
There was a problem hiding this comment.
In C++ using a different integer type we might truncate, and yep this applies to Rust as well.
However, we felt that we might want to move this to only unsafe bucketing since the truly bad things that can happen are really only relevant there.
There was a problem hiding this comment.
What does truly bad mean for you? If you only convert it back to a pointer yeah you need unsafe.
I am thinking of maybe using a integer that was converted from a pointer as a key to a hashmap. If dataloss happens you now have two pointers that access the same bucket.
| * - Rule 8.1.1 | ||
| - | ||
| - The borrow checker catches attempts to capture shortlived references in closures. Rust also doesn't have implicit ``this``, so in the closure ``self`` has to be used, which makes it obvious which object is being captured. Closure capture behaves the same in an unsafe block, so this isn't affected by unsafe code. (this mapping depends on a rule about using unsafe to extend the lifetime of references, if such a rule does not exist this would apply to unsafe rust) | ||
| * - Rule 8.2.9 |
There was a problem hiding this comment.
We are kind of confused at how complex this is, but the rationale given does seem to make sense. We therefore agree.
| - | ||
| - | ||
| - "uintptr\_t" and "intptr\_t" map to "usize" and "isize" in rust. This is marked as applicable to safe rust, because information loss can be important for safe rust as well. | ||
| * - Rule 8.2.10 |
There was a problem hiding this comment.
We agree with this categorization. Nothing special about Rust here.
vapdrs
left a comment
There was a problem hiding this comment.
Group A in the 2026-07-29 meeting reviewed 4.1.1, 4.1.2, 4.1.3, 5.7.1, 6.0.4, 6.4.2, 6.7.1, 6.7.2, 6.8.1
| - ``-`` | ||
| - | ||
| - | ||
| - While the C++ standard is obviously not relevant, the general principle applies to analogous Specifications (e.g. FLS). However, in the safe Rust subset all syntactically programs not rejected by the compiler should be in compliance (otherwise its a bug in the compiler) Unsafe Rust, must be free of UB in order to conform. |
There was a problem hiding this comment.
| - While the C++ standard is obviously not relevant, the general principle applies to analogous Specifications (e.g. FLS). However, in the safe Rust subset all syntactically programs not rejected by the compiler should be in compliance (otherwise its a bug in the compiler) Unsafe Rust, must be free of UB in order to conform. | |
| - While the C++ standard is obviously not relevant, the general principle applies to analogous Specifications (e.g. FLS). However, in the safe Rust subset all syntactically programs not rejected by the compiler should be in compliance (otherwise its a bug in the compiler) Unsafe Rust, must be free of UB in order to conform. Rust does not quite have Language extensions, but unstable nightly features should be avoided. |
| - Rule 1.3 | ||
| - | ||
| - | ||
| - MISRA C mapping (not entirely clear why safe rust is applicable, maybe because of "critical unspecified behavior") |
There was a problem hiding this comment.
A possible explanation is that "critical unspecified behavior" is the difference between the written Rust language specification, and the compiler's implementation behavior.
Rust only documents undefined behaviors, which should be avoided.
@AlexCeleste do you have any comments on the rationale for the MISRA C mapping?
| - Rule 5.3 | ||
| - | ||
| - | ||
| - MISRA C mapping |
There was a problem hiding this comment.
Perhaps add 6.4.2 in the mapping here. Which will become relevant after a future PR is merged. rust-lang/rust#148605
| - Rule 5.3 | ||
| - | ||
| - | ||
| - MISRA C mapping |
There was a problem hiding this comment.
This can much more easily cause issues in C or C++, in Rust it is less severe to shadow variables.
| - | ||
| - | ||
| - "reinterpret\_cast" maps to "transmute" in Rust and it is similarly dangerous. In Rust one additional exception might be added in regards to "repr(transparent" types. "transmute" is a unsafe function so safe code isn't affected. | ||
| * - Rule 8.2.11 |
There was a problem hiding this comment.
Note that this is going to be stabilized for c-variadic functions:
rust-lang/reference#2177
So we should probably note this as something which applies under unsafe for this purpose as well.
There was a problem hiding this comment.
Note that rule 8.2.11 is only about calling variadic functions, which has been possible in unsafe rust for a long time.
Rule 21.10.1 is about creating variadic functions. I changed this to apply to unsafe rust two days ago since the stabilization PR already merged, even if the reference hasn't been updated yet.
| note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace | ||
|
|
||
| error: aborting due to 1 previous error | ||
| * - Rule 6.8.2 |
There was a problem hiding this comment.
We agree with this categorization.
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| | | ||
| = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior | ||
| = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information | ||
| * - Rule 6.8.3 |
There was a problem hiding this comment.
We agree with this categorization.
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| - | ||
| - | ||
| - In safe Rust, Error E0597 is emitted: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=596fdb2179c4c79b494afb51aaa8b40a In unsafe Rust this is possible using raw pointers. (similar to Rule 6.8.2) | ||
| * - Rule 6.8.4 |
There was a problem hiding this comment.
We agree with this categorization.
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| - | ||
| - | ||
| - Same reasoning as for Rule 6.7.1 | ||
| * - Rule 7.0.1 |
There was a problem hiding this comment.
It is a prohibitive one. We agree that it is applicable in safe Rust. We suppose to have one rule for each.
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| * When casting a bool to an integral type, its clearer to explicitly name the numerical values that are assigned for each boolean value. | ||
|
|
||
| Depending on whether either or both of these aspects are considered important enough to be mapped to our rules, the classification of Rule 7.0.1 is either both "yes" or both "no". | ||
| * - Rule 7.0.4 |
There was a problem hiding this comment.
This rule is valid and agree with the categorization.
Compiler doesn't raise error when the method is called directly, instead errors happen as panics at runtime. See the sample code in playground.
For reference
- https://doc.rust-lang.org/std/primitive.u8.html#method.overflowing_shl
- https://doc.rust-lang.org/std/primitive.u8.html#method.overflowing_shl
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| The ``as`` operator cannot convert into bool. Conversions via the ``TryInto``/``TryFrom`` traits correspond with ``explicit operator bool`` and are exempted by the Rule. | ||
|
|
||
| For unsafe Rust, one should also consider ``transmute``\ ing into bool where the safety invariant of bool must be ensured. However, this is simply part of the general unsafe Rust rules and does not need a dedicated rule in the Rust guidelines | ||
| * - Rule 8.1.2 |
There was a problem hiding this comment.
What is written is sufficient. Agree with the categorization.
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| - | ||
| - | ||
| - Rust can unsafely call variadic functions. As this is interop the C/C++ rules apply directly. | ||
| * - Rule 8.7.1 |
There was a problem hiding this comment.
Good explanation. Agreed.
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| - | ||
| - | ||
| - This applies to the unsafe "add" and similar functions on pointers. Creating invalid pointers using these functions is UB. The "wrapping\_add" family of functions doesn't create UB when an invalid pointer is created and are callable from safe code. This rule doesn't apply to safe code as the dereferencing of such pointers is supposed to be covered by rule 4.1.3 and UB can only happen when using the unsafe functions. | ||
| * - Rule 8.7.2 |
There was a problem hiding this comment.
Agree the categorization.
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| - Safety-critical Rust rule | ||
| - Category | ||
| - Comment | ||
| * - Rule 6.0.3 |
There was a problem hiding this comment.
We agree with this categorization.
Comment based on minutes from Asia Pacific + Americas Meeting on 2026-07-31.
| - | ||
| - | ||
| - The rationale fully applies to rust. The impact on understandability of the code isn't reduced by the use of references instead of pointers, so it also maps to safe rust. | ||
| * - Rule 13.3.3 |
There was a problem hiding this comment.
Comment of meeting 5/8/2026.
Mapping agreed
| - | ||
| - | ||
| - In Rust it is possible to use different parameter names for a trait definition and the trait implementation. This maps to overriding a function in C++. https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=b9fefe14582277f2a79019bd4a26a279 There is a clippy lint against this: https://rust-lang.github.io/rust-clippy/master/#renamed_function_params | ||
| * - Rule 13.3.4 |
There was a problem hiding this comment.
Comment from meeting 5/8/26
Mapping agreed
| - | ||
| - | ||
| - In Rust every comparison between functions pointers is unspecified, not only for virtual member pointers. Therefore this rule needs to be extended to cover function pointer/vtable pointer comparisons in general. See https://github.com/rust-lang/unsafe-code-guidelines/issues/589 and https://github.com/Safety-Critical-Rust-Consortium/safety-critical-rust-coding-guidelines/pull/256 | ||
| * - Rule 14.1.1 |
There was a problem hiding this comment.
Comment from meeting 5/8/26
Mapping agreed
Rationale should be expanded.
| - :need:`gui_ot2Zt3dd6of1` | ||
| - Required | ||
| - The same issues regarding stack usage apply to rust. clippy has a lint against unconditional recursion. In safety critical even conditional recursion should be used carefully | ||
| * - Rule 8.9.1 |
There was a problem hiding this comment.
"Surprising behavior" in Rust is a very fine line we'd like to be more sure about, as it can lead to the rule being more struct or less strict when mapped to Rust. If it's purely UB then it does 100% map to Rust, otherwise some further analysis would be appreciated
| - | ||
| - | ||
| - This can also lead to "surprising or unspecified behaviour" in rust. See discussion: https://rust-lang.zulipchat.com/#narrow/channel/136281-t-opsem/topic/.E2.9C.94.20Eq.20and.20Ord.20in.20raw.20pointers | ||
| * - Rule 8.14.1 |
There was a problem hiding this comment.
Agree. The mentioned operators in Rust behave lazily as well, so we can come across the same surprises
| - | ||
| - | ||
| - The "-" operator isn't available on pointers in rust. This maps to the "offset\_from" family of methods on raw pointers. These are unsafe and introduce UB if used on pointers to different allocations. Casting pointers to integers and doing arithmetic on them will produce unspecified results if the pointers belong to different allocations and is possible in safe code, but this rule is explicitly concerned with UB and therefore does not apply to safe code. | ||
| * - Rule 8.18.1 |
There was a problem hiding this comment.
We agree with the reasoning; it's in unsafe were the problem with be regarding union checks
| - | ||
| - | ||
| - In rust the evaluation of the "&&" operator is also short-circuiting, so evaluation of the right-hand side depends on the value of the left-hand side. | ||
| * - Rule 8.20.1 |
| - | ||
| - | ||
| - Arithmetic overflow in constant evaluation is a compile error if runtime overflow checking is enabled.(https://play.rust-lang.org/?version=stable&mode=release&edition=2024&gist=15b1f64f02b76e6aff6af79730bae8dc difference between debug and release build). It shouldn't happen even if runtime checks are disabled. In some cases (like ``const A: u8 = 200 + 200``) compilation always errors. | ||
| * - Rule 9.4.1 |
There was a problem hiding this comment.
Agree. Missing an extra else clause could lead to a possible type error depending on the use case
| - | ||
| - | ||
| - Same rationale as in C++ applies. Clippy has a lint that recommends the opposite (clippy::needless\_else) it would have to be disabled. | ||
| * - Rule 9.4.2 |
There was a problem hiding this comment.
Agree. for subrule #6 we also suggest take into consideration the exception of 1-branch match statements
| 6. Maps to rust (there should maybe be an exception for match statements with zero branches to allow conversion from an uninhabited type) | ||
|
|
||
| 7. Does not map to rust, as it is checked by the compiler that match statements are always exhaustive. Placement of the default does map to rust as it even influences which branch is taken (unreachable pattern warning) | ||
| * - Rule 9.5.1 |
There was a problem hiding this comment.
We think it doesn't really map to Rust 100%, though it would be appreciated to analyze the iterator-related reasoning to better analyze if it maps/doesn't map
Locally it seemed to work and looked fine.
TODO: