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.
@@ -529,81 +511,189 @@ enum UnsafeOpKind {
529
511
use UnsafeOpKind :: * ;
530
512
531
513
impl UnsafeOpKind {
532
- pub fn simple_description ( & self ) -> & ' static str {
533
- match self {
534
- CallToUnsafeFunction ( ..) => "call to unsafe function" ,
535
- UseOfInlineAssembly => "use of inline assembly" ,
536
- InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr" ,
537
- UseOfMutableStatic => "use of mutable static" ,
538
- UseOfExternStatic => "use of extern static" ,
539
- DerefOfRawPointer => "dereference of raw pointer" ,
540
- AccessToUnionField => "access to union field" ,
541
- MutationOfLayoutConstrainedField => "mutation of layout constrained field" ,
542
- BorrowOfLayoutConstrainedField => {
543
- "borrow of layout constrained field with interior mutability"
544
- }
545
- CallToFunctionWith ( ..) => "call to function with `#[target_feature]`" ,
546
- }
547
- }
548
-
549
- pub fn description_and_note ( & self , tcx : TyCtxt < ' _ > ) -> ( Cow < ' static , str > , & ' static str ) {
514
+ pub fn emit_unsafe_op_in_unsafe_fn_lint (
515
+ & self ,
516
+ tcx : TyCtxt < ' _ > ,
517
+ hir_id : hir:: HirId ,
518
+ span : Span ,
519
+ ) {
550
520
match self {
551
- CallToUnsafeFunction ( did) => (
552
- if let Some ( did) = did {
553
- Cow :: from ( format ! ( "call to unsafe function `{}`" , tcx. def_path_str( * did) ) )
554
- } else {
555
- Cow :: Borrowed ( self . simple_description ( ) )
521
+ CallToUnsafeFunction ( did) if did. is_some ( ) => tcx. emit_spanned_lint (
522
+ UNSAFE_OP_IN_UNSAFE_FN ,
523
+ hir_id,
524
+ span,
525
+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe {
526
+ span,
527
+ function : & tcx. def_path_str ( did. unwrap ( ) ) ,
556
528
} ,
557
- "consult the function's documentation for information on how to avoid undefined \
558
- behavior",
559
529
) ,
560
- UseOfInlineAssembly => (
561
- Cow :: Borrowed ( self . simple_description ( ) ) ,
562
- "inline assembly is entirely unchecked and can cause undefined behavior" ,
530
+ CallToUnsafeFunction ( ..) => tcx. emit_spanned_lint (
531
+ UNSAFE_OP_IN_UNSAFE_FN ,
532
+ hir_id,
533
+ span,
534
+ UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span } ,
535
+ ) ,
536
+ UseOfInlineAssembly => tcx. emit_spanned_lint (
537
+ UNSAFE_OP_IN_UNSAFE_FN ,
538
+ hir_id,
539
+ span,
540
+ UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span } ,
563
541
) ,
564
- InitializingTypeWith => (
565
- Cow :: Borrowed ( self . simple_description ( ) ) ,
566
- "initializing a layout restricted type's field with a value outside the valid \
567
- range is undefined behavior",
542
+ InitializingTypeWith => tcx. emit_spanned_lint (
543
+ UNSAFE_OP_IN_UNSAFE_FN ,
544
+ hir_id,
545
+ span,
546
+ UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span } ,
568
547
) ,
569
- UseOfMutableStatic => (
570
- Cow :: Borrowed ( self . simple_description ( ) ) ,
571
- "mutable statics can be mutated by multiple threads: aliasing violations or data \
572
- races will cause undefined behavior",
548
+ UseOfMutableStatic => tcx. emit_spanned_lint (
549
+ UNSAFE_OP_IN_UNSAFE_FN ,
550
+ hir_id,
551
+ span,
552
+ UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span } ,
573
553
) ,
574
- UseOfExternStatic => (
575
- Cow :: Borrowed ( self . simple_description ( ) ) ,
576
- "extern statics are not controlled by the Rust type system: invalid data, \
577
- aliasing violations or data races will cause undefined behavior",
554
+ UseOfExternStatic => tcx. emit_spanned_lint (
555
+ UNSAFE_OP_IN_UNSAFE_FN ,
556
+ hir_id,
557
+ span,
558
+ UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span } ,
578
559
) ,
579
- DerefOfRawPointer => (
580
- Cow :: Borrowed ( self . simple_description ( ) ) ,
581
- "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
582
- and cause data races: all of these are undefined behavior",
560
+ DerefOfRawPointer => tcx. emit_spanned_lint (
561
+ UNSAFE_OP_IN_UNSAFE_FN ,
562
+ hir_id,
563
+ span,
564
+ UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span } ,
583
565
) ,
584
- AccessToUnionField => (
585
- Cow :: Borrowed ( self . simple_description ( ) ) ,
586
- "the field may not be properly initialized: using uninitialized data will cause \
587
- undefined behavior",
566
+ AccessToUnionField => tcx. emit_spanned_lint (
567
+ UNSAFE_OP_IN_UNSAFE_FN ,
568
+ hir_id,
569
+ span,
570
+ UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span } ,
588
571
) ,
589
- MutationOfLayoutConstrainedField => (
590
- Cow :: Borrowed ( self . simple_description ( ) ) ,
591
- "mutating layout constrained fields cannot statically be checked for valid values" ,
572
+ MutationOfLayoutConstrainedField => tcx. emit_spanned_lint (
573
+ UNSAFE_OP_IN_UNSAFE_FN ,
574
+ hir_id,
575
+ span,
576
+ UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span } ,
592
577
) ,
593
- BorrowOfLayoutConstrainedField => (
594
- Cow :: Borrowed ( self . simple_description ( ) ) ,
595
- "references to fields of layout constrained fields lose the constraints. Coupled \
596
- with interior mutability, the field can be changed to invalid values",
578
+ BorrowOfLayoutConstrainedField => tcx. emit_spanned_lint (
579
+ UNSAFE_OP_IN_UNSAFE_FN ,
580
+ hir_id,
581
+ span,
582
+ UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span } ,
597
583
) ,
598
- CallToFunctionWith ( did) => (
599
- Cow :: from ( format ! (
600
- "call to function `{}` with `#[target_feature]`" ,
601
- tcx. def_path_str( * did)
602
- ) ) ,
603
- "can only be called if the required target features are available" ,
584
+ CallToFunctionWith ( did) => tcx. emit_spanned_lint (
585
+ UNSAFE_OP_IN_UNSAFE_FN ,
586
+ hir_id,
587
+ span,
588
+ UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe {
589
+ span,
590
+ function : & tcx. def_path_str ( * did) ,
591
+ } ,
604
592
) ,
605
593
}
606
594
}
595
+
596
+ pub fn emit_requires_unsafe_err (
597
+ & self ,
598
+ tcx : TyCtxt < ' _ > ,
599
+ span : Span ,
600
+ unsafe_op_in_unsafe_fn_allowed : bool ,
601
+ ) {
602
+ match self {
603
+ CallToUnsafeFunction ( did) if did. is_some ( ) && unsafe_op_in_unsafe_fn_allowed => {
604
+ tcx. sess . emit_err ( CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
605
+ span,
606
+ function : & tcx. def_path_str ( did. unwrap ( ) ) ,
607
+ } ) ;
608
+ }
609
+ CallToUnsafeFunction ( did) if did. is_some ( ) => {
610
+ tcx. sess . emit_err ( CallToUnsafeFunctionRequiresUnsafe {
611
+ span,
612
+ function : & tcx. def_path_str ( did. unwrap ( ) ) ,
613
+ } ) ;
614
+ }
615
+ CallToUnsafeFunction ( ..) if unsafe_op_in_unsafe_fn_allowed => {
616
+ tcx. sess . emit_err (
617
+ CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span } ,
618
+ ) ;
619
+ }
620
+ CallToUnsafeFunction ( ..) => {
621
+ tcx. sess . emit_err ( CallToUnsafeFunctionRequiresUnsafeNameless { span } ) ;
622
+ }
623
+ UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => {
624
+ tcx. sess
625
+ . emit_err ( UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
626
+ }
627
+ UseOfInlineAssembly => {
628
+ tcx. sess . emit_err ( UseOfInlineAssemblyRequiresUnsafe { span } ) ;
629
+ }
630
+ InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => {
631
+ tcx. sess
632
+ . emit_err ( InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
633
+ }
634
+ InitializingTypeWith => {
635
+ tcx. sess . emit_err ( InitializingTypeWithRequiresUnsafe { span } ) ;
636
+ }
637
+ UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => {
638
+ tcx. sess
639
+ . emit_err ( UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
640
+ }
641
+ UseOfMutableStatic => {
642
+ tcx. sess . emit_err ( UseOfMutableStaticRequiresUnsafe { span } ) ;
643
+ }
644
+ UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => {
645
+ tcx. sess
646
+ . emit_err ( UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
647
+ }
648
+ UseOfExternStatic => {
649
+ tcx. sess . emit_err ( UseOfExternStaticRequiresUnsafe { span } ) ;
650
+ }
651
+ DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => {
652
+ tcx. sess
653
+ . emit_err ( DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
654
+ }
655
+ DerefOfRawPointer => {
656
+ tcx. sess . emit_err ( DerefOfRawPointerRequiresUnsafe { span } ) ;
657
+ }
658
+ AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => {
659
+ tcx. sess
660
+ . emit_err ( AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ) ;
661
+ }
662
+ AccessToUnionField => {
663
+ tcx. sess . emit_err ( AccessToUnionFieldRequiresUnsafe { span } ) ;
664
+ }
665
+ MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
666
+ tcx. sess . emit_err (
667
+ MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
668
+ span,
669
+ } ,
670
+ ) ;
671
+ }
672
+ MutationOfLayoutConstrainedField => {
673
+ tcx. sess . emit_err ( MutationOfLayoutConstrainedFieldRequiresUnsafe { span } ) ;
674
+ }
675
+ BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => {
676
+ tcx. sess . emit_err (
677
+ BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span } ,
678
+ ) ;
679
+ }
680
+ BorrowOfLayoutConstrainedField => {
681
+ tcx. sess . emit_err ( BorrowOfLayoutConstrainedFieldRequiresUnsafe { span } ) ;
682
+ }
683
+ CallToFunctionWith ( did) if unsafe_op_in_unsafe_fn_allowed => {
684
+ tcx. sess . emit_err ( CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
685
+ span,
686
+ function : & tcx. def_path_str ( * did) ,
687
+ } ) ;
688
+ }
689
+ CallToFunctionWith ( did) => {
690
+ tcx. sess . emit_err ( CallToFunctionWithRequiresUnsafe {
691
+ span,
692
+ function : & tcx. def_path_str ( * did) ,
693
+ } ) ;
694
+ }
695
+ }
696
+ }
607
697
}
608
698
609
699
pub fn check_unsafety < ' tcx > ( tcx : TyCtxt < ' tcx > , def : ty:: WithOptConstParam < LocalDefId > ) {
0 commit comments