1
1
use crate :: build:: ExprCategory ;
2
+ use crate :: errors:: * ;
2
3
use rustc_middle:: thir:: visit:: { self , Visitor } ;
3
4
4
- use rustc_errors:: struct_span_err;
5
5
use rustc_hir as hir;
6
6
use rustc_middle:: mir:: BorrowKind ;
7
7
use rustc_middle:: thir:: * ;
@@ -12,7 +12,6 @@ use rustc_span::def_id::{DefId, LocalDefId};
12
12
use rustc_span:: symbol:: Symbol ;
13
13
use rustc_span:: Span ;
14
14
15
- use std:: borrow:: Cow ;
16
15
use std:: ops:: Bound ;
17
16
18
17
struct UnsafetyVisitor < ' a , ' tcx > {
@@ -46,7 +45,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
46
45
self . warn_unused_unsafe (
47
46
hir_id,
48
47
block_span,
49
- Some ( ( self . tcx . sess . source_map ( ) . guess_head_span ( enclosing_span) , "block" ) ) ,
48
+ Some ( UnusedUnsafeEnclosing :: Block {
49
+ span : self . tcx . sess . source_map ( ) . guess_head_span ( enclosing_span) ,
50
+ } ) ,
50
51
) ;
51
52
f ( self ) ;
52
53
} else {
@@ -60,7 +61,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
60
61
hir_id,
61
62
span,
62
63
if self . unsafe_op_in_unsafe_fn_allowed ( ) {
63
- self . body_unsafety . unsafe_fn_sig_span ( ) . map ( |span| ( span, "fn" ) )
64
+ self . body_unsafety
65
+ . unsafe_fn_sig_span ( )
66
+ . map ( |span| UnusedUnsafeEnclosing :: Function { span } )
64
67
} else {
65
68
None
66
69
} ,
@@ -83,30 +86,11 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
83
86
}
84
87
SafetyContext :: UnsafeFn if unsafe_op_in_unsafe_fn_allowed => { }
85
88
SafetyContext :: UnsafeFn => {
86
- let ( description, note) = kind. description_and_note ( self . tcx ) ;
87
89
// unsafe_op_in_unsafe_fn is disallowed
88
- self . tcx . struct_span_lint_hir (
89
- UNSAFE_OP_IN_UNSAFE_FN ,
90
- self . hir_context ,
91
- span,
92
- format ! ( "{} is unsafe and requires unsafe block (error E0133)" , description, ) ,
93
- |lint| lint. span_label ( span, kind. simple_description ( ) ) . note ( note) ,
94
- )
90
+ kind. emit_unsafe_op_in_unsafe_fn_lint ( self . tcx , self . hir_context , span) ;
95
91
}
96
92
SafetyContext :: Safe => {
97
- let ( description, note) = kind. description_and_note ( self . tcx ) ;
98
- let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" } ;
99
- struct_span_err ! (
100
- self . tcx. sess,
101
- span,
102
- E0133 ,
103
- "{} is unsafe and requires unsafe{} block" ,
104
- description,
105
- fn_sugg,
106
- )
107
- . span_label ( span, kind. simple_description ( ) )
108
- . note ( note)
109
- . emit ( ) ;
93
+ kind. emit_requires_unsafe_err ( self . tcx , span, unsafe_op_in_unsafe_fn_allowed) ;
110
94
}
111
95
}
112
96
}
@@ -115,17 +99,15 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
115
99
& self ,
116
100
hir_id : hir:: HirId ,
117
101
block_span : Span ,
118
- enclosing_unsafe : Option < ( Span , & ' static str ) > ,
102
+ enclosing_unsafe : Option < UnusedUnsafeEnclosing > ,
119
103
) {
120
104
let block_span = self . tcx . sess . source_map ( ) . guess_head_span ( block_span) ;
121
- let msg = "unnecessary `unsafe` block" ;
122
- self . tcx . struct_span_lint_hir ( UNUSED_UNSAFE , hir_id, block_span, msg, |lint| {
123
- lint. span_label ( block_span, msg) ;
124
- if let Some ( ( span, kind) ) = enclosing_unsafe {
125
- lint. span_label ( span, format ! ( "because it's nested under this `unsafe` {}" , kind) ) ;
126
- }
127
- lint
128
- } ) ;
105
+ self . tcx . emit_spanned_lint (
106
+ UNUSED_UNSAFE ,
107
+ hir_id,
108
+ block_span,
109
+ UnusedUnsafe { span : block_span, enclosing : enclosing_unsafe } ,
110
+ ) ;
129
111
}
130
112
131
113
/// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node.
@@ -536,81 +518,189 @@ enum UnsafeOpKind {
536
518
use UnsafeOpKind :: * ;
537
519
538
520
impl UnsafeOpKind {
539
- pub fn simple_description ( & self ) -> & ' static str {
540
- match self {
541
- CallToUnsafeFunction ( ..) => "call to unsafe function" ,
542
- UseOfInlineAssembly => "use of inline assembly" ,
543
- InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr" ,
544
- UseOfMutableStatic => "use of mutable static" ,
545
- UseOfExternStatic => "use of extern static" ,
546
- DerefOfRawPointer => "dereference of raw pointer" ,
547
- AccessToUnionField => "access to union field" ,
548
- MutationOfLayoutConstrainedField => "mutation of layout constrained field" ,
549
- BorrowOfLayoutConstrainedField => {
550
- "borrow of layout constrained field with interior mutability"
551
- }
552
- CallToFunctionWith ( ..) => "call to function with `#[target_feature]`" ,
553
- }
554
- }
555
-
556
- pub fn description_and_note ( & self , tcx : TyCtxt < ' _ > ) -> ( Cow < ' static , str > , & ' static str ) {
521
+ pub fn emit_unsafe_op_in_unsafe_fn_lint (
522
+ & self ,
523
+ tcx : TyCtxt < ' _ > ,
524
+ hir_id : hir:: HirId ,
525
+ span : Span ,
526
+ ) {
557
527
match self {
558
- CallToUnsafeFunction ( did) => (
559
- if let Some ( did) = did {
560
- Cow :: from ( format ! ( "call to unsafe function `{}`" , tcx. def_path_str( * did) ) )
561
- } else {
562
- Cow :: Borrowed ( self . simple_description ( ) )
528
+ CallToUnsafeFunction ( did) if did. is_some ( ) => tcx. emit_spanned_lint (
529
+ UNSAFE_OP_IN_UNSAFE_FN ,
530
+ hir_id,
531
+ span,
532
+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
533
+ span,
534
+ function : & tcx. def_path_str ( did. unwrap ( ) ) ,
563
535
} ,
564
- "consult the function's documentation for information on how to avoid undefined \
565
- behavior",
566
536
) ,
567
- UseOfInlineAssembly => (
568
- Cow :: Borrowed ( self . simple_description ( ) ) ,
569
- "inline assembly is entirely unchecked and can cause undefined behavior" ,
537
+ CallToUnsafeFunction ( ..) => tcx. emit_spanned_lint (
538
+ UNSAFE_OP_IN_UNSAFE_FN ,
539
+ hir_id,
540
+ span,
541
+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span } ,
542
+ ) ,
543
+ UseOfInlineAssembly => tcx. emit_spanned_lint (
544
+ UNSAFE_OP_IN_UNSAFE_FN ,
545
+ hir_id,
546
+ span,
547
+ UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span } ,
570
548
) ,
571
- InitializingTypeWith => (
572
- Cow :: Borrowed ( self . simple_description ( ) ) ,
573
- "initializing a layout restricted type's field with a value outside the valid \
574
- range is undefined behavior",
549
+ InitializingTypeWith => tcx. emit_spanned_lint (
550
+ UNSAFE_OP_IN_UNSAFE_FN ,
551
+ hir_id,
552
+ span,
553
+ UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span } ,
575
554
) ,
576
- UseOfMutableStatic => (
577
- Cow :: Borrowed ( self . simple_description ( ) ) ,
578
- "mutable statics can be mutated by multiple threads: aliasing violations or data \
579
- races will cause undefined behavior",
555
+ UseOfMutableStatic => tcx. emit_spanned_lint (
556
+ UNSAFE_OP_IN_UNSAFE_FN ,
557
+ hir_id,
558
+ span,
559
+ UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span } ,
580
560
) ,
581
- UseOfExternStatic => (
582
- Cow :: Borrowed ( self . simple_description ( ) ) ,
583
- "extern statics are not controlled by the Rust type system: invalid data, \
584
- aliasing violations or data races will cause undefined behavior",
561
+ UseOfExternStatic => tcx. emit_spanned_lint (
562
+ UNSAFE_OP_IN_UNSAFE_FN ,
563
+ hir_id,
564
+ span,
565
+ UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span } ,
585
566
) ,
586
- DerefOfRawPointer => (
587
- Cow :: Borrowed ( self . simple_description ( ) ) ,
588
- "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
589
- and cause data races: all of these are undefined behavior",
567
+ DerefOfRawPointer => tcx. emit_spanned_lint (
568
+ UNSAFE_OP_IN_UNSAFE_FN ,
569
+ hir_id,
570
+ span,
571
+ UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span } ,
590
572
) ,
591
- AccessToUnionField => (
592
- Cow :: Borrowed ( self . simple_description ( ) ) ,
593
- "the field may not be properly initialized: using uninitialized data will cause \
594
- undefined behavior",
573
+ AccessToUnionField => tcx. emit_spanned_lint (
574
+ UNSAFE_OP_IN_UNSAFE_FN ,
575
+ hir_id,
576
+ span,
577
+ UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span } ,
595
578
) ,
596
- MutationOfLayoutConstrainedField => (
597
- Cow :: Borrowed ( self . simple_description ( ) ) ,
598
- "mutating layout constrained fields cannot statically be checked for valid values" ,
579
+ MutationOfLayoutConstrainedField => tcx. emit_spanned_lint (
580
+ UNSAFE_OP_IN_UNSAFE_FN ,
581
+ hir_id,
582
+ span,
583
+ UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span } ,
599
584
) ,
600
- BorrowOfLayoutConstrainedField => (
601
- Cow :: Borrowed ( self . simple_description ( ) ) ,
602
- "references to fields of layout constrained fields lose the constraints. Coupled \
603
- with interior mutability, the field can be changed to invalid values",
585
+ BorrowOfLayoutConstrainedField => tcx. emit_spanned_lint (
586
+ UNSAFE_OP_IN_UNSAFE_FN ,
587
+ hir_id,
588
+ span,
589
+ UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span } ,
604
590
) ,
605
- CallToFunctionWith ( did) => (
606
- Cow :: from ( format ! (
607
- "call to function `{}` with `#[target_feature]`" ,
608
- tcx. def_path_str( * did)
609
- ) ) ,
610
- "can only be called if the required target features are available" ,
591
+ CallToFunctionWith ( did) => tcx. emit_spanned_lint (
592
+ UNSAFE_OP_IN_UNSAFE_FN ,
593
+ hir_id,
594
+ span,
595
+ UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
596
+ span,
597
+ function : & tcx. def_path_str ( * did) ,
598
+ } ,
611
599
) ,
612
600
}
613
601
}
602
+
603
+ pub fn emit_requires_unsafe_err (
604
+ & self ,
605
+ tcx : TyCtxt < ' _ > ,
606
+ span : Span ,
607
+ unsafe_op_in_unsafe_fn_allowed : bool ,
608
+ ) {
609
+ match self {
610
+ CallToUnsafeFunction ( did) if did. is_some ( ) && unsafe_op_in_unsafe_fn_allowed => {
611
+ tcx. sess . emit_err ( CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
612
+ span,
613
+ function : & tcx. def_path_str ( did. unwrap ( ) ) ,
614
+ } ) ;
615
+ }
616
+ CallToUnsafeFunction ( did) if did. is_some ( ) => {
617
+ tcx. sess . emit_err ( CallToUnsafeFunctionRequiresUnsafe {
618
+ span,
619
+ function : & tcx. def_path_str ( did. unwrap ( ) ) ,
620
+ } ) ;
621
+ }
622
+ CallToUnsafeFunction ( ..) if unsafe_op_in_unsafe_fn_allowed => {
623
+ tcx. sess . emit_err (
624
+ CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span } ,
625
+ ) ;
626
+ }
627
+ CallToUnsafeFunction ( ..) => {
628
+ tcx. sess . emit_err ( CallToUnsafeFunctionRequiresUnsafeNameless { span } ) ;
629
+ }
630
+ UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => {
631
+ tcx. sess
632
+ . emit_err ( UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
633
+ }
634
+ UseOfInlineAssembly => {
635
+ tcx. sess . emit_err ( UseOfInlineAssemblyRequiresUnsafe { span } ) ;
636
+ }
637
+ InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => {
638
+ tcx. sess
639
+ . emit_err ( InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
640
+ }
641
+ InitializingTypeWith => {
642
+ tcx. sess . emit_err ( InitializingTypeWithRequiresUnsafe { span } ) ;
643
+ }
644
+ UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
645
+ tcx. sess
646
+ . emit_err ( UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
647
+ }
648
+ UseOfMutableStatic => {
649
+ tcx. sess . emit_err ( UseOfMutableStaticRequiresUnsafe { span } ) ;
650
+ }
651
+ UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => {
652
+ tcx. sess
653
+ . emit_err ( UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
654
+ }
655
+ UseOfExternStatic => {
656
+ tcx. sess . emit_err ( UseOfExternStaticRequiresUnsafe { span } ) ;
657
+ }
658
+ DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => {
659
+ tcx. sess
660
+ . emit_err ( DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
661
+ }
662
+ DerefOfRawPointer => {
663
+ tcx. sess . emit_err ( DerefOfRawPointerRequiresUnsafe { span } ) ;
664
+ }
665
+ AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => {
666
+ tcx. sess
667
+ . emit_err ( AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
668
+ }
669
+ AccessToUnionField => {
670
+ tcx. sess . emit_err ( AccessToUnionFieldRequiresUnsafe { span } ) ;
671
+ }
672
+ MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
673
+ tcx. sess . emit_err (
674
+ MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
675
+ span,
676
+ } ,
677
+ ) ;
678
+ }
679
+ MutationOfLayoutConstrainedField => {
680
+ tcx. sess . emit_err ( MutationOfLayoutConstrainedFieldRequiresUnsafe { span } ) ;
681
+ }
682
+ BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
683
+ tcx. sess . emit_err (
684
+ BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ,
685
+ ) ;
686
+ }
687
+ BorrowOfLayoutConstrainedField => {
688
+ tcx. sess . emit_err ( BorrowOfLayoutConstrainedFieldRequiresUnsafe { span } ) ;
689
+ }
690
+ CallToFunctionWith ( did) if unsafe_op_in_unsafe_fn_allowed => {
691
+ tcx. sess . emit_err ( CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
692
+ span,
693
+ function : & tcx. def_path_str ( * did) ,
694
+ } ) ;
695
+ }
696
+ CallToFunctionWith ( did) => {
697
+ tcx. sess . emit_err ( CallToFunctionWithRequiresUnsafe {
698
+ span,
699
+ function : & tcx. def_path_str ( * did) ,
700
+ } ) ;
701
+ }
702
+ }
703
+ }
614
704
}
615
705
616
706
pub fn check_unsafety < ' tcx > ( tcx : TyCtxt < ' tcx > , def : ty:: WithOptConstParam < LocalDefId > ) {
0 commit comments