Skip to content

Commit 4d9d3f8

Browse files
committed
Fix four_forward_slashes false positive on inner doc comments
The lint computes the item's end line from a span folded over the item's doc-comment attributes, then scans the lines above for `////`. The fold previously included inner doc comments (`//!`); an inner doc inside the body lowers onto the item with `AttrStyle::Inner`, so folding its span pushed the end line down into the body and the upward scan flagged a regular `////` comment there — whose suggested fix (`///`) then fails to compile. Fold in outer doc comments only, mirroring the pattern in `doc/suspicious_doc_comments.rs`.
1 parent ef124f6 commit 4d9d3f8

3 files changed

Lines changed: 30 additions & 2 deletions

File tree

clippy_lints/src/four_forward_slashes.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::source::SpanExt as _;
33
use itertools::Itertools as _;
4+
use rustc_ast::AttrStyle;
45
use rustc_errors::Applicability;
5-
use rustc_hir::Item;
6+
use rustc_hir::attrs::AttributeKind;
7+
use rustc_hir::{Attribute, Item};
68
use rustc_lint::{LateContext, LateLintPass, LintContext as _};
79
use rustc_session::declare_lint_pass;
810
use rustc_span::Span;
@@ -48,7 +50,19 @@ impl<'tcx> LateLintPass<'tcx> for FourForwardSlashes {
4850
.tcx
4951
.hir_attrs(item.hir_id())
5052
.iter()
51-
.filter(|i| i.is_doc_comment().is_some())
53+
// Only fold in OUTER doc comments. An inner doc (`//!`) inside the item's
54+
// body lowers onto the item with `AttrStyle::Inner`; folding its span drags
55+
// `end_line` down into the body, so the upward `////` scan then flags a
56+
// regular comment there (see #16168).
57+
.filter(|i| {
58+
matches!(
59+
i,
60+
Attribute::Parsed(AttributeKind::DocComment {
61+
style: AttrStyle::Outer,
62+
..
63+
})
64+
)
65+
})
5266
.fold(item.span.shrink_to_lo(), |span, attr| span.to(attr.span()));
5367
let (Some(file), _, _, end_line, _) = sm.span_to_location_info(span) else {
5468
return;

tests/ui/four_forward_slashes.fixed

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,10 @@ with_span! {
4747
//// don't lint me bozo
4848
fn f() {}
4949
}
50+
51+
// Regression test for #16168: an inner doc comment (`//!`) inside the body must not
52+
// drag the `////` scan down into the body and flag a regular comment there.
53+
fn inner_doc() {
54+
//// I am not a doc comment!
55+
//! inner doc comment
56+
}

tests/ui/four_forward_slashes.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,10 @@ with_span! {
4747
//// don't lint me bozo
4848
fn f() {}
4949
}
50+
51+
// Regression test for #16168: an inner doc comment (`//!`) inside the body must not
52+
// drag the `////` scan down into the body and flag a regular comment there.
53+
fn inner_doc() {
54+
//// I am not a doc comment!
55+
//! inner doc comment
56+
}

0 commit comments

Comments
 (0)