Skip to content

naive attempt to add the misra c++ mapping - #1226

Draft
inkreasing wants to merge 5 commits into
Safety-Critical-Rust-Consortium:mainfrom
inkreasing:push-wuoxmmqrnuyy
Draft

naive attempt to add the misra c++ mapping#1226
inkreasing wants to merge 5 commits into
Safety-Critical-Rust-Consortium:mainfrom
inkreasing:push-wuoxmmqrnuyy

Conversation

@inkreasing

Copy link
Copy Markdown

Locally it seemed to work and looked fine.

TODO:

  • finish the current discussions with Max
  • link it from the standards page
  • write some introduction / a heading
  • maybe investigate why the py.lock changed? it just happens when i build locally
  • cleanup the data, don't need the assignment for example (this is probably best done in the google sheet)

@netlify

netlify Bot commented Jul 28, 2026

Copy link
Copy Markdown

Deploy Preview for scrc-coding-guidelines failed.

Name Link
🔨 Latest commit b0f0e0b
🔍 Latest deploy log https://app.netlify.com/projects/scrc-coding-guidelines/deploys/6a735385462145000887b691

@inkreasing

Copy link
Copy Markdown
Author

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.

@inkreasing

Copy link
Copy Markdown
Author

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We agreed!

- :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

@PLeVasseur PLeVasseur Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@PLeVasseur PLeVasseur Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We agree with this categorization. Nothing special about Rust here.

@vapdrs vapdrs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- 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")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@onixie onixie Jul 31, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@onixie onixie Jul 31, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@luckymachi luckymachi Aug 5, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. No extra notes

-
-
- 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants