Propagate accept-comment-above-attributes to statements (#15213)

Turns out that things like `#[attr]return unsafe { func(); }` didn't
work because we weren't checking above attributes on statements, only on
blocks!

fixes https://github.com/rust-lang/rust-clippy/issues/13189

Useful for Rust-For-Linux

changelog:[`undocumented_unsafe_blocks`]: Make sure to propagate
`accept-comment-above-attributes` to **all** statements.
This commit is contained in:
Samuel Tardieu 2025-07-06 07:28:40 +00:00 committed by GitHub
commit 7c39d378e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 37 additions and 4 deletions

View file

@ -143,7 +143,8 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
if let Some(tail) = block.expr
&& !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, tail.hir_id)
&& !tail.span.in_external_macro(cx.tcx.sess.source_map())
&& let HasSafetyComment::Yes(pos) = stmt_has_safety_comment(cx, tail.span, tail.hir_id)
&& let HasSafetyComment::Yes(pos) =
stmt_has_safety_comment(cx, tail.span, tail.hir_id, self.accept_comment_above_attributes)
&& let Some(help_span) = expr_has_unnecessary_safety_comment(cx, tail, pos)
{
span_lint_and_then(
@ -167,7 +168,8 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
};
if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, stmt.hir_id)
&& !stmt.span.in_external_macro(cx.tcx.sess.source_map())
&& let HasSafetyComment::Yes(pos) = stmt_has_safety_comment(cx, stmt.span, stmt.hir_id)
&& let HasSafetyComment::Yes(pos) =
stmt_has_safety_comment(cx, stmt.span, stmt.hir_id, self.accept_comment_above_attributes)
&& let Some(help_span) = expr_has_unnecessary_safety_comment(cx, expr, pos)
{
span_lint_and_then(
@ -534,7 +536,12 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> HasSaf
/// Checks if the lines immediately preceding the item contain a safety comment.
#[allow(clippy::collapsible_match)]
fn stmt_has_safety_comment(cx: &LateContext<'_>, span: Span, hir_id: HirId) -> HasSafetyComment {
fn stmt_has_safety_comment(
cx: &LateContext<'_>,
span: Span,
hir_id: HirId,
accept_comment_above_attributes: bool,
) -> HasSafetyComment {
match span_from_macro_expansion_has_safety_comment(cx, span) {
HasSafetyComment::Maybe => (),
has_safety_comment => return has_safety_comment,
@ -549,6 +556,13 @@ fn stmt_has_safety_comment(cx: &LateContext<'_>, span: Span, hir_id: HirId) -> H
_ => return HasSafetyComment::Maybe,
};
// if span_with_attrs_has_safety_comment(cx, span, hir_id, accept_comment_above_attrib
// }
let mut span = span;
if accept_comment_above_attributes {
span = include_attrs_in_span(cx, hir_id, span);
}
let source_map = cx.sess().source_map();
if let Some(comment_start) = comment_start
&& let Ok(unsafe_line) = source_map.lookup_line(span.lo())

View file

@ -450,5 +450,13 @@ help: consider removing the safety comment
LL | // SAFETY: unnecessary_safety_comment triggers here
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 52 previous errors
error: unsafe block missing a safety comment
--> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:733:12
|
LL | return unsafe { h() };
| ^^^^^^^^^^^^^^
|
= help: consider adding a safety comment on the preceding line
error: aborting due to 53 previous errors

View file

@ -723,4 +723,15 @@ fn issue_13039() {
_ = unsafe { foo() }
}
fn rfl_issue15034() -> i32 {
unsafe fn h() -> i32 {
1i32
}
// This shouldn't lint with accept-comment-above-attributes! Thus fixing a false positive!
// SAFETY: My safety comment!
#[allow(clippy::unnecessary_cast)]
return unsafe { h() };
//~[disabled]^ ERROR: unsafe block missing a safety comment
}
fn main() {}