@@ -35,6 +35,10 @@ struct UnsafetyVisitor<'a, 'tcx> {
35
35
param_env : ParamEnv < ' tcx > ,
36
36
inside_adt : bool ,
37
37
warnings : & ' a mut Vec < UnusedUnsafeWarning > ,
38
+
39
+ /// Flag to ensure that we only suggest wrapping the entire function body in
40
+ /// an unsafe block once.
41
+ suggest_unsafe_block : bool ,
38
42
}
39
43
40
44
impl < ' tcx > UnsafetyVisitor < ' _ , ' tcx > {
@@ -95,7 +99,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
95
99
SafetyContext :: UnsafeFn if unsafe_op_in_unsafe_fn_allowed => { }
96
100
SafetyContext :: UnsafeFn => {
97
101
// unsafe_op_in_unsafe_fn is disallowed
98
- kind. emit_unsafe_op_in_unsafe_fn_lint ( self . tcx , self . hir_context , span) ;
102
+ kind. emit_unsafe_op_in_unsafe_fn_lint (
103
+ self . tcx ,
104
+ self . hir_context ,
105
+ span,
106
+ self . suggest_unsafe_block ,
107
+ ) ;
108
+ self . suggest_unsafe_block = false ;
99
109
}
100
110
SafetyContext :: Safe => {
101
111
kind. emit_requires_unsafe_err (
@@ -297,6 +307,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
297
307
}
298
308
PatKind :: InlineConstant { def, .. } => {
299
309
self . visit_inner_body ( * def) ;
310
+ visit:: walk_pat ( self , pat) ;
300
311
}
301
312
_ => {
302
313
visit:: walk_pat ( self , pat) ;
@@ -545,7 +556,22 @@ impl UnsafeOpKind {
545
556
tcx : TyCtxt < ' _ > ,
546
557
hir_id : hir:: HirId ,
547
558
span : Span ,
559
+ suggest_unsafe_block : bool ,
548
560
) {
561
+ let parent_id = tcx. hir ( ) . get_parent_item ( hir_id) ;
562
+ let parent_owner = tcx. hir ( ) . owner ( parent_id) ;
563
+ let should_suggest = parent_owner. fn_sig ( ) . map_or ( false , |sig| sig. header . is_unsafe ( ) ) ;
564
+ let unsafe_not_inherited_note = if should_suggest {
565
+ suggest_unsafe_block. then ( || {
566
+ let body_span = tcx. hir ( ) . body ( parent_owner. body_id ( ) . unwrap ( ) ) . value . span ;
567
+ UnsafeNotInheritedLintNote {
568
+ signature_span : tcx. def_span ( parent_id. def_id ) ,
569
+ body_span,
570
+ }
571
+ } )
572
+ } else {
573
+ None
574
+ } ;
549
575
// FIXME: ideally we would want to trim the def paths, but this is not
550
576
// feasible with the current lint emission API (see issue #106126).
551
577
match self {
@@ -556,61 +582,89 @@ impl UnsafeOpKind {
556
582
UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
557
583
span,
558
584
function : & with_no_trimmed_paths ! ( tcx. def_path_str( * did) ) ,
585
+ unsafe_not_inherited_note,
559
586
} ,
560
587
) ,
561
588
CallToUnsafeFunction ( None ) => tcx. emit_spanned_lint (
562
589
UNSAFE_OP_IN_UNSAFE_FN ,
563
590
hir_id,
564
591
span,
565
- UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span } ,
592
+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
593
+ span,
594
+ unsafe_not_inherited_note,
595
+ } ,
566
596
) ,
567
597
UseOfInlineAssembly => tcx. emit_spanned_lint (
568
598
UNSAFE_OP_IN_UNSAFE_FN ,
569
599
hir_id,
570
600
span,
571
- UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span } ,
601
+ UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
602
+ span,
603
+ unsafe_not_inherited_note,
604
+ } ,
572
605
) ,
573
606
InitializingTypeWith => tcx. emit_spanned_lint (
574
607
UNSAFE_OP_IN_UNSAFE_FN ,
575
608
hir_id,
576
609
span,
577
- UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span } ,
610
+ UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
611
+ span,
612
+ unsafe_not_inherited_note,
613
+ } ,
578
614
) ,
579
615
UseOfMutableStatic => tcx. emit_spanned_lint (
580
616
UNSAFE_OP_IN_UNSAFE_FN ,
581
617
hir_id,
582
618
span,
583
- UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span } ,
619
+ UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
620
+ span,
621
+ unsafe_not_inherited_note,
622
+ } ,
584
623
) ,
585
624
UseOfExternStatic => tcx. emit_spanned_lint (
586
625
UNSAFE_OP_IN_UNSAFE_FN ,
587
626
hir_id,
588
627
span,
589
- UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span } ,
628
+ UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
629
+ span,
630
+ unsafe_not_inherited_note,
631
+ } ,
590
632
) ,
591
633
DerefOfRawPointer => tcx. emit_spanned_lint (
592
634
UNSAFE_OP_IN_UNSAFE_FN ,
593
635
hir_id,
594
636
span,
595
- UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span } ,
637
+ UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
638
+ span,
639
+ unsafe_not_inherited_note,
640
+ } ,
596
641
) ,
597
642
AccessToUnionField => tcx. emit_spanned_lint (
598
643
UNSAFE_OP_IN_UNSAFE_FN ,
599
644
hir_id,
600
645
span,
601
- UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span } ,
646
+ UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
647
+ span,
648
+ unsafe_not_inherited_note,
649
+ } ,
602
650
) ,
603
651
MutationOfLayoutConstrainedField => tcx. emit_spanned_lint (
604
652
UNSAFE_OP_IN_UNSAFE_FN ,
605
653
hir_id,
606
654
span,
607
- UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span } ,
655
+ UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
656
+ span,
657
+ unsafe_not_inherited_note,
658
+ } ,
608
659
) ,
609
660
BorrowOfLayoutConstrainedField => tcx. emit_spanned_lint (
610
661
UNSAFE_OP_IN_UNSAFE_FN ,
611
662
hir_id,
612
663
span,
613
- UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span } ,
664
+ UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
665
+ span,
666
+ unsafe_not_inherited_note,
667
+ } ,
614
668
) ,
615
669
CallToFunctionWith ( did) => tcx. emit_spanned_lint (
616
670
UNSAFE_OP_IN_UNSAFE_FN ,
@@ -619,6 +673,7 @@ impl UnsafeOpKind {
619
673
UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
620
674
span,
621
675
function : & with_no_trimmed_paths ! ( tcx. def_path_str( * did) ) ,
676
+ unsafe_not_inherited_note,
622
677
} ,
623
678
) ,
624
679
}
@@ -833,6 +888,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
833
888
param_env : tcx. param_env ( def) ,
834
889
inside_adt : false ,
835
890
warnings : & mut warnings,
891
+ suggest_unsafe_block : true ,
836
892
} ;
837
893
visitor. visit_expr ( & thir[ expr] ) ;
838
894
0 commit comments