1
1
use rustc_data_structures:: fx:: FxHashMap ;
2
- use rustc_errors:: struct_span_err;
2
+ use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder } ;
3
3
use rustc_hir as hir;
4
4
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
5
5
use rustc_hir:: hir_id:: HirId ;
@@ -569,6 +569,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
569
569
}
570
570
571
571
let UnsafetyCheckResult { violations, unused_unsafes, .. } = tcx. unsafety_check_result ( def_id) ;
572
+ // Only suggest wrapping the entire function body in an unsafe block once
573
+ let mut suggest_unsafe_block = true ;
572
574
573
575
for & UnsafetyViolation { source_info, lint_root, kind, details } in violations. iter ( ) {
574
576
let ( description, note) = details. description_and_note ( ) ;
@@ -597,13 +599,16 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
597
599
lint_root,
598
600
source_info. span ,
599
601
|lint| {
600
- lint. build ( & format ! (
602
+ let mut err = lint. build ( & format ! (
601
603
"{} is unsafe and requires unsafe block (error E0133)" ,
602
604
description,
603
- ) )
604
- . span_label ( source_info. span , description)
605
- . note ( note)
606
- . emit ( ) ;
605
+ ) ) ;
606
+ err. span_label ( source_info. span , description) . note ( note) ;
607
+ if suggest_unsafe_block {
608
+ suggest_wrapping_unsafe_block ( tcx, def_id, & mut err) ;
609
+ suggest_unsafe_block = false ;
610
+ }
611
+ err. emit ( ) ;
607
612
} ,
608
613
) ,
609
614
}
@@ -614,6 +619,25 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
614
619
}
615
620
}
616
621
622
+ fn suggest_wrapping_unsafe_block (
623
+ tcx : TyCtxt < ' _ > ,
624
+ def_id : LocalDefId ,
625
+ err : & mut DiagnosticBuilder < ' _ , ( ) > ,
626
+ ) {
627
+ let body_span = tcx. hir ( ) . body ( tcx. hir ( ) . body_owned_by ( def_id) ) . value . span ;
628
+
629
+ let suggestion = vec ! [
630
+ ( tcx. sess. source_map( ) . start_point( body_span) . shrink_to_hi( ) , " unsafe {" . into( ) ) ,
631
+ ( tcx. sess. source_map( ) . end_point( body_span) . shrink_to_lo( ) , "}" . into( ) ) ,
632
+ ] ;
633
+
634
+ err. multipart_suggestion_verbose (
635
+ "consider wrapping the function in an unsafe block" ,
636
+ suggestion,
637
+ Applicability :: MaybeIncorrect ,
638
+ ) ;
639
+ }
640
+
617
641
fn unsafe_op_in_unsafe_fn_allowed ( tcx : TyCtxt < ' _ > , id : HirId ) -> bool {
618
642
tcx. lint_level_at_node ( UNSAFE_OP_IN_UNSAFE_FN , id) . 0 == Level :: Allow
619
643
}
0 commit comments