@@ -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) ;
@@ -545,7 +556,22 @@ impl UnsafeOpKind {
545556 tcx : TyCtxt < ' _ > ,
546557 hir_id : hir:: HirId ,
547558 span : Span ,
559+ suggest_unsafe_block : bool ,
548560 ) {
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+ } ;
549575 // FIXME: ideally we would want to trim the def paths, but this is not
550576 // feasible with the current lint emission API (see issue #106126).
551577 match self {
@@ -556,61 +582,89 @@ impl UnsafeOpKind {
556582 UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
557583 span,
558584 function : & with_no_trimmed_paths ! ( tcx. def_path_str( * did) ) ,
585+ unsafe_not_inherited_note,
559586 } ,
560587 ) ,
561588 CallToUnsafeFunction ( None ) => tcx. emit_spanned_lint (
562589 UNSAFE_OP_IN_UNSAFE_FN ,
563590 hir_id,
564591 span,
565- UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span } ,
592+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless {
593+ span,
594+ unsafe_not_inherited_note,
595+ } ,
566596 ) ,
567597 UseOfInlineAssembly => tcx. emit_spanned_lint (
568598 UNSAFE_OP_IN_UNSAFE_FN ,
569599 hir_id,
570600 span,
571- UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span } ,
601+ UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe {
602+ span,
603+ unsafe_not_inherited_note,
604+ } ,
572605 ) ,
573606 InitializingTypeWith => tcx. emit_spanned_lint (
574607 UNSAFE_OP_IN_UNSAFE_FN ,
575608 hir_id,
576609 span,
577- UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span } ,
610+ UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe {
611+ span,
612+ unsafe_not_inherited_note,
613+ } ,
578614 ) ,
579615 UseOfMutableStatic => tcx. emit_spanned_lint (
580616 UNSAFE_OP_IN_UNSAFE_FN ,
581617 hir_id,
582618 span,
583- UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span } ,
619+ UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe {
620+ span,
621+ unsafe_not_inherited_note,
622+ } ,
584623 ) ,
585624 UseOfExternStatic => tcx. emit_spanned_lint (
586625 UNSAFE_OP_IN_UNSAFE_FN ,
587626 hir_id,
588627 span,
589- UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span } ,
628+ UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe {
629+ span,
630+ unsafe_not_inherited_note,
631+ } ,
590632 ) ,
591633 DerefOfRawPointer => tcx. emit_spanned_lint (
592634 UNSAFE_OP_IN_UNSAFE_FN ,
593635 hir_id,
594636 span,
595- UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span } ,
637+ UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe {
638+ span,
639+ unsafe_not_inherited_note,
640+ } ,
596641 ) ,
597642 AccessToUnionField => tcx. emit_spanned_lint (
598643 UNSAFE_OP_IN_UNSAFE_FN ,
599644 hir_id,
600645 span,
601- UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span } ,
646+ UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe {
647+ span,
648+ unsafe_not_inherited_note,
649+ } ,
602650 ) ,
603651 MutationOfLayoutConstrainedField => tcx. emit_spanned_lint (
604652 UNSAFE_OP_IN_UNSAFE_FN ,
605653 hir_id,
606654 span,
607- UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span } ,
655+ UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe {
656+ span,
657+ unsafe_not_inherited_note,
658+ } ,
608659 ) ,
609660 BorrowOfLayoutConstrainedField => tcx. emit_spanned_lint (
610661 UNSAFE_OP_IN_UNSAFE_FN ,
611662 hir_id,
612663 span,
613- UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span } ,
664+ UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe {
665+ span,
666+ unsafe_not_inherited_note,
667+ } ,
614668 ) ,
615669 CallToFunctionWith ( did) => tcx. emit_spanned_lint (
616670 UNSAFE_OP_IN_UNSAFE_FN ,
@@ -619,6 +673,7 @@ impl UnsafeOpKind {
619673 UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
620674 span,
621675 function : & with_no_trimmed_paths ! ( tcx. def_path_str( * did) ) ,
676+ unsafe_not_inherited_note,
622677 } ,
623678 ) ,
624679 }
@@ -833,6 +888,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
833888 param_env : tcx. param_env ( def) ,
834889 inside_adt : false ,
835890 warnings : & mut warnings,
891+ suggest_unsafe_block : true ,
836892 } ;
837893 visitor. visit_expr ( & thir[ expr] ) ;
838894
0 commit comments