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.
@@ -529,81 +511,189 @@ enum UnsafeOpKind {
529511use UnsafeOpKind :: * ;
530512
531513impl 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+ ) {
550520 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 ( ) ) ,
556528 } ,
557- "consult the function's documentation for information on how to avoid undefined \
558- behavior",
559529 ) ,
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 } ,
563541 ) ,
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 } ,
568547 ) ,
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 } ,
573553 ) ,
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 } ,
578559 ) ,
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 } ,
583565 ) ,
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 } ,
588571 ) ,
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 } ,
592577 ) ,
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 } ,
597583 ) ,
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+ } ,
604592 ) ,
605593 }
606594 }
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+ }
607697}
608698
609699pub fn check_unsafety < ' tcx > ( tcx : TyCtxt < ' tcx > , def : ty:: WithOptConstParam < LocalDefId > ) {
0 commit comments