Skip to content

Commit 03c085e

Browse files
committed
Adding configuration to allow safety comment above stmt containing unsafe block
1 parent c85ceea commit 03c085e

File tree

9 files changed

+93
-7
lines changed

9 files changed

+93
-7
lines changed

book/src/lint_configuration.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,3 +643,13 @@ The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::u
643643
* [`unnecessary_box_returns`](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
644644

645645

646+
## `accept-comment-above-statement`
647+
Whether to accept a safety comment to be placed above the statement containing the `usafe` block
648+
649+
**Default Value:** `false` (`bool`)
650+
651+
---
652+
**Affected lints:**
653+
* [`undocumented_unsafe_blocks`](https://rust-lang.github.io/rust-clippy/master/index.html#undocumented_unsafe_blocks)
654+
655+

clippy_lints/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
909909
enable_raw_pointer_heuristic_for_send,
910910
))
911911
});
912-
store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
912+
let accept_comment_above_statement = conf.accept_comment_above_statement;
913+
store.register_late_pass(move |_| {
914+
Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::new(
915+
accept_comment_above_statement,
916+
))
917+
});
913918
let allow_mixed_uninlined = conf.allow_mixed_uninlined_format_args;
914919
store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv(), allow_mixed_uninlined)));
915920
store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));

clippy_lints/src/undocumented_unsafe_blocks.rs

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
1111
use rustc_lexer::{tokenize, TokenKind};
1212
use rustc_lint::{LateContext, LateLintPass, LintContext};
1313
use rustc_middle::lint::in_external_macro;
14-
use rustc_session::{declare_lint_pass, declare_tool_lint};
14+
use rustc_session::{declare_tool_lint, impl_lint_pass};
1515
use rustc_span::{BytePos, Pos, Span, SyntaxContext};
1616

1717
declare_clippy_lint! {
@@ -92,7 +92,20 @@ declare_clippy_lint! {
9292
"annotating safe code with a safety comment"
9393
}
9494

95-
declare_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]);
95+
#[derive(Copy, Clone)]
96+
pub struct UndocumentedUnsafeBlocks {
97+
accept_comment_above_statement: bool,
98+
}
99+
100+
impl UndocumentedUnsafeBlocks {
101+
pub fn new(accept_comment_above_statement: bool) -> Self {
102+
Self {
103+
accept_comment_above_statement,
104+
}
105+
}
106+
}
107+
108+
impl_lint_pass!(UndocumentedUnsafeBlocks => [UNDOCUMENTED_UNSAFE_BLOCKS, UNNECESSARY_SAFETY_COMMENT]);
96109

97110
impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
98111
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
@@ -101,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
101114
&& !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, block.hir_id)
102115
&& !is_unsafe_from_proc_macro(cx, block.span)
103116
&& !block_has_safety_comment(cx, block.span)
104-
&& !block_parents_have_safety_comment(cx, block.hir_id)
117+
&& !block_parents_have_safety_comment(self.accept_comment_above_statement, cx, block.hir_id)
105118
{
106119
let source_map = cx.tcx.sess.source_map();
107120
let span = if source_map.is_multiline(block.span) {
@@ -313,10 +326,31 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool {
313326

314327
// Checks if any parent {expression, statement, block, local, const, static}
315328
// has a safety comment
316-
fn block_parents_have_safety_comment(cx: &LateContext<'_>, id: hir::HirId) -> bool {
329+
fn block_parents_have_safety_comment(
330+
accept_comment_above_statement: bool,
331+
cx: &LateContext<'_>,
332+
id: hir::HirId,
333+
) -> bool {
317334
if let Some(node) = get_parent_node(cx.tcx, id) {
318335
return match node {
319-
Node::Expr(expr) => !is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span),
336+
Node::Expr(expr) => {
337+
if let Some(
338+
Node::Local(hir::Local { span, .. })
339+
| Node::Item(hir::Item {
340+
kind: hir::ItemKind::Const(..) | ItemKind::Static(..),
341+
span,
342+
..
343+
}),
344+
) = get_parent_node(cx.tcx, expr.hir_id)
345+
{
346+
// if unsafe block is part of a let/const/static statement,
347+
// and accept_comment_above_statement is set to true
348+
// we accept the safety comment in the line the precedes this statement.
349+
accept_comment_above_statement && span_in_body_has_safety_comment(cx, *span)
350+
} else {
351+
!is_branchy(expr) && span_in_body_has_safety_comment(cx, expr.span)
352+
}
353+
},
320354
Node::Stmt(hir::Stmt {
321355
kind:
322356
hir::StmtKind::Local(hir::Local { span, .. })

clippy_lints/src/utils/conf.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,10 @@ define_Conf! {
514514
///
515515
/// The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
516516
(unnecessary_box_size: u64 = 128),
517+
/// Lint: UNDOCUMENTED_UNSAFE_BLOCKS.
518+
///
519+
/// Whether to accept a safety comment to be placed above the statement containing the `usafe` block
520+
(accept_comment_above_statement: bool = false),
517521
}
518522

519523
/// Search for the configuration file.

tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
error: error reading Clippy's configuration file: unknown field `foobar`, expected one of
2+
accept-comment-above-statement
23
allow-dbg-in-tests
34
allow-expect-in-tests
45
allow-mixed-uninlined-format-args
@@ -60,6 +61,7 @@ LL | foobar = 42
6061
| ^^^^^^
6162

6263
error: error reading Clippy's configuration file: unknown field `barfoo`, expected one of
64+
accept-comment-above-statement
6365
allow-dbg-in-tests
6466
allow-expect-in-tests
6567
allow-mixed-uninlined-format-args
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
accept-comment-above-statement = true
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![deny(clippy::undocumented_unsafe_blocks)]
2+
#![allow(clippy::missing_safety_doc)]
3+
4+
fn main() {
5+
// Safety: A safety comment
6+
let _some_variable_with_a_very_long_name_to_break_the_line =
7+
unsafe { a_function_with_a_very_long_name_to_break_the_line() };
8+
}
9+
10+
pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 {
11+
1
12+
}

tests/ui/undocumented_unsafe_blocks.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,4 +509,14 @@ fn issue_9142() {
509509
};
510510
}
511511

512+
pub unsafe fn a_function_with_a_very_long_name_to_break_the_line() -> u32 {
513+
1
514+
}
515+
516+
fn issue_10832() {
517+
// Safety: A safety comment. But it will warn anyways
518+
let _some_variable_with_a_very_long_name_to_break_the_line =
519+
unsafe { a_function_with_a_very_long_name_to_break_the_line() };
520+
}
521+
512522
fn main() {}

tests/ui/undocumented_unsafe_blocks.stderr

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,5 +318,13 @@ LL | let bar = unsafe {};
318318
|
319319
= help: consider adding a safety comment on the preceding line
320320

321-
error: aborting due to 36 previous errors
321+
error: unsafe block missing a safety comment
322+
--> $DIR/undocumented_unsafe_blocks.rs:519:9
323+
|
324+
LL | unsafe { a_function_with_a_very_long_name_to_break_the_line() };
325+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
326+
|
327+
= help: consider adding a safety comment on the preceding line
328+
329+
error: aborting due to 37 previous errors
322330

0 commit comments

Comments
 (0)