Skip to content

Defects vs subsets #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

AlexCeleste
Copy link
Contributor

This adds a basic example of three kinds of guideline:

  • a blanket Advisory subsetting guideline
  • a more targeted decidable Required subsetting guideline
  • a defect-oriented undecidable Required guideline

AlexCeleste and others added 3 commits June 4, 2025 15:53
…n explicit Amplification section exists (instead, whatever paragraph immediately opens the guideline is just normative). We can continue to call it that but the subheading is not necessary.
Copy link

netlify bot commented Jun 4, 2025

Deploy Preview for scrc-coding-guidelines ready!

Name Link
🔨 Latest commit 6b37575
🔍 Latest deploy log https://app.netlify.com/projects/scrc-coding-guidelines/deploys/68405ea9bcc4830008d2b969
😎 Deploy Preview https://deploy-preview-127--scrc-coding-guidelines.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

.. code-block:: rust

fn f1 (x:u16, y:i32, z:u64, w:usize) {
let p1 = x as * const u32; // not compliant

Choose a reason for hiding this comment

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

Can NULL (0) be safely converted from integer to pointer in Rust?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, but it's considered bad form. Rust playground example

There's a clippy lint zero_ptr which is on by default.

The recommendation is instead to use the core library functions core::ptr::null_mut() and core::ptr::null_mut().

Maybe that can be mentioned somewhere here @AlexCeleste or should this be a separate guideline? What do you think?

There is no compliant example of this operation.


.. guideline:: An integer shall not be converted to an invalid pointer

Choose a reason for hiding this comment

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

I take it this is a variant or subset of the previous rule? A dev should choose to follow this rule or the prev one, right?


An expression of numeric type shall not be converted to a pointer if the resulting pointer
is incorrectly aligned, does not point to an entity of the referenced type, or is an invalid representation.

Choose a reason for hiding this comment

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

I recognize this wording from CERT INT36-C :) IIRC it all comes from ISO C. That aside, does the above sentence have the same meaning in Rust? Or is Rust relying on the ISO C definitions of these terms?

Copy link
Collaborator

@PLeVasseur PLeVasseur left a comment

Choose a reason for hiding this comment

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

Thanks @AlexCeleste for the excellent additions! Could you take a look at the comments I left?

By the way -- I think I recall you saying the plan is to incorporate these examples more into the Style Guideline to help flesh it out. Was that right? In this PR or another?

I suppose then it would be quite helpful to use the examples to illustrate the difference between a defect and subset.

@@ -81,3 +81,245 @@ Expressions
}

fn with_base(_: &Base) { ... }


.. guideline:: The ``as`` operator should not be used with numeric operands
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is really nice. I recall there was a CVE which occurred due to this too.


A pointer-to-address cast is not symmetrical because the resulting pointer may not point to a valid object,
may not point to an object of the right type, or may not be properly aligned.
If a conversion in this direction is needed, ``std::mem::transmute`` will communicate the intent to perform
Copy link
Collaborator

Choose a reason for hiding this comment

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

A nice feature of the extension we have is that you could write this as:

Suggested change
If a conversion in this direction is needed, ``std::mem::transmute`` will communicate the intent to perform
If a conversion in this direction is needed, :std:`std::mem::transmute` will communicate the intent to perform

and then this should also turn into a link to the standard library.

Could you take a look through your additions and try this out?

(shout out to @pietroalbini as this was originally written for the FLS)


fn f1 (x:u16, y:i32, z:u64, w:u8) {
let a = w as char; // non-compliant
let b = y as u32; // non-compliant - changes value range
Copy link
Collaborator

Choose a reason for hiding this comment

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

Struggling to clearly write what I mean here. But if e.g. you pass in a negative number the meaning of it changes

Suggested change
let b = y as u32; // non-compliant - changes value range
let b = y as u32; // non-compliant - changes value range, negative values change in meaning

let a3 = p1 as u64; // non-compliant - use usize to indicate intent

let p2 = a1 as * const u32; // non-compliant - prefer transmute
let p3 = a2 as * const u32; // non-compliant, and probably invalid
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you help me understand what is meant by this is invalid?

.. code-block:: rust

fn f2 (x:u16, y:i32, z:u64, w:u8) {
let a:char = w.into ();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we move the parens closer, like this, for these?

Could we also leave a space between the : and the type, like this, for these?

I think rustfmt would make these changes and it'll look a little more familiar for those who know Rust.

Suggested change
let a:char = w.into ();
let a: char = w.into();

@@ -99,6 +99,10 @@
dict(name="readability", description="Readability-related guideline"),
dict(name="reduce-human-error", description="Reducing human error guideline"),
dict(name="numerics", description="Numerics-related guideline"),
dict(name="undefined-behavior", description="Numerics-related guideline"),

dict(name="defect", description="Guideline associated with the language-subset profile"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you'd like we can have a new Sphinx Needs option for whether it's a defect or subset.
If we think most guidelines can or should be classified as one or the other it might make sense.
What do you think?

@@ -308,15 +304,27 @@ what it covers.
Content **SHOULD** aim to be as short and self-contained as possible, while still explaining
the scope of the guideline.

Content **SHOULD NOT** cover the rationale for the guideline, which is done in the ``rationale`` section.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you mentioned about removing the IETF RFC 2119-styling to this chapter when it was intended for readers. Now that it's intended for contributors are you thinking to keep it in?

Or is this change unrelated to that to aid in understanding?

@@ -363,7 +379,13 @@ The ``status`` option of a ``rationale`` **MUST** match the ``status`` of its pa
Rationale Content
-----------------

TODO(pete.levasseur)
The content of the rationale **SHOULD** provide the relevant context for why this guideline is useful.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be MUST or SHOULD? Reading through IETF RFC 2119 I debated myself.

Same for the one below on undefined behavior.

MUST This word, or the terms "REQUIRED" or "SHALL", mean that the definition is an absolute requirement of the specification.

SHOULD This word, or the adjective "RECOMMENDED", mean that there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course.

The Rationale **MAY** make reference to other guidelines or to external documents cited in the
References.

The Rationale **SHOULD** be supported by code examples wherever concise examples are possible.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a nice usage of SHOULD 👍

@@ -435,6 +457,9 @@ than the current guideline.
``compliant_example``
=====================

A compliant example **MAY** be omitted when the guideline forbids an action entirely, i.e. there
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be SHOULD to encourage the right action taken by a guideline writer? 🤔

Suggested change
A compliant example **MAY** be omitted when the guideline forbids an action entirely, i.e. there
A compliant example **MAY** be omitted when the guideline forbids an action entirely, i.e. there

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.

3 participants