@@ -85,7 +85,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
85
85
let func_ty = func. ty ( self . mir , self . tcx ) ;
86
86
let sig = func_ty. fn_sig ( self . tcx ) ;
87
87
if let hir:: Unsafety :: Unsafe = sig. unsafety ( ) {
88
- self . require_unsafe ( "call to unsafe function" )
88
+ self . require_unsafe ( "call to unsafe function" ,
89
+ "consult the function's documentation for information on how to avoid \
90
+ undefined behavior")
89
91
}
90
92
}
91
93
}
@@ -112,7 +114,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
112
114
}
113
115
114
116
StatementKind :: InlineAsm { .. } => {
115
- self . require_unsafe ( "use of inline assembly" )
117
+ self . require_unsafe ( "use of inline assembly" ,
118
+ "inline assembly is entirely unchecked and can cause undefined behavior" )
116
119
} ,
117
120
}
118
121
self . super_statement ( block, statement, location) ;
@@ -151,6 +154,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
151
154
self . register_violations ( & [ UnsafetyViolation {
152
155
source_info,
153
156
description : Symbol :: intern ( "borrow of packed field" ) . as_interned_str ( ) ,
157
+ details :
158
+ Symbol :: intern ( "fields of packed structs might be misaligned: \
159
+ dereferencing a misaligned pointer or even just creating a \
160
+ misaligned reference is undefined behavior")
161
+ . as_interned_str ( ) ,
154
162
kind : UnsafetyViolationKind :: BorrowPacked ( lint_root)
155
163
} ] , & [ ] ) ;
156
164
}
@@ -172,7 +180,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
172
180
let base_ty = base. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
173
181
match base_ty. sty {
174
182
ty:: TyRawPtr ( ..) => {
175
- self . require_unsafe ( "dereference of raw pointer" )
183
+ self . require_unsafe ( "dereference of raw pointer" ,
184
+ "raw pointers may be NULL, dangling or unaligned; they can violate \
185
+ aliasing rules and cause data races: all of these are undefined \
186
+ behavior")
176
187
}
177
188
ty:: TyAdt ( adt, _) => {
178
189
if adt. is_union ( ) {
@@ -190,12 +201,17 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
190
201
if elem_ty. moves_by_default ( self . tcx , self . param_env ,
191
202
self . source_info . span ) {
192
203
self . require_unsafe (
193
- "assignment to non-`Copy` union field" )
204
+ "assignment to non-`Copy` union field" ,
205
+ "the previous content of the field may be dropped, which \
206
+ cause undefined behavior if the field was not properly \
207
+ initialized")
194
208
} else {
195
209
// write to non-move union, safe
196
210
}
197
211
} else {
198
- self . require_unsafe ( "access to union field" )
212
+ self . require_unsafe ( "access to union field" ,
213
+ "the field may not be properly initialized: using \
214
+ uninitialized data will cause undefined behavior")
199
215
}
200
216
}
201
217
}
@@ -208,14 +224,21 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
208
224
}
209
225
& Place :: Static ( box Static { def_id, ty : _ } ) => {
210
226
if self . tcx . is_static ( def_id) == Some ( hir:: Mutability :: MutMutable ) {
211
- self . require_unsafe ( "use of mutable static" ) ;
227
+ self . require_unsafe ( "use of mutable static" ,
228
+ "mutable statics can be mutated by multiple threads: aliasing violations \
229
+ or data races will cause undefined behavior") ;
212
230
} else if self . tcx . is_foreign_item ( def_id) {
213
231
let source_info = self . source_info ;
214
232
let lint_root =
215
233
self . source_scope_local_data [ source_info. scope ] . lint_root ;
216
234
self . register_violations ( & [ UnsafetyViolation {
217
235
source_info,
218
236
description : Symbol :: intern ( "use of extern static" ) . as_interned_str ( ) ,
237
+ details :
238
+ Symbol :: intern ( "extern statics are not controlled by the Rust type \
239
+ system: invalid data, aliasing violations or data \
240
+ races will cause undefined behavior")
241
+ . as_interned_str ( ) ,
219
242
kind : UnsafetyViolationKind :: ExternStatic ( lint_root)
220
243
} ] , & [ ] ) ;
221
244
}
@@ -227,12 +250,14 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
227
250
228
251
impl < ' a , ' tcx > UnsafetyChecker < ' a , ' tcx > {
229
252
fn require_unsafe ( & mut self ,
230
- description : & ' static str )
253
+ description : & ' static str ,
254
+ details : & ' static str )
231
255
{
232
256
let source_info = self . source_info ;
233
257
self . register_violations ( & [ UnsafetyViolation {
234
258
source_info,
235
259
description : Symbol :: intern ( description) . as_interned_str ( ) ,
260
+ details : Symbol :: intern ( details) . as_interned_str ( ) ,
236
261
kind : UnsafetyViolationKind :: General ,
237
262
} ] , & [ ] ) ;
238
263
}
@@ -437,33 +462,36 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
437
462
} = tcx. unsafety_check_result ( def_id) ;
438
463
439
464
for & UnsafetyViolation {
440
- source_info, description, kind
465
+ source_info, description, details , kind
441
466
} in violations. iter ( ) {
442
467
// Report an error.
443
468
match kind {
444
469
UnsafetyViolationKind :: General => {
445
470
struct_span_err ! (
446
471
tcx. sess, source_info. span, E0133 ,
447
- "{} requires unsafe function or block" , description)
472
+ "{} is unsafe and requires unsafe function or block" , description)
448
473
. span_label ( source_info. span , & description. as_str ( ) [ ..] )
474
+ . note ( & details. as_str ( ) [ ..] )
449
475
. emit ( ) ;
450
476
}
451
477
UnsafetyViolationKind :: ExternStatic ( lint_node_id) => {
452
- tcx. lint_node ( SAFE_EXTERN_STATICS ,
478
+ tcx. lint_node_note ( SAFE_EXTERN_STATICS ,
453
479
lint_node_id,
454
480
source_info. span ,
455
- & format ! ( "{} requires unsafe function or \
456
- block (error E0133)", & description. as_str( ) [ ..] ) ) ;
481
+ & format ! ( "{} is unsafe and requires unsafe function or block \
482
+ (error E0133)", & description. as_str( ) [ ..] ) ,
483
+ & details. as_str ( ) [ ..] ) ;
457
484
}
458
485
UnsafetyViolationKind :: BorrowPacked ( lint_node_id) => {
459
486
if let Some ( impl_def_id) = builtin_derive_def_id ( tcx, def_id) {
460
487
tcx. unsafe_derive_on_repr_packed ( impl_def_id) ;
461
488
} else {
462
- tcx. lint_node ( SAFE_PACKED_BORROWS ,
489
+ tcx. lint_node_note ( SAFE_PACKED_BORROWS ,
463
490
lint_node_id,
464
491
source_info. span ,
465
- & format ! ( "{} requires unsafe function or \
466
- block (error E0133)", & description. as_str( ) [ ..] ) ) ;
492
+ & format ! ( "{} is unsafe and requires unsafe function or block \
493
+ (error E0133)", & description. as_str( ) [ ..] ) ,
494
+ & details. as_str ( ) [ ..] ) ;
467
495
}
468
496
}
469
497
}
0 commit comments