@@ -35,6 +35,10 @@ struct UnsafetyVisitor<'a, 'tcx> {
3535    param_env :  ParamEnv < ' tcx > , 
3636    inside_adt :  bool , 
3737    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 , 
3842} 
3943
4044impl < ' tcx >  UnsafetyVisitor < ' _ ,  ' tcx >  { 
@@ -95,7 +99,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
9599            SafetyContext :: UnsafeFn  if  unsafe_op_in_unsafe_fn_allowed => { } 
96100            SafetyContext :: UnsafeFn  => { 
97101                // 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 ; 
99109            } 
100110            SafetyContext :: Safe  => { 
101111                kind. emit_requires_unsafe_err ( 
@@ -297,6 +307,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
297307            } 
298308            PatKind :: InlineConstant  {  def,  .. }  => { 
299309                self . visit_inner_body ( * def) ; 
310+                 visit:: walk_pat ( self ,  pat) ; 
300311            } 
301312            _ => { 
302313                visit:: walk_pat ( self ,  pat) ; 
@@ -394,7 +405,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
394405                } 
395406            } 
396407            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+                 { 
398411                    if  self . tcx . is_mutable_static ( def_id)  { 
399412                        self . requires_unsafe ( expr. span ,  UseOfMutableStatic ) ; 
400413                    }  else  if  self . tcx . is_foreign_item ( def_id)  { 
@@ -482,14 +495,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
482495                    } 
483496                } 
484497            } 
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-             } 
493498            _ => { } 
494499        } 
495500        visit:: walk_expr ( self ,  expr) ; 
@@ -543,7 +548,22 @@ impl UnsafeOpKind {
543548        tcx :  TyCtxt < ' _ > , 
544549        hir_id :  hir:: HirId , 
545550        span :  Span , 
551+         suggest_unsafe_block :  bool , 
546552    )  { 
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+         } ; 
547567        // FIXME: ideally we would want to trim the def paths, but this is not 
548568        // feasible with the current lint emission API (see issue #106126). 
549569        match  self  { 
@@ -554,61 +574,89 @@ impl UnsafeOpKind {
554574                UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe  { 
555575                    span, 
556576                    function :  & with_no_trimmed_paths ! ( tcx. def_path_str( * did) ) , 
577+                     unsafe_not_inherited_note, 
557578                } , 
558579            ) , 
559580            CallToUnsafeFunction ( None )  => tcx. emit_spanned_lint ( 
560581                UNSAFE_OP_IN_UNSAFE_FN , 
561582                hir_id, 
562583                span, 
563-                 UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless  {  span } , 
584+                 UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless  { 
585+                     span, 
586+                     unsafe_not_inherited_note, 
587+                 } , 
564588            ) , 
565589            UseOfInlineAssembly  => tcx. emit_spanned_lint ( 
566590                UNSAFE_OP_IN_UNSAFE_FN , 
567591                hir_id, 
568592                span, 
569-                 UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe  {  span } , 
593+                 UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe  { 
594+                     span, 
595+                     unsafe_not_inherited_note, 
596+                 } , 
570597            ) , 
571598            InitializingTypeWith  => tcx. emit_spanned_lint ( 
572599                UNSAFE_OP_IN_UNSAFE_FN , 
573600                hir_id, 
574601                span, 
575-                 UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe  {  span } , 
602+                 UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe  { 
603+                     span, 
604+                     unsafe_not_inherited_note, 
605+                 } , 
576606            ) , 
577607            UseOfMutableStatic  => tcx. emit_spanned_lint ( 
578608                UNSAFE_OP_IN_UNSAFE_FN , 
579609                hir_id, 
580610                span, 
581-                 UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe  {  span } , 
611+                 UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe  { 
612+                     span, 
613+                     unsafe_not_inherited_note, 
614+                 } , 
582615            ) , 
583616            UseOfExternStatic  => tcx. emit_spanned_lint ( 
584617                UNSAFE_OP_IN_UNSAFE_FN , 
585618                hir_id, 
586619                span, 
587-                 UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe  {  span } , 
620+                 UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe  { 
621+                     span, 
622+                     unsafe_not_inherited_note, 
623+                 } , 
588624            ) , 
589625            DerefOfRawPointer  => tcx. emit_spanned_lint ( 
590626                UNSAFE_OP_IN_UNSAFE_FN , 
591627                hir_id, 
592628                span, 
593-                 UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe  {  span } , 
629+                 UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe  { 
630+                     span, 
631+                     unsafe_not_inherited_note, 
632+                 } , 
594633            ) , 
595634            AccessToUnionField  => tcx. emit_spanned_lint ( 
596635                UNSAFE_OP_IN_UNSAFE_FN , 
597636                hir_id, 
598637                span, 
599-                 UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe  {  span } , 
638+                 UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe  { 
639+                     span, 
640+                     unsafe_not_inherited_note, 
641+                 } , 
600642            ) , 
601643            MutationOfLayoutConstrainedField  => tcx. emit_spanned_lint ( 
602644                UNSAFE_OP_IN_UNSAFE_FN , 
603645                hir_id, 
604646                span, 
605-                 UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe  {  span } , 
647+                 UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe  { 
648+                     span, 
649+                     unsafe_not_inherited_note, 
650+                 } , 
606651            ) , 
607652            BorrowOfLayoutConstrainedField  => tcx. emit_spanned_lint ( 
608653                UNSAFE_OP_IN_UNSAFE_FN , 
609654                hir_id, 
610655                span, 
611-                 UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe  {  span } , 
656+                 UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe  { 
657+                     span, 
658+                     unsafe_not_inherited_note, 
659+                 } , 
612660            ) , 
613661            CallToFunctionWith ( did)  => tcx. emit_spanned_lint ( 
614662                UNSAFE_OP_IN_UNSAFE_FN , 
@@ -617,6 +665,7 @@ impl UnsafeOpKind {
617665                UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe  { 
618666                    span, 
619667                    function :  & with_no_trimmed_paths ! ( tcx. def_path_str( * did) ) , 
668+                     unsafe_not_inherited_note, 
620669                } , 
621670            ) , 
622671        } 
@@ -831,6 +880,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
831880        param_env :  tcx. param_env ( def) , 
832881        inside_adt :  false , 
833882        warnings :  & mut  warnings, 
883+         suggest_unsafe_block :  true , 
834884    } ; 
835885    visitor. visit_expr ( & thir[ expr] ) ; 
836886
0 commit comments