@@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
113113 && !block. span . in_external_macro ( cx. tcx . sess . source_map ( ) )
114114 && !is_lint_allowed ( cx, UNDOCUMENTED_UNSAFE_BLOCKS , block. hir_id )
115115 && !is_unsafe_from_proc_macro ( cx, block. span )
116- && !block_has_safety_comment ( cx, block. span )
116+ && !block_has_safety_comment ( cx, block. span , self . accept_comment_above_attributes )
117117 && !block_parents_have_safety_comment (
118118 self . accept_comment_above_statement ,
119119 self . accept_comment_above_attributes ,
@@ -408,46 +408,29 @@ fn block_parents_have_safety_comment(
408408 cx : & LateContext < ' _ > ,
409409 id : HirId ,
410410) -> bool {
411- let ( span, hir_id ) = match cx. tcx . parent_hir_node ( id) {
412- Node :: Expr ( expr) if let Some ( inner ) = find_unsafe_block_parent_in_expr ( cx, expr) => inner ,
411+ let span = match cx. tcx . parent_hir_node ( id) {
412+ Node :: Expr ( expr) if let Some ( ( span , _ ) ) = find_unsafe_block_parent_in_expr ( cx, expr) => span ,
413413 Node :: Stmt ( hir:: Stmt {
414414 kind :
415- hir:: StmtKind :: Let ( hir:: LetStmt { span, hir_id , .. } )
416- | hir:: StmtKind :: Expr ( hir:: Expr { span, hir_id , .. } )
417- | hir:: StmtKind :: Semi ( hir:: Expr { span, hir_id , .. } ) ,
415+ hir:: StmtKind :: Let ( hir:: LetStmt { span, .. } )
416+ | hir:: StmtKind :: Expr ( hir:: Expr { span, .. } )
417+ | hir:: StmtKind :: Semi ( hir:: Expr { span, .. } ) ,
418418 ..
419419 } )
420- | Node :: LetStmt ( hir:: LetStmt { span, hir_id , .. } ) => ( * span, * hir_id ) ,
420+ | Node :: LetStmt ( hir:: LetStmt { span, .. } ) => * span,
421421
422- node if let Some ( ( span, hir_id ) ) = span_and_hid_of_item_alike_node ( & node)
422+ node if let Some ( ( span, _ ) ) = span_and_hid_of_item_alike_node ( & node)
423423 && is_const_or_static ( & node) =>
424424 {
425- ( span, hir_id )
425+ span
426426 } ,
427427
428428 _ => return false ,
429429 } ;
430430 // if unsafe block is part of a let/const/static statement,
431431 // and accept_comment_above_statement is set to true
432432 // we accept the safety comment in the line the precedes this statement.
433- accept_comment_above_statement
434- && span_with_attrs_has_safety_comment ( cx, span, hir_id, accept_comment_above_attributes)
435- }
436-
437- /// Extends `span` to also include its attributes, then checks if that span has a safety comment.
438- fn span_with_attrs_has_safety_comment (
439- cx : & LateContext < ' _ > ,
440- span : Span ,
441- hir_id : HirId ,
442- accept_comment_above_attributes : bool ,
443- ) -> bool {
444- let span = if accept_comment_above_attributes {
445- include_attrs_in_span ( cx, hir_id, span)
446- } else {
447- span
448- } ;
449-
450- span_has_safety_comment ( cx, span)
433+ accept_comment_above_statement && span_has_safety_comment ( cx, span, accept_comment_above_attributes)
451434}
452435
453436/// Checks if an expression is "branchy", e.g. loop, match/if/etc.
@@ -459,7 +442,7 @@ fn is_branchy(expr: &hir::Expr<'_>) -> bool {
459442}
460443
461444/// Checks if the lines immediately preceding the block contain a safety comment.
462- fn block_has_safety_comment ( cx : & LateContext < ' _ > , span : Span ) -> bool {
445+ fn block_has_safety_comment ( cx : & LateContext < ' _ > , span : Span , accept_comment_above_attributes : bool ) -> bool {
463446 // This intentionally ignores text before the start of a function so something like:
464447 // ```
465448 // // SAFETY: reason
@@ -469,18 +452,9 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
469452 // attributes and doc comments.
470453
471454 matches ! (
472- span_from_macro_expansion_has_safety_comment( cx, span) ,
455+ span_from_macro_expansion_has_safety_comment( cx, span, accept_comment_above_attributes ) ,
473456 HasSafetyComment :: Yes ( _)
474- ) || span_has_safety_comment ( cx, span)
475- }
476-
477- fn include_attrs_in_span ( cx : & LateContext < ' _ > , hir_id : HirId , span : Span ) -> Span {
478- span. to ( cx. tcx . hir_attrs ( hir_id) . iter ( ) . fold ( span, |acc, attr| {
479- if attr. is_doc_comment ( ) {
480- return acc;
481- }
482- acc. to ( attr. span ( ) )
483- } ) )
457+ ) || span_has_safety_comment ( cx, span, accept_comment_above_attributes)
484458}
485459
486460#[ derive( Debug ) ]
@@ -497,7 +471,7 @@ fn item_has_safety_comment(
497471 item : & hir:: Item < ' _ > ,
498472 accept_comment_above_attributes : bool ,
499473) -> HasSafetyComment {
500- match span_from_macro_expansion_has_safety_comment ( cx, item. span ) {
474+ match span_from_macro_expansion_has_safety_comment ( cx, item. span , accept_comment_above_attributes ) {
501475 HasSafetyComment :: Maybe => ( ) ,
502476 has_safety_comment => return has_safety_comment,
503477 }
@@ -530,15 +504,10 @@ fn item_has_safety_comment(
530504 } ,
531505 } ;
532506
533- let mut span = item. span ;
534- if accept_comment_above_attributes {
535- span = include_attrs_in_span ( cx, item. hir_id ( ) , span) ;
536- }
537-
538507 let source_map = cx. sess ( ) . source_map ( ) ;
539508 // If the comment is in the first line of the file, there is no preceding line
540509 if let Some ( comment_start) = comment_start
541- && let Ok ( unsafe_line) = source_map. lookup_line ( span. lo ( ) )
510+ && let Ok ( unsafe_line) = source_map. lookup_line ( item . span . lo ( ) )
542511 && let Ok ( comment_start_line) = source_map. lookup_line ( comment_start. into ( ) )
543512 && let include_first_line_of_file = matches ! ( comment_start, CommentStartBeforeItem :: Start )
544513 && ( include_first_line_of_file || Arc :: ptr_eq ( & unsafe_line. sf , & comment_start_line. sf ) )
@@ -552,6 +521,7 @@ fn item_has_safety_comment(
552521 & unsafe_line. sf . lines ( )
553522 [ ( comment_start_line. line + usize:: from ( !include_first_line_of_file) ) ..=unsafe_line. line ] ,
554523 unsafe_line. sf . start_pos ,
524+ accept_comment_above_attributes,
555525 ) {
556526 Some ( b) => HasSafetyComment :: Yes ( b) ,
557527 None => HasSafetyComment :: No ,
@@ -569,7 +539,7 @@ fn stmt_has_safety_comment(
569539 hir_id : HirId ,
570540 accept_comment_above_attributes : bool ,
571541) -> HasSafetyComment {
572- match span_from_macro_expansion_has_safety_comment ( cx, span) {
542+ match span_from_macro_expansion_has_safety_comment ( cx, span, accept_comment_above_attributes ) {
573543 HasSafetyComment :: Maybe => ( ) ,
574544 has_safety_comment => return has_safety_comment,
575545 }
@@ -583,26 +553,21 @@ fn stmt_has_safety_comment(
583553 _ => return HasSafetyComment :: Maybe ,
584554 } ;
585555
586- let mut span = span;
587- if accept_comment_above_attributes {
588- span = include_attrs_in_span ( cx, hir_id, span) ;
589- }
590-
591556 let source_map = cx. sess ( ) . source_map ( ) ;
592557 if let Some ( comment_start) = comment_start
593558 && let Ok ( unsafe_line) = source_map. lookup_line ( span. lo ( ) )
594559 && let Ok ( comment_start_line) = source_map. lookup_line ( comment_start)
595560 && Arc :: ptr_eq ( & unsafe_line. sf , & comment_start_line. sf )
596561 && let Some ( src) = unsafe_line. sf . src . as_deref ( )
597562 {
598- // dbg!(src);
599563 return if comment_start_line. line >= unsafe_line. line {
600564 HasSafetyComment :: No
601565 } else {
602566 match text_has_safety_comment (
603567 src,
604568 & unsafe_line. sf . lines ( ) [ comment_start_line. line + 1 ..=unsafe_line. line ] ,
605569 unsafe_line. sf . start_pos ,
570+ accept_comment_above_attributes,
606571 ) {
607572 Some ( b) => HasSafetyComment :: Yes ( b) ,
608573 None => HasSafetyComment :: No ,
@@ -659,7 +624,11 @@ fn comment_start_before_item_in_mod(
659624 } )
660625}
661626
662- fn span_from_macro_expansion_has_safety_comment ( cx : & LateContext < ' _ > , span : Span ) -> HasSafetyComment {
627+ fn span_from_macro_expansion_has_safety_comment (
628+ cx : & LateContext < ' _ > ,
629+ span : Span ,
630+ accept_comment_above_attributes : bool ,
631+ ) -> HasSafetyComment {
663632 let source_map = cx. sess ( ) . source_map ( ) ;
664633 let ctxt = span. ctxt ( ) ;
665634 if ctxt == SyntaxContext :: root ( ) {
@@ -679,6 +648,7 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span
679648 src,
680649 & unsafe_line. sf . lines ( ) [ macro_line. line + 1 ..=unsafe_line. line ] ,
681650 unsafe_line. sf . start_pos ,
651+ accept_comment_above_attributes,
682652 ) {
683653 Some ( b) => HasSafetyComment :: Yes ( b) ,
684654 None => HasSafetyComment :: No ,
@@ -725,7 +695,7 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
725695 None
726696}
727697
728- fn span_has_safety_comment ( cx : & LateContext < ' _ > , span : Span ) -> bool {
698+ fn span_has_safety_comment ( cx : & LateContext < ' _ > , span : Span , accept_comment_above_attributes : bool ) -> bool {
729699 let source_map = cx. sess ( ) . source_map ( ) ;
730700 let ctxt = span. ctxt ( ) ;
731701 if ctxt. is_root ( )
@@ -745,6 +715,7 @@ fn span_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
745715 src,
746716 & unsafe_line. sf . lines ( ) [ body_line. line + 1 ..=unsafe_line. line ] ,
747717 unsafe_line. sf . start_pos ,
718+ accept_comment_above_attributes,
748719 )
749720 . is_some ( )
750721 } else {
@@ -757,7 +728,14 @@ fn span_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
757728}
758729
759730/// Checks if the given text has a safety comment for the immediately proceeding line.
760- fn text_has_safety_comment ( src : & str , line_starts : & [ RelativeBytePos ] , start_pos : BytePos ) -> Option < BytePos > {
731+ ///
732+ /// If `accept_comment_above_attributes` is true, it will ignore attributes inbetween blocks of comments
733+ fn text_has_safety_comment (
734+ src : & str ,
735+ line_starts : & [ RelativeBytePos ] ,
736+ start_pos : BytePos ,
737+ accept_comment_above_attributes : bool ,
738+ ) -> Option < BytePos > {
761739 let mut lines = line_starts
762740 . array_windows :: < 2 > ( )
763741 . rev ( )
@@ -768,7 +746,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos
768746 let trimmed = text. trim_start ( ) ;
769747 Some ( ( start + ( text. len ( ) - trimmed. len ( ) ) , trimmed) )
770748 } )
771- . filter ( |( _, text) | !text. is_empty ( ) ) ;
749+ . filter ( |( _, text) | !( text. is_empty ( ) || ( accept_comment_above_attributes && is_attribute ( text ) ) ) ) ;
772750
773751 let ( line_start, line) = lines. next ( ) ?;
774752 let mut in_codeblock = false ;
@@ -812,6 +790,10 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos
812790 }
813791}
814792
793+ fn is_attribute ( text : & str ) -> bool {
794+ ( text. starts_with ( "#[" ) || text. starts_with ( "#![" ) ) && text. trim_end ( ) . ends_with ( ']' )
795+ }
796+
815797fn span_and_hid_of_item_alike_node ( node : & Node < ' _ > ) -> Option < ( Span , HirId ) > {
816798 match node {
817799 Node :: Item ( item) => Some ( ( item. span , item. owner_id . into ( ) ) ) ,
0 commit comments