@@ -12,6 +12,7 @@ use rustc_span::def_id::{DefId, LocalDefId};
1212use rustc_span:: symbol:: Symbol ;
1313use rustc_span:: Span ;
1414
15+ use std:: borrow:: Cow ;
1516use std:: ops:: Bound ;
1617
1718struct UnsafetyVisitor < ' a , ' tcx > {
@@ -70,7 +71,6 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
7071 }
7172
7273 fn requires_unsafe ( & mut self , span : Span , kind : UnsafeOpKind ) {
73- let ( description, note) = kind. description_and_note ( ) ;
7474 let unsafe_op_in_unsafe_fn_allowed = self . unsafe_op_in_unsafe_fn_allowed ( ) ;
7575 match self . safety_context {
7676 SafetyContext :: BuiltinUnsafeBlock => { }
@@ -82,6 +82,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
8282 }
8383 SafetyContext :: UnsafeFn if unsafe_op_in_unsafe_fn_allowed => { }
8484 SafetyContext :: UnsafeFn => {
85+ let ( description, note) = kind. description_and_note ( self . tcx ) ;
8586 // unsafe_op_in_unsafe_fn is disallowed
8687 self . tcx . struct_span_lint_hir (
8788 UNSAFE_OP_IN_UNSAFE_FN ,
@@ -92,13 +93,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
9293 "{} is unsafe and requires unsafe block (error E0133)" ,
9394 description,
9495 ) )
95- . span_label ( span, description )
96+ . span_label ( span, kind . simple_description ( ) )
9697 . note ( note)
9798 . emit ( ) ;
9899 } ,
99100 )
100101 }
101102 SafetyContext :: Safe => {
103+ let ( description, note) = kind. description_and_note ( self . tcx ) ;
102104 let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" } ;
103105 struct_span_err ! (
104106 self . tcx. sess,
@@ -108,7 +110,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
108110 description,
109111 fn_sugg,
110112 )
111- . span_label ( span, description )
113+ . span_label ( span, kind . simple_description ( ) )
112114 . note ( note)
113115 . emit ( ) ;
114116 }
@@ -350,7 +352,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
350352 }
351353 ExprKind :: Call { fun, ty : _, args : _, from_hir_call : _, fn_span : _ } => {
352354 if self . thir [ fun] . ty . fn_sig ( self . tcx ) . unsafety ( ) == hir:: Unsafety :: Unsafe {
353- self . requires_unsafe ( expr. span , CallToUnsafeFunction ) ;
355+ let func_id = if let ty:: FnDef ( func_id, _) = self . thir [ fun] . ty . kind ( ) {
356+ Some ( * func_id)
357+ } else {
358+ None
359+ } ;
360+ self . requires_unsafe ( expr. span , CallToUnsafeFunction ( func_id) ) ;
354361 } else if let & ty:: FnDef ( func_did, _) = self . thir [ fun] . ty . kind ( ) {
355362 // If the called function has target features the calling function hasn't,
356363 // the call requires `unsafe`. Don't check this on wasm
@@ -364,7 +371,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
364371 . iter ( )
365372 . all ( |feature| self . body_target_features . contains ( feature) )
366373 {
367- self . requires_unsafe ( expr. span , CallToFunctionWith ) ;
374+ self . requires_unsafe ( expr. span , CallToFunctionWith ( func_did ) ) ;
368375 }
369376 }
370377 }
@@ -523,7 +530,7 @@ impl BodyUnsafety {
523530
524531#[ derive( Clone , Copy , PartialEq ) ]
525532enum UnsafeOpKind {
526- CallToUnsafeFunction ,
533+ CallToUnsafeFunction ( Option < DefId > ) ,
527534 UseOfInlineAssembly ,
528535 InitializingTypeWith ,
529536 UseOfMutableStatic ,
@@ -533,64 +540,89 @@ enum UnsafeOpKind {
533540 AccessToUnionField ,
534541 MutationOfLayoutConstrainedField ,
535542 BorrowOfLayoutConstrainedField ,
536- CallToFunctionWith ,
543+ CallToFunctionWith ( DefId ) ,
537544}
538545
539546use UnsafeOpKind :: * ;
540547
541548impl UnsafeOpKind {
542- pub fn description_and_note ( & self ) -> ( & ' static str , & ' static str ) {
549+ pub fn simple_description ( & self ) -> & ' static str {
543550 match self {
544- CallToUnsafeFunction => (
545- "call to unsafe function" ,
551+ CallToUnsafeFunction ( ..) => "call to unsafe function" ,
552+ UseOfInlineAssembly => "use of inline assembly" ,
553+ InitializingTypeWith => "initializing type with `rustc_layout_scalar_valid_range` attr" ,
554+ UseOfMutableStatic => "use of mutable static" ,
555+ UseOfExternStatic => "use of extern static" ,
556+ DerefOfRawPointer => "dereference of raw pointer" ,
557+ AssignToDroppingUnionField => "assignment to union field that might need dropping" ,
558+ AccessToUnionField => "access to union field" ,
559+ MutationOfLayoutConstrainedField => "mutation of layout constrained field" ,
560+ BorrowOfLayoutConstrainedField => {
561+ "borrow of layout constrained field with interior mutability"
562+ }
563+ CallToFunctionWith ( ..) => "call to function with `#[target_feature]`" ,
564+ }
565+ }
566+
567+ pub fn description_and_note ( & self , tcx : TyCtxt < ' _ > ) -> ( Cow < ' static , str > , & ' static str ) {
568+ match self {
569+ CallToUnsafeFunction ( did) => (
570+ if let Some ( did) = did {
571+ Cow :: from ( format ! ( "call to unsafe function `{}`" , tcx. def_path_str( * did) ) )
572+ } else {
573+ Cow :: Borrowed ( self . simple_description ( ) )
574+ } ,
546575 "consult the function's documentation for information on how to avoid undefined \
547576 behavior",
548577 ) ,
549578 UseOfInlineAssembly => (
550- "use of inline assembly" ,
579+ Cow :: Borrowed ( self . simple_description ( ) ) ,
551580 "inline assembly is entirely unchecked and can cause undefined behavior" ,
552581 ) ,
553582 InitializingTypeWith => (
554- "initializing type with `rustc_layout_scalar_valid_range` attr" ,
583+ Cow :: Borrowed ( self . simple_description ( ) ) ,
555584 "initializing a layout restricted type's field with a value outside the valid \
556585 range is undefined behavior",
557586 ) ,
558587 UseOfMutableStatic => (
559- "use of mutable static" ,
588+ Cow :: Borrowed ( self . simple_description ( ) ) ,
560589 "mutable statics can be mutated by multiple threads: aliasing violations or data \
561590 races will cause undefined behavior",
562591 ) ,
563592 UseOfExternStatic => (
564- "use of extern static" ,
593+ Cow :: Borrowed ( self . simple_description ( ) ) ,
565594 "extern statics are not controlled by the Rust type system: invalid data, \
566595 aliasing violations or data races will cause undefined behavior",
567596 ) ,
568597 DerefOfRawPointer => (
569- "dereference of raw pointer" ,
598+ Cow :: Borrowed ( self . simple_description ( ) ) ,
570599 "raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
571600 and cause data races: all of these are undefined behavior",
572601 ) ,
573602 AssignToDroppingUnionField => (
574- "assignment to union field that might need dropping" ,
603+ Cow :: Borrowed ( self . simple_description ( ) ) ,
575604 "the previous content of the field will be dropped, which causes undefined \
576605 behavior if the field was not properly initialized",
577606 ) ,
578607 AccessToUnionField => (
579- "access to union field" ,
608+ Cow :: Borrowed ( self . simple_description ( ) ) ,
580609 "the field may not be properly initialized: using uninitialized data will cause \
581610 undefined behavior",
582611 ) ,
583612 MutationOfLayoutConstrainedField => (
584- "mutation of layout constrained field" ,
613+ Cow :: Borrowed ( self . simple_description ( ) ) ,
585614 "mutating layout constrained fields cannot statically be checked for valid values" ,
586615 ) ,
587616 BorrowOfLayoutConstrainedField => (
588- "borrow of layout constrained field with interior mutability" ,
617+ Cow :: Borrowed ( self . simple_description ( ) ) ,
589618 "references to fields of layout constrained fields lose the constraints. Coupled \
590619 with interior mutability, the field can be changed to invalid values",
591620 ) ,
592- CallToFunctionWith => (
593- "call to function with `#[target_feature]`" ,
621+ CallToFunctionWith ( did) => (
622+ Cow :: from ( format ! (
623+ "call to function `{}` with `#[target_feature]`" ,
624+ tcx. def_path_str( * did)
625+ ) ) ,
594626 "can only be called if the required target features are available" ,
595627 ) ,
596628 }
0 commit comments