@@ -11,7 +11,7 @@ use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource};
1111use rustc_lexer:: { tokenize, TokenKind } ;
1212use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
1313use 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 } ;
1515use rustc_span:: { BytePos , Pos , Span , SyntaxContext } ;
1616
1717declare_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
97110impl < ' 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, .. } )
@@ -546,7 +580,14 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
546580 for ( _, node) in map. parent_iter ( body. hir_id ) {
547581 match node {
548582 Node :: Expr ( e) => span = e. span ,
549- Node :: Block ( _) | Node :: Arm ( _) | Node :: Stmt ( _) | Node :: Local ( _) => ( ) ,
583+ Node :: Block ( _)
584+ | Node :: Arm ( _)
585+ | Node :: Stmt ( _)
586+ | Node :: Local ( _)
587+ | Node :: Item ( hir:: Item {
588+ kind : hir:: ItemKind :: Const ( ..) | ItemKind :: Static ( ..) ,
589+ ..
590+ } ) => ( ) ,
550591 _ => break ,
551592 }
552593 }
0 commit comments