@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashSet;
2
2
use rustc_errors:: struct_span_err;
3
3
use rustc_hir as hir;
4
4
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
5
+ use rustc_hir:: hir_id:: HirId ;
5
6
use rustc_hir:: intravisit;
6
7
use rustc_hir:: Node ;
7
8
use rustc_middle:: mir:: visit:: { MutatingUseContext , PlaceContext , Visitor } ;
@@ -10,6 +11,7 @@ use rustc_middle::ty::cast::CastTy;
10
11
use rustc_middle:: ty:: query:: Providers ;
11
12
use rustc_middle:: ty:: { self , TyCtxt } ;
12
13
use rustc_session:: lint:: builtin:: { SAFE_PACKED_BORROWS , UNSAFE_OP_IN_UNSAFE_FN , UNUSED_UNSAFE } ;
14
+ use rustc_session:: lint:: Level ;
13
15
use rustc_span:: symbol:: { sym, Symbol } ;
14
16
15
17
use std:: ops:: Bound ;
@@ -220,7 +222,18 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
220
222
221
223
for ( i, elem) in place. projection . iter ( ) . enumerate ( ) {
222
224
let proj_base = & place. projection [ ..i] ;
223
- let old_source_info = self . source_info ;
225
+ if context. is_borrow ( ) {
226
+ if util:: is_disaligned ( self . tcx , self . body , self . param_env , * place) {
227
+ self . require_unsafe (
228
+ "borrow of packed field" ,
229
+ "fields of packed structs might be misaligned: dereferencing a \
230
+ misaligned pointer or even just creating a misaligned reference \
231
+ is undefined behavior",
232
+ UnsafetyViolationKind :: BorrowPacked ,
233
+ ) ;
234
+ }
235
+ }
236
+ let source_info = self . source_info ;
224
237
if let [ ] = proj_base {
225
238
let decl = & self . body . local_decls [ place. local ] ;
226
239
if decl. internal {
@@ -301,7 +314,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
301
314
}
302
315
_ => { }
303
316
}
304
- self . source_info = old_source_info ;
317
+ self . source_info = source_info ;
305
318
}
306
319
}
307
320
}
@@ -314,9 +327,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
314
327
kind : UnsafetyViolationKind ,
315
328
) {
316
329
let source_info = self . source_info ;
330
+ let lint_root = self . body . source_scopes [ self . source_info . scope ]
331
+ . local_data
332
+ . as_ref ( )
333
+ . assert_crate_local ( )
334
+ . lint_root ;
317
335
self . register_violations (
318
336
& [ UnsafetyViolation {
319
337
source_info,
338
+ lint_root,
320
339
description : Symbol :: intern ( description) ,
321
340
details : Symbol :: intern ( details) ,
322
341
kind,
@@ -343,15 +362,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
343
362
match violation. kind {
344
363
UnsafetyViolationKind :: GeneralAndConstFn
345
364
| UnsafetyViolationKind :: General => { }
346
- UnsafetyViolationKind :: BorrowPacked ( _ ) => {
365
+ UnsafetyViolationKind :: BorrowPacked => {
347
366
if self . min_const_fn {
348
367
// const fns don't need to be backwards compatible and can
349
368
// emit these violations as a hard error instead of a backwards
350
369
// compat lint
351
370
violation. kind = UnsafetyViolationKind :: General ;
352
371
}
353
372
}
354
- UnsafetyViolationKind :: UnsafeFn ( _ ) => {
373
+ UnsafetyViolationKind :: UnsafeFn => {
355
374
bug ! ( "`UnsafetyViolationKind::UnsafeFn` in an `Safe` context" )
356
375
}
357
376
}
@@ -365,14 +384,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
365
384
Safety :: FnUnsafe if self . tcx . features ( ) . unsafe_block_in_unsafe_fn => {
366
385
for violation in violations {
367
386
let mut violation = * violation;
368
- let lint_root = self . body . source_scopes [ self . source_info . scope ]
369
- . local_data
370
- . as_ref ( )
371
- . assert_crate_local ( )
372
- . lint_root ;
373
387
374
388
// FIXME(LeSeulArtichaut): what to do with `UnsafetyViolationKind::BorrowPacked`?
375
- violation. kind = UnsafetyViolationKind :: UnsafeFn ( lint_root ) ;
389
+ violation. kind = UnsafetyViolationKind :: UnsafeFn ;
376
390
if !self . violations . contains ( & violation) {
377
391
self . violations . push ( violation)
378
392
}
@@ -394,7 +408,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
394
408
UnsafetyViolationKind :: GeneralAndConstFn => { }
395
409
// these things are forbidden in const fns
396
410
UnsafetyViolationKind :: General
397
- | UnsafetyViolationKind :: BorrowPacked ( _ ) => {
411
+ | UnsafetyViolationKind :: BorrowPacked => {
398
412
let mut violation = * violation;
399
413
// const fns don't need to be backwards compatible and can
400
414
// emit these violations as a hard error instead of a backwards
@@ -404,7 +418,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
404
418
self . violations . push ( violation)
405
419
}
406
420
}
407
- UnsafetyViolationKind :: UnsafeFn ( _ ) => bug ! (
421
+ UnsafetyViolationKind :: UnsafeFn => bug ! (
408
422
"`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context"
409
423
) ,
410
424
}
@@ -657,47 +671,50 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
657
671
let UnsafetyCheckResult { violations, unsafe_blocks } =
658
672
tcx. unsafety_check_result ( def_id. expect_local ( ) ) ;
659
673
660
- let or_block_msg = if tcx . features ( ) . unsafe_block_in_unsafe_fn { "" } else { " or block" } ;
661
-
662
- for & UnsafetyViolation { source_info , description , details , kind } in violations . iter ( ) {
674
+ for & UnsafetyViolation { source_info , lint_root , description , details , kind } in
675
+ violations . iter ( )
676
+ {
663
677
// Report an error.
678
+ let unsafe_fn_msg =
679
+ if unsafe_op_in_unsafe_fn_allowed ( tcx, lint_root) { "" } else { " function or" } ;
680
+
664
681
match kind {
665
682
UnsafetyViolationKind :: GeneralAndConstFn | UnsafetyViolationKind :: General => {
666
683
// once
667
684
struct_span_err ! (
668
685
tcx. sess,
669
686
source_info. span,
670
687
E0133 ,
671
- "{} is unsafe and requires unsafe function{} " ,
688
+ "{} is unsafe and requires unsafe{} block " ,
672
689
description,
673
- or_block_msg ,
690
+ unsafe_fn_msg ,
674
691
)
675
692
. span_label ( source_info. span , & * description. as_str ( ) )
676
693
. note ( & details. as_str ( ) )
677
694
. emit ( ) ;
678
695
}
679
- UnsafetyViolationKind :: BorrowPacked ( lint_hir_id ) => {
696
+ UnsafetyViolationKind :: BorrowPacked => {
680
697
if let Some ( impl_def_id) = builtin_derive_def_id ( tcx, def_id) {
681
698
tcx. ensure ( ) . unsafe_derive_on_repr_packed ( impl_def_id) ;
682
699
} else {
683
700
tcx. struct_span_lint_hir (
684
701
SAFE_PACKED_BORROWS ,
685
- lint_hir_id ,
702
+ lint_root ,
686
703
source_info. span ,
687
704
|lint| {
688
705
lint. build ( & format ! (
689
- "{} is unsafe and requires unsafe function{} (error E0133)" ,
690
- description, or_block_msg ,
706
+ "{} is unsafe and requires unsafe{} block (error E0133)" ,
707
+ description, unsafe_fn_msg ,
691
708
) )
692
709
. note ( & details. as_str ( ) )
693
710
. emit ( )
694
711
} ,
695
712
)
696
713
}
697
714
}
698
- UnsafetyViolationKind :: UnsafeFn ( lint_hir_id ) => tcx. struct_span_lint_hir (
715
+ UnsafetyViolationKind :: UnsafeFn => tcx. struct_span_lint_hir (
699
716
UNSAFE_OP_IN_UNSAFE_FN ,
700
- lint_hir_id ,
717
+ lint_root ,
701
718
source_info. span ,
702
719
|lint| {
703
720
lint. build ( & format ! (
@@ -728,3 +745,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
728
745
report_unused_unsafe ( tcx, & unsafe_used, block_id) ;
729
746
}
730
747
}
748
+
749
+ fn unsafe_op_in_unsafe_fn_allowed ( tcx : TyCtxt < ' _ > , id : HirId ) -> bool {
750
+ tcx. lint_level_at_node ( UNSAFE_OP_IN_UNSAFE_FN , id) . 0 == Level :: Allow
751
+ }
0 commit comments