11use crate :: build:: ExprCategory ;
2+ use crate :: errors:: * ;
23use rustc_middle:: thir:: visit:: { self , Visitor } ;
34
4- use rustc_errors:: struct_span_err;
55use rustc_hir as hir;
66use rustc_middle:: mir:: BorrowKind ;
77use rustc_middle:: thir:: * ;
@@ -12,7 +12,6 @@ use rustc_span::def_id::{DefId, LocalDefId};
1212use rustc_span:: symbol:: Symbol ;
1313use rustc_span:: Span ;
1414
15- use std:: borrow:: Cow ;
1615use std:: ops:: Bound ;
1716
1817struct UnsafetyVisitor < ' a , ' tcx > {
@@ -46,7 +45,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
4645 self . warn_unused_unsafe (
4746 hir_id,
4847 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+ } ) ,
5051 ) ;
5152 f ( self ) ;
5253 } else {
@@ -60,7 +61,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
6061 hir_id,
6162 span,
6263 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 } )
6467 } else {
6568 None
6669 } ,
@@ -83,30 +86,11 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
8386 }
8487 SafetyContext :: UnsafeFn if unsafe_op_in_unsafe_fn_allowed => { }
8588 SafetyContext :: UnsafeFn => {
86- let ( description, note) = kind. description_and_note ( self . tcx ) ;
8789 // 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) ;
9591 }
9692 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) ;
11094 }
11195 }
11296 }
@@ -115,17 +99,15 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
11599 & self ,
116100 hir_id : hir:: HirId ,
117101 block_span : Span ,
118- enclosing_unsafe : Option < ( Span , & ' static str ) > ,
102+ enclosing_unsafe : Option < UnusedUnsafeEnclosing > ,
119103 ) {
120104 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+ ) ;
129111 }
130112
131113 /// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node.
@@ -536,81 +518,189 @@ enum UnsafeOpKind {
536518use UnsafeOpKind :: * ;
537519
538520impl 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+ ) {
557527 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 ( ) ) ,
563535 } ,
564- "consult the function's documentation for information on how to avoid undefined \
565- behavior",
566536 ) ,
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 } ,
570548 ) ,
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 } ,
575554 ) ,
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 } ,
580560 ) ,
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 } ,
585566 ) ,
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 } ,
590572 ) ,
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 } ,
595578 ) ,
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 } ,
599584 ) ,
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 } ,
604590 ) ,
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+ } ,
611599 ) ,
612600 }
613601 }
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+ }
614704}
615705
616706pub fn check_unsafety < ' tcx > ( tcx : TyCtxt < ' tcx > , def : ty:: WithOptConstParam < LocalDefId > ) {
0 commit comments