@@ -113,7 +113,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks {
113
113
&& !block. span . in_external_macro ( cx. tcx . sess . source_map ( ) )
114
114
&& !is_lint_allowed ( cx, UNDOCUMENTED_UNSAFE_BLOCKS , block. hir_id )
115
115
&& !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 )
117
117
&& !block_parents_have_safety_comment (
118
118
self . accept_comment_above_statement ,
119
119
self . accept_comment_above_attributes ,
@@ -408,46 +408,29 @@ fn block_parents_have_safety_comment(
408
408
cx : & LateContext < ' _ > ,
409
409
id : HirId ,
410
410
) -> 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 ,
413
413
Node :: Stmt ( hir:: Stmt {
414
414
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, .. } ) ,
418
418
..
419
419
} )
420
- | Node :: LetStmt ( hir:: LetStmt { span, hir_id , .. } ) => ( * span, * hir_id ) ,
420
+ | Node :: LetStmt ( hir:: LetStmt { span, .. } ) => * span,
421
421
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)
423
423
&& is_const_or_static ( & node) =>
424
424
{
425
- ( span, hir_id )
425
+ span
426
426
} ,
427
427
428
428
_ => return false ,
429
429
} ;
430
430
// if unsafe block is part of a let/const/static statement,
431
431
// and accept_comment_above_statement is set to true
432
432
// 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)
451
434
}
452
435
453
436
/// Checks if an expression is "branchy", e.g. loop, match/if/etc.
@@ -459,7 +442,7 @@ fn is_branchy(expr: &hir::Expr<'_>) -> bool {
459
442
}
460
443
461
444
/// 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 {
463
446
// This intentionally ignores text before the start of a function so something like:
464
447
// ```
465
448
// // SAFETY: reason
@@ -469,18 +452,9 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
469
452
// attributes and doc comments.
470
453
471
454
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 ) ,
473
456
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)
484
458
}
485
459
486
460
#[ derive( Debug ) ]
@@ -497,7 +471,7 @@ fn item_has_safety_comment(
497
471
item : & hir:: Item < ' _ > ,
498
472
accept_comment_above_attributes : bool ,
499
473
) -> 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 ) {
501
475
HasSafetyComment :: Maybe => ( ) ,
502
476
has_safety_comment => return has_safety_comment,
503
477
}
@@ -530,15 +504,10 @@ fn item_has_safety_comment(
530
504
} ,
531
505
} ;
532
506
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
-
538
507
let source_map = cx. sess ( ) . source_map ( ) ;
539
508
// If the comment is in the first line of the file, there is no preceding line
540
509
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 ( ) )
542
511
&& let Ok ( comment_start_line) = source_map. lookup_line ( comment_start. into ( ) )
543
512
&& let include_first_line_of_file = matches ! ( comment_start, CommentStartBeforeItem :: Start )
544
513
&& ( include_first_line_of_file || Arc :: ptr_eq ( & unsafe_line. sf , & comment_start_line. sf ) )
@@ -552,6 +521,7 @@ fn item_has_safety_comment(
552
521
& unsafe_line. sf . lines ( )
553
522
[ ( comment_start_line. line + usize:: from ( !include_first_line_of_file) ) ..=unsafe_line. line ] ,
554
523
unsafe_line. sf . start_pos ,
524
+ accept_comment_above_attributes,
555
525
) {
556
526
Some ( b) => HasSafetyComment :: Yes ( b) ,
557
527
None => HasSafetyComment :: No ,
@@ -569,7 +539,7 @@ fn stmt_has_safety_comment(
569
539
hir_id : HirId ,
570
540
accept_comment_above_attributes : bool ,
571
541
) -> 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 ) {
573
543
HasSafetyComment :: Maybe => ( ) ,
574
544
has_safety_comment => return has_safety_comment,
575
545
}
@@ -583,26 +553,21 @@ fn stmt_has_safety_comment(
583
553
_ => return HasSafetyComment :: Maybe ,
584
554
} ;
585
555
586
- let mut span = span;
587
- if accept_comment_above_attributes {
588
- span = include_attrs_in_span ( cx, hir_id, span) ;
589
- }
590
-
591
556
let source_map = cx. sess ( ) . source_map ( ) ;
592
557
if let Some ( comment_start) = comment_start
593
558
&& let Ok ( unsafe_line) = source_map. lookup_line ( span. lo ( ) )
594
559
&& let Ok ( comment_start_line) = source_map. lookup_line ( comment_start)
595
560
&& Arc :: ptr_eq ( & unsafe_line. sf , & comment_start_line. sf )
596
561
&& let Some ( src) = unsafe_line. sf . src . as_deref ( )
597
562
{
598
- // dbg!(src);
599
563
return if comment_start_line. line >= unsafe_line. line {
600
564
HasSafetyComment :: No
601
565
} else {
602
566
match text_has_safety_comment (
603
567
src,
604
568
& unsafe_line. sf . lines ( ) [ comment_start_line. line + 1 ..=unsafe_line. line ] ,
605
569
unsafe_line. sf . start_pos ,
570
+ accept_comment_above_attributes,
606
571
) {
607
572
Some ( b) => HasSafetyComment :: Yes ( b) ,
608
573
None => HasSafetyComment :: No ,
@@ -659,7 +624,11 @@ fn comment_start_before_item_in_mod(
659
624
} )
660
625
}
661
626
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 {
663
632
let source_map = cx. sess ( ) . source_map ( ) ;
664
633
let ctxt = span. ctxt ( ) ;
665
634
if ctxt == SyntaxContext :: root ( ) {
@@ -679,6 +648,7 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span
679
648
src,
680
649
& unsafe_line. sf . lines ( ) [ macro_line. line + 1 ..=unsafe_line. line ] ,
681
650
unsafe_line. sf . start_pos ,
651
+ accept_comment_above_attributes,
682
652
) {
683
653
Some ( b) => HasSafetyComment :: Yes ( b) ,
684
654
None => HasSafetyComment :: No ,
@@ -725,7 +695,7 @@ fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> {
725
695
None
726
696
}
727
697
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 {
729
699
let source_map = cx. sess ( ) . source_map ( ) ;
730
700
let ctxt = span. ctxt ( ) ;
731
701
if ctxt. is_root ( )
@@ -745,6 +715,7 @@ fn span_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
745
715
src,
746
716
& unsafe_line. sf . lines ( ) [ body_line. line + 1 ..=unsafe_line. line ] ,
747
717
unsafe_line. sf . start_pos ,
718
+ accept_comment_above_attributes,
748
719
)
749
720
. is_some ( )
750
721
} else {
@@ -757,7 +728,14 @@ fn span_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool {
757
728
}
758
729
759
730
/// 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 > {
761
739
let mut lines = line_starts
762
740
. array_windows :: < 2 > ( )
763
741
. rev ( )
@@ -768,7 +746,7 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos
768
746
let trimmed = text. trim_start ( ) ;
769
747
Some ( ( start + ( text. len ( ) - trimmed. len ( ) ) , trimmed) )
770
748
} )
771
- . filter ( |( _, text) | !text. is_empty ( ) ) ;
749
+ . filter ( |( _, text) | !( text. is_empty ( ) || ( accept_comment_above_attributes && is_attribute ( text ) ) ) ) ;
772
750
773
751
let ( line_start, line) = lines. next ( ) ?;
774
752
let mut in_codeblock = false ;
@@ -812,6 +790,10 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos
812
790
}
813
791
}
814
792
793
+ fn is_attribute ( text : & str ) -> bool {
794
+ ( text. starts_with ( "#[" ) || text. starts_with ( "#![" ) ) && text. trim_end ( ) . ends_with ( ']' )
795
+ }
796
+
815
797
fn span_and_hid_of_item_alike_node ( node : & Node < ' _ > ) -> Option < ( Span , HirId ) > {
816
798
match node {
817
799
Node :: Item ( item) => Some ( ( item. span , item. owner_id . into ( ) ) ) ,
0 commit comments