@@ -11,7 +11,7 @@ use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
11
11
use rustc_lexer:: { tokenize, TokenKind } ;
12
12
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
13
13
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 } ;
15
15
use rustc_span:: { BytePos , Pos , Span , SyntaxContext } ;
16
16
17
17
declare_clippy_lint ! {
@@ -92,7 +92,20 @@ declare_clippy_lint! {
92
92
"annotating safe code with a safety comment"
93
93
}
94
94
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 ] ) ;
96
109
97
110
impl < ' tcx > LateLintPass < ' tcx > for UndocumentedUnsafeBlocks {
98
111
fn check_block ( & mut self , cx : & LateContext < ' tcx > , block : & ' tcx Block < ' tcx > ) {
@@ -101,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
101
114
&& !is_lint_allowed ( cx, UNDOCUMENTED_UNSAFE_BLOCKS , block. hir_id )
102
115
&& !is_unsafe_from_proc_macro ( cx, block. span )
103
116
&& !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 )
105
118
{
106
119
let source_map = cx. tcx . sess . source_map ( ) ;
107
120
let span = if source_map. is_multiline ( block. span ) {
@@ -313,10 +326,31 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool {
313
326
314
327
// Checks if any parent {expression, statement, block, local, const, static}
315
328
// 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 {
317
334
if let Some ( node) = get_parent_node ( cx. tcx , id) {
318
335
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
+ } ,
320
354
Node :: Stmt ( hir:: Stmt {
321
355
kind :
322
356
hir:: StmtKind :: Local ( hir:: Local { span, .. } )
0 commit comments