@@ -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) ;
@@ -394,7 +405,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
394
405
}
395
406
}
396
407
ExprKind :: Deref { arg } => {
397
- if let ExprKind :: StaticRef { def_id, .. } = self . thir [ arg] . kind {
408
+ if let ExprKind :: StaticRef { def_id, .. } | ExprKind :: ThreadLocalRef ( def_id) =
409
+ self . thir [ arg] . kind
410
+ {
398
411
if self . tcx . is_mutable_static ( def_id) {
399
412
self . requires_unsafe ( expr. span , UseOfMutableStatic ) ;
400
413
} else if self . tcx . is_foreign_item ( def_id) {
@@ -482,14 +495,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
482
495
}
483
496
}
484
497
}
485
- ExprKind :: Let { expr : expr_id, .. } => {
486
- let let_expr = & self . thir [ expr_id] ;
487
- if let ty:: Adt ( adt_def, _) = let_expr. ty . kind ( )
488
- && adt_def. is_union ( )
489
- {
490
- self . requires_unsafe ( expr. span , AccessToUnionField ) ;
491
- }
492
- }
493
498
_ => { }
494
499
}
495
500
visit:: walk_expr ( self , expr) ;
@@ -543,7 +548,22 @@ impl UnsafeOpKind {
543
548
tcx : TyCtxt < ' _ > ,
544
549
hir_id : hir:: HirId ,
545
550
span : Span ,
551
+ suggest_unsafe_block : bool ,
546
552
) {
553
+ let parent_id = tcx. hir ( ) . get_parent_item ( hir_id) ;
554
+ let parent_owner = tcx. hir ( ) . owner ( parent_id) ;
555
+ let should_suggest = parent_owner. fn_sig ( ) . map_or ( false , |sig| sig. header . is_unsafe ( ) ) ;
556
+ let unsafe_not_inherited_note = if should_suggest {
557
+ suggest_unsafe_block. then ( || {
558
+ let body_span = tcx. hir ( ) . body ( parent_owner. body_id ( ) . unwrap ( ) ) . value . span ;
559
+ UnsafeNotInheritedLintNote {
560
+ signature_span : tcx. def_span ( parent_id. def_id ) ,
561
+ body_span,
562
+ }
563
+ } )
564
+ } else {
565
+ None
566
+ } ;
547
567
// FIXME: ideally we would want to trim the def paths, but this is not
548
568
// feasible with the current lint emission API (see issue #106126).
549
569
match self {
@@ -554,61 +574,89 @@ impl UnsafeOpKind {
554
574
UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
555
575
span,
556
576
function : & with_no_trimmed_paths ! ( tcx. def_path_str( * did) ) ,
577
+ unsafe_not_inherited_note,
557
578
} ,
558
579
) ,
559
580
CallToUnsafeFunction ( None ) => tcx. emit_spanned_lint (
560
581
UNSAFE_OP_IN_UNSAFE_FN ,
561
582
hir_id,
562
583
span,
563
- UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span } ,
584
+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
585
+ span,
586
+ unsafe_not_inherited_note,
587
+ } ,
564
588
) ,
565
589
UseOfInlineAssembly => tcx. emit_spanned_lint (
566
590
UNSAFE_OP_IN_UNSAFE_FN ,
567
591
hir_id,
568
592
span,
569
- UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span } ,
593
+ UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
594
+ span,
595
+ unsafe_not_inherited_note,
596
+ } ,
570
597
) ,
571
598
InitializingTypeWith => tcx. emit_spanned_lint (
572
599
UNSAFE_OP_IN_UNSAFE_FN ,
573
600
hir_id,
574
601
span,
575
- UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span } ,
602
+ UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
603
+ span,
604
+ unsafe_not_inherited_note,
605
+ } ,
576
606
) ,
577
607
UseOfMutableStatic => tcx. emit_spanned_lint (
578
608
UNSAFE_OP_IN_UNSAFE_FN ,
579
609
hir_id,
580
610
span,
581
- UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span } ,
611
+ UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
612
+ span,
613
+ unsafe_not_inherited_note,
614
+ } ,
582
615
) ,
583
616
UseOfExternStatic => tcx. emit_spanned_lint (
584
617
UNSAFE_OP_IN_UNSAFE_FN ,
585
618
hir_id,
586
619
span,
587
- UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span } ,
620
+ UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
621
+ span,
622
+ unsafe_not_inherited_note,
623
+ } ,
588
624
) ,
589
625
DerefOfRawPointer => tcx. emit_spanned_lint (
590
626
UNSAFE_OP_IN_UNSAFE_FN ,
591
627
hir_id,
592
628
span,
593
- UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span } ,
629
+ UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
630
+ span,
631
+ unsafe_not_inherited_note,
632
+ } ,
594
633
) ,
595
634
AccessToUnionField => tcx. emit_spanned_lint (
596
635
UNSAFE_OP_IN_UNSAFE_FN ,
597
636
hir_id,
598
637
span,
599
- UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span } ,
638
+ UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
639
+ span,
640
+ unsafe_not_inherited_note,
641
+ } ,
600
642
) ,
601
643
MutationOfLayoutConstrainedField => tcx. emit_spanned_lint (
602
644
UNSAFE_OP_IN_UNSAFE_FN ,
603
645
hir_id,
604
646
span,
605
- UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span } ,
647
+ UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
648
+ span,
649
+ unsafe_not_inherited_note,
650
+ } ,
606
651
) ,
607
652
BorrowOfLayoutConstrainedField => tcx. emit_spanned_lint (
608
653
UNSAFE_OP_IN_UNSAFE_FN ,
609
654
hir_id,
610
655
span,
611
- UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span } ,
656
+ UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
657
+ span,
658
+ unsafe_not_inherited_note,
659
+ } ,
612
660
) ,
613
661
CallToFunctionWith ( did) => tcx. emit_spanned_lint (
614
662
UNSAFE_OP_IN_UNSAFE_FN ,
@@ -617,6 +665,7 @@ impl UnsafeOpKind {
617
665
UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
618
666
span,
619
667
function : & with_no_trimmed_paths ! ( tcx. def_path_str( * did) ) ,
668
+ unsafe_not_inherited_note,
620
669
} ,
621
670
) ,
622
671
}
@@ -831,6 +880,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
831
880
param_env : tcx. param_env ( def) ,
832
881
inside_adt : false ,
833
882
warnings : & mut warnings,
883
+ suggest_unsafe_block : true ,
834
884
} ;
835
885
visitor. visit_expr ( & thir[ expr] ) ;
836
886
0 commit comments