@@ -12,6 +12,7 @@ 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 ;
15
16
use std:: ops:: Bound ;
16
17
17
18
struct UnsafetyVisitor < ' a , ' tcx > {
@@ -70,7 +71,6 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
70
71
}
71
72
72
73
fn requires_unsafe ( & mut self , span : Span , kind : UnsafeOpKind ) {
73
- let ( description, note) = kind. description_and_note ( ) ;
74
74
let unsafe_op_in_unsafe_fn_allowed = self . unsafe_op_in_unsafe_fn_allowed ( ) ;
75
75
match self . safety_context {
76
76
SafetyContext :: BuiltinUnsafeBlock => { }
@@ -82,6 +82,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
82
82
}
83
83
SafetyContext :: UnsafeFn if unsafe_op_in_unsafe_fn_allowed => { }
84
84
SafetyContext :: UnsafeFn => {
85
+ let ( description, note) = kind. description_and_note ( self . tcx ) ;
85
86
// unsafe_op_in_unsafe_fn is disallowed
86
87
self . tcx . struct_span_lint_hir (
87
88
UNSAFE_OP_IN_UNSAFE_FN ,
@@ -92,13 +93,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
92
93
"{} is unsafe and requires unsafe block (error E0133)" ,
93
94
description,
94
95
) )
95
- . span_label ( span, description )
96
+ . span_label ( span, kind . simple_description ( ) )
96
97
. note ( note)
97
98
. emit ( ) ;
98
99
} ,
99
100
)
100
101
}
101
102
SafetyContext :: Safe => {
103
+ let ( description, note) = kind. description_and_note ( self . tcx ) ;
102
104
let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" } ;
103
105
struct_span_err ! (
104
106
self . tcx. sess,
@@ -108,7 +110,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
108
110
description,
109
111
fn_sugg,
110
112
)
111
- . span_label ( span, description )
113
+ . span_label ( span, kind . simple_description ( ) )
112
114
. note ( note)
113
115
. emit ( ) ;
114
116
}
@@ -350,7 +352,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
350
352
}
351
353
ExprKind :: Call { fun, ty : _, args : _, from_hir_call : _, fn_span : _ } => {
352
354
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) ) ;
354
361
} else if let & ty:: FnDef ( func_did, _) = self . thir [ fun] . ty . kind ( ) {
355
362
// If the called function has target features the calling function hasn't,
356
363
// the call requires `unsafe`. Don't check this on wasm
@@ -364,7 +371,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
364
371
. iter ( )
365
372
. all ( |feature| self . body_target_features . contains ( feature) )
366
373
{
367
- self . requires_unsafe ( expr. span , CallToFunctionWith ) ;
374
+ self . requires_unsafe ( expr. span , CallToFunctionWith ( func_did ) ) ;
368
375
}
369
376
}
370
377
}
@@ -523,7 +530,7 @@ impl BodyUnsafety {
523
530
524
531
#[ derive( Clone , Copy , PartialEq ) ]
525
532
enum UnsafeOpKind {
526
- CallToUnsafeFunction ,
533
+ CallToUnsafeFunction ( Option < DefId > ) ,
527
534
UseOfInlineAssembly ,
528
535
InitializingTypeWith ,
529
536
UseOfMutableStatic ,
@@ -533,64 +540,89 @@ enum UnsafeOpKind {
533
540
AccessToUnionField ,
534
541
MutationOfLayoutConstrainedField ,
535
542
BorrowOfLayoutConstrainedField ,
536
- CallToFunctionWith ,
543
+ CallToFunctionWith ( DefId ) ,
537
544
}
538
545
539
546
use UnsafeOpKind :: * ;
540
547
541
548
impl UnsafeOpKind {
542
- pub fn description_and_note ( & self ) -> ( & ' static str , & ' static str ) {
549
+ pub fn simple_description ( & self ) -> & ' static str {
543
550
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
+ } ,
546
575
"consult the function's documentation for information on how to avoid undefined \
547
576
behavior",
548
577
) ,
549
578
UseOfInlineAssembly => (
550
- "use of inline assembly" ,
579
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
551
580
"inline assembly is entirely unchecked and can cause undefined behavior" ,
552
581
) ,
553
582
InitializingTypeWith => (
554
- "initializing type with `rustc_layout_scalar_valid_range` attr" ,
583
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
555
584
"initializing a layout restricted type's field with a value outside the valid \
556
585
range is undefined behavior",
557
586
) ,
558
587
UseOfMutableStatic => (
559
- "use of mutable static" ,
588
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
560
589
"mutable statics can be mutated by multiple threads: aliasing violations or data \
561
590
races will cause undefined behavior",
562
591
) ,
563
592
UseOfExternStatic => (
564
- "use of extern static" ,
593
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
565
594
"extern statics are not controlled by the Rust type system: invalid data, \
566
595
aliasing violations or data races will cause undefined behavior",
567
596
) ,
568
597
DerefOfRawPointer => (
569
- "dereference of raw pointer" ,
598
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
570
599
"raw pointers may be null, dangling or unaligned; they can violate aliasing rules \
571
600
and cause data races: all of these are undefined behavior",
572
601
) ,
573
602
AssignToDroppingUnionField => (
574
- "assignment to union field that might need dropping" ,
603
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
575
604
"the previous content of the field will be dropped, which causes undefined \
576
605
behavior if the field was not properly initialized",
577
606
) ,
578
607
AccessToUnionField => (
579
- "access to union field" ,
608
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
580
609
"the field may not be properly initialized: using uninitialized data will cause \
581
610
undefined behavior",
582
611
) ,
583
612
MutationOfLayoutConstrainedField => (
584
- "mutation of layout constrained field" ,
613
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
585
614
"mutating layout constrained fields cannot statically be checked for valid values" ,
586
615
) ,
587
616
BorrowOfLayoutConstrainedField => (
588
- "borrow of layout constrained field with interior mutability" ,
617
+ Cow :: Borrowed ( self . simple_description ( ) ) ,
589
618
"references to fields of layout constrained fields lose the constraints. Coupled \
590
619
with interior mutability, the field can be changed to invalid values",
591
620
) ,
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
+ ) ) ,
594
626
"can only be called if the required target features are available" ,
595
627
) ,
596
628
}
0 commit comments