* [PATCH 2/3] checkpatch.pl: warn about // comments on private Rust items
2025-07-29 19:56 [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items Arnaud Lecomte
@ 2025-07-29 20:01 ` Arnaud Lecomte
2025-07-29 20:04 ` [PATCH 3/3] checkpatch.pl: --fix support for `//` comments rust private items Arnaud Lecomte
2025-07-29 20:23 ` [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items Miguel Ojeda
2025-08-13 15:32 ` Lecomte, Arnaud
2 siblings, 1 reply; 6+ messages in thread
From: Arnaud Lecomte @ 2025-07-29 20:01 UTC (permalink / raw)
To: joe
Cc: a.hindborg, alex.gaynor, aliceryhl, apw, bjorn3_gh, boqun.feng,
dakr, dwaipayanray1, gary, linux-kernel, lossin, lukas.bulwahn,
ojeda, rust-for-linux, tmgross, Arnaud Lecomte, Miguel Ojeda
Add a new checkpatch.pl warning to detect //-style comments above
private Rust items that were likely intended to be doc comments (///).
This helps catch documentation that won't appear in rustdoc output.
The detection uses multiple heuristics to identify likely doc comments:
- Comments containing markdown
- Comments starting with an imperative tone
- Comments with mention of params
- Comments with code block
- Comments with keywords: Returns, ...
- Block comments longer than 3 lines.
Comments are only flagged if they:
- Appear above private items
- Don't contain obvious non-doc patterns (TODO, FIXME)
- Score sufficiently on heuristics
The warning triggered then suggests to convert flagged comments to
doc comments.
Results
--------------------
The following implementation has been tested against real patches:
- https://lore.kernel.org/rust-for-linux/dc63bdc4bff8f084714e2c8ff30e4c0d435e85b7.camel@redhat.com/T/#t
- https://lore.kernel.org/rust-for-linux/20250418-ptr-as-ptr-v10-0-3d63d27907aa@gmail.com/T/#t
- https://lore.kernel.org/rust-for-linux/20250420-nova-frts-v1-1-ecd1cca23963@nvidia.com/T/#u
- https://lore.kernel.org/all/20250502094537.231725-5-fujita.tomonori@gmail.com
and against a test patch containing:
// Returns a value
fn private_function() {}
// Computes the result
struct PrivateStruct;
// Arguments:
// - x: input value
// - y: other input
const PRIVATE_CONST: u32 = 42;
// Returns [`SomeType`] with the result
//
// # Examples
// ```
// let x = example();
// ```
fn with_markdown() {}
// Arguments:
// - `param1`: First parameter
// - `param2`: Second parameter
fn with_parameters(param1: u32, param2: String) {}
// 値を返します
fn non_english_doc() {}
// Returns something
// TODO: Change this later
fn mixed_comments() {}
// Internal helper
fn indented_comment() {}
// From kernel example
// Returns a reference to the underlying [`cpufreq::Table`].
fn table(&self) -> &cpufreq::Table {
// SAFETY: The `ptr` is guaranteed by the C code to be valid.
unsafe { cpufreq::Table::from_raw(self.ptr) }
}
// Trait implementation docs
impl SomeTrait for SomeType {
// Performs the operation
fn method(&self) {}
}
// Cases that should NOT trigger warnings
/// Proper documentation
fn documented_function() {}
// TODO: Implement this later
fn todo_function() {}
// SAFETY: This is unsafe because...
unsafe fn safety_comment() {}
// ------
// Not a doc comment
fn visual_separator() {}
pub fn public_function() {} // Public item (handled by rustc)
// some_code(); let x = 42;
fn looks_like_code() {}
// !!! IMPORTANT !!!
fn punctuation_only() {}
// This is just
// a regular
// multi-line comment
fn multi_line_regular() {}
// [DEBUG] Starting process
fn log_message() {}
// <html>test</html>
fn html_comment() {}
// $ echo command
fn shell_command() {}
which resulted into:
WARNING: Possible documentation comment using `//` instead of `///`.
Consider using `///` for documentation comments on private items.
+// Arguments:
+// - x: input value
+// - y: other input
WARNING: Possible documentation comment using `//` instead of `///`.
Consider using `///` for documentation comments on private items.
+// Arguments:
+// - `param1`: First parameter
+// - `param2`: Second parameter
WARNING: Possible documentation comment using `//` instead of `///`.
Consider using `///` for documentation comments on private items.
+// From kernel example
+// Returns a reference to the underlying [`cpufreq::Table`].
Conclusion
--------------------
I think We achieved a balanced solution that effectively enforces
proper documentation while minimizing false positives.
Closes: https://github.com/Rust-for-Linux/linux/issues/1157
Suggested-by: Miguel Ojeda <ojeda@kernel.orgs>
Signed-off-by: Arnaud Lecomte <contact@arnaud-lcm.com>
---
scripts/checkpatch.pl | 111 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 111 insertions(+)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 664f7b7a622c..ac403d270eb4 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2007,6 +2007,97 @@ sub ctx_locate_comment {
chomp($current_comment);
return($current_comment);
}
+
+sub ctx_detect_missing_doc_comment_behind_rust_private_item {
+ my ($linenr) = @_;
+ my $start_line = $linenr - 1;
+ my $idx = $start_line;
+
+ # Skip public items (handled by rustc)
+ return unless $rawlines[$start_line] !~ /^\+?\s*pub(\s|\([^)]*\)\s)/;
+
+ # Check if it's an empty line
+ return unless $rawlines[$start_line] !~ /^\s*\+?\s*$/;
+
+ # Check if it's a comment
+ return unless $rawlines[$start_line] !~ /^\+?\s*\/\/\/?\/?.*$/;
+
+ # Check if it is a private macro
+ if ($rawlines[$start_line] =~ /^\+?\s*macro_rules!\s+([a-zA-Z_][a-zA-Z0-9_]*|#?[a-zA-Z_][a-zA-Z0-9_]*)\s*(?:\{|$)/ && $idx > 0) {
+ return unless $rawlines[$idx -1] !~ /^\+?\s*#\s*\[\s*macro_export\s*\]\s*$/;
+ } else {
+ # Check if it's a Rust item
+ return unless $rawlines[$start_line] =~ /^\+?\s*\b(fn|struct|const|enum|trait|type|mod|impl|use)\b/;
+ }
+
+ # Walk backwards through non-empty lines
+ $idx--;
+ my @comment_lines;
+ while ($idx >= 0 && $rawlines[$idx] !~ /^\s*\+?\s*$/) {
+ # Stop if a doc comment is found
+ last if $rawlines[$idx] =~ m@^\+?\s*///@;
+ # Clean the line first (remove diff markers, trim spaces)
+ my $clean_line = $rawlines[$idx];
+ $clean_line =~ s/^\+?\s*//;
+ $clean_line =~ s/\s*$//;
+ if($clean_line =~ m@^\+?\s*//@) { # Only add comments
+ unshift @comment_lines, $clean_line;
+ }
+ $idx--;
+ }
+
+ # No comments to check
+ return unless @comment_lines;
+
+ # Skip obvious non-doc comments
+ return if grep { /^\s*\/\/\s*(?:TODO|FIXME|XXX|NOTE|HACK|SAFETY):?/i } @comment_lines;
+ return if grep { /^\s*\/\/\s*[[:punct:]]{2,}/ } @comment_lines;
+
+ # Heuristic: Check for documentation keywords
+ my $keywords = qr/Returns|Arguments|Examples?|Panics|Safety|Note|Errors|See\s+Also/i;
+ my $has_keywords = grep { /\/\/\s*$keywords/ } @comment_lines;
+
+ # Heuristic: Markdown syntax
+ my $markdown = qr{
+ `[^`]+` # Inline code
+ | \*\*[^*]+\*\* # Bold
+ | \b_[^_\s][^_]*_\b # Italic
+ | \#[^#\s] # Headings like # Title
+ | ^\s*```[\w]*\s*$ # Code block marker line (allow optional language)
+ }x;
+
+ my $has_markdown = grep { /$markdown/ } @comment_lines;
+
+ # Heuristic: Parameter mentions
+ my $item_line = $rawlines[$start_line];
+ my @params = ($item_line =~ /(\b\w+)\s*:\s*\w+/g); # Extract param names
+ my $param_mentions = 0;
+ if (@params) {
+ $param_mentions = grep { my $line = $_; grep { $line =~ /\b$_\b/ } @params } @comment_lines;
+ }
+
+ # Heuristic: Start with imperative tones
+ my $first_line = $comment_lines[0];
+ my $imperative_tone = $first_line =~ /^\s*\/\/\s*(Returns?|Computes?|Checks?|Converts?|Creates?)\b/i;
+
+ # Heuristic: Code block
+ my $has_code_block = grep { /```|\buse\s+\w+::|^\s*\/\/\s*\w+\(.*\)/ } @comment_lines;
+ # Combine heuristics
+ my $score = 0;
+ $score += 1 if $has_keywords;
+ $score += 2 if $has_markdown;
+ $score += 1 if $param_mentions;
+ $score += 1 if $imperative_tone;
+ $score += 2 if scalar(@comment_lines) >= 3;
+ $score += 2 if $has_code_block;
+
+ # Trigger if score meets threshold
+ return unless $score >= 3;
+
+ return ($idx+1, $start_line);
+}
+
+
sub ctx_has_comment {
my ($first_line, $end_line) = @_;
my $cmt = ctx_locate_comment($first_line, $end_line);
@@ -2970,6 +3061,26 @@ sub process {
}
}
+# check for incorrect use of `//` instead of `\\\` for doc comments in Rust
+ if ($perl_version_ok && $realfile =~ /\.rs$/) {
+ my ($start_l, $end_l) = ctx_detect_missing_doc_comment_behind_rust_private_item($linenr);
+ if (defined($start_l) && defined($end_l)) {
+ my @comment_lines;
+ for (my $i = $start_l; $i <= $end_l; $i++) {
+ next unless $rawlines[$i - 1] =~ m@^\+//([^/].*)$@;
+ push @comment_lines, $rawlines[$i - 1];
+ }
+ my $formatted_comments = join("", map {
+ s/\n$//;
+ "$_\n"
+ } @comment_lines);
+ WARN("MISSING_RUST_DOC",
+ "Possible documentation comment using `//` instead of `///`.\n" .
+ "Consider using `///` for documentation comments on private items.\n" .
+ "$here\n$formatted_comments");
+ }
+ }
+
# Check the patch for a From:
if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) {
$author = $1;
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 3/3] checkpatch.pl: --fix support for `//` comments rust private items
2025-07-29 20:01 ` [PATCH 2/3] checkpatch.pl: warn about " Arnaud Lecomte
@ 2025-07-29 20:04 ` Arnaud Lecomte
0 siblings, 0 replies; 6+ messages in thread
From: Arnaud Lecomte @ 2025-07-29 20:04 UTC (permalink / raw)
To: joe
Cc: a.hindborg, alex.gaynor, aliceryhl, apw, bjorn3_gh, boqun.feng,
dakr, dwaipayanray1, gary, linux-kernel, lossin, lukas.bulwahn,
ojeda, rust-for-linux, tmgross, Arnaud Lecomte
Extend the Rust private item documentation checker (added in the previous
patch) to support automatic fixes when the `--fix` option is enabled.
Signed-off-by: Arnaud Lecomte <contact@arnaud-lcm.com>
---
scripts/checkpatch.pl | 3 +++
1 file changed, 3 insertions(+)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index ac403d270eb4..d01d993d8a9f 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3069,6 +3069,9 @@ sub process {
for (my $i = $start_l; $i <= $end_l; $i++) {
next unless $rawlines[$i - 1] =~ m@^\+//([^/].*)$@;
push @comment_lines, $rawlines[$i - 1];
+ if($fix) {
+ $fixed[$i - 1] =~ s/^\+(\/\/)/+$1\//;
+ }
}
my $formatted_comments = join("", map {
s/\n$//;
--
2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items
2025-07-29 19:56 [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items Arnaud Lecomte
2025-07-29 20:01 ` [PATCH 2/3] checkpatch.pl: warn about " Arnaud Lecomte
@ 2025-07-29 20:23 ` Miguel Ojeda
2025-07-29 20:29 ` Lecomte, Arnaud
2025-08-13 15:32 ` Lecomte, Arnaud
2 siblings, 1 reply; 6+ messages in thread
From: Miguel Ojeda @ 2025-07-29 20:23 UTC (permalink / raw)
To: Arnaud Lecomte
Cc: joe, apw, dwaipayanray1, lukas.bulwahn, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, linux-kernel, rust-for-linux
On Tue, Jul 29, 2025 at 9:56 PM Arnaud Lecomte <contact@arnaud-lcm.com> wrote:
>
> Background
I think you meant to send a cover letter here (i.e. patch zero, rather
than 1) -- you can generate one e.g. with `git format-patch
--cover-letter`.
(No need to resend just for this -- I would wait for some reviews or
comments from maintainers)
Thanks!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items
2025-07-29 20:23 ` [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items Miguel Ojeda
@ 2025-07-29 20:29 ` Lecomte, Arnaud
0 siblings, 0 replies; 6+ messages in thread
From: Lecomte, Arnaud @ 2025-07-29 20:29 UTC (permalink / raw)
To: Miguel Ojeda
Cc: joe, apw, dwaipayanray1, lukas.bulwahn, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, linux-kernel, rust-for-linux
Oops, good catch Miguel, thanks !
On 29/07/2025 21:23, Miguel Ojeda wrote:
> On Tue, Jul 29, 2025 at 9:56 PM Arnaud Lecomte <contact@arnaud-lcm.com> wrote:
>> Background
> I think you meant to send a cover letter here (i.e. patch zero, rather
> than 1) -- you can generate one e.g. with `git format-patch
> --cover-letter`.
>
> (No need to resend just for this -- I would wait for some reviews or
> comments from maintainers)
>
> Thanks!
>
> Cheers,
> Miguel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items
2025-07-29 19:56 [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items Arnaud Lecomte
2025-07-29 20:01 ` [PATCH 2/3] checkpatch.pl: warn about " Arnaud Lecomte
2025-07-29 20:23 ` [PATCH 1/3] checkpatch.pl: Add warning for // comments on private Rust items Miguel Ojeda
@ 2025-08-13 15:32 ` Lecomte, Arnaud
2 siblings, 0 replies; 6+ messages in thread
From: Lecomte, Arnaud @ 2025-08-13 15:32 UTC (permalink / raw)
To: joe
Cc: apw, dwaipayanray1, lukas.bulwahn, ojeda, alex.gaynor,
boqun.feng, gary, bjorn3_gh, lossin, a.hindborg, aliceryhl,
tmgross, dakr, linux-kernel, rust-for-linux
Hi !
Just checking in on this patch series. Is there anything I can clarify
or improve to help move this forward ?
Cheers,
Arnaud
On 29/07/2025 20:56, Arnaud Lecomte wrote:
> Hi,
>
> Background
> ----------
>
> The Rust-for-Linux project currently lacks enforcement of documentation for private Rust items,
> as highlighted in https://github.com/Rust-for-Linux/linux/issues/1157.
> While rustc already lints missing documentation for public items, private items remain unchecked.
> This patch series aims to close that gap by ensuring proper documentation practices
> for private Rust items in the kernel as mentioned in the coding
> guidelines for the Rust linux kernel: Documentation/rust/coding-guidelines.rst.
>
> The actual solution comes in several parts
> ------------------------------------------
>
> 1) Patch 1 : Implements detection logic to emit warnings for improperly
> documented private Rust items (e.g., // comments instead of ///)
> through a set of heuristics.
> 2) Patch 2 : Adds an auto-fix mechanism via the --fix option to help
> developers correct documentation issues.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1157
> Signed-off-by: Arnaud Lecomte <contact@arnaud-lcm.com>
> --
> 2.43.0
^ permalink raw reply [flat|nested] 6+ messages in thread