@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashSet;
22use rustc_errors:: struct_span_err;
33use rustc_hir as hir;
44use rustc_hir:: def_id:: { DefId , LocalDefId } ;
5+ use rustc_hir:: hir_id:: HirId ;
56use rustc_hir:: intravisit;
67use rustc_hir:: Node ;
78use rustc_middle:: mir:: visit:: { MutatingUseContext , PlaceContext , Visitor } ;
@@ -10,6 +11,7 @@ use rustc_middle::ty::cast::CastTy;
1011use rustc_middle:: ty:: query:: Providers ;
1112use rustc_middle:: ty:: { self , TyCtxt } ;
1213use rustc_session:: lint:: builtin:: { SAFE_PACKED_BORROWS , UNSAFE_OP_IN_UNSAFE_FN , UNUSED_UNSAFE } ;
14+ use rustc_session:: lint:: Level ;
1315use rustc_span:: symbol:: { sym, Symbol } ;
1416
1517use std:: ops:: Bound ;
@@ -220,7 +222,18 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
220222
221223 for ( i, elem) in place. projection . iter ( ) . enumerate ( ) {
222224 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 ;
224237 if let [ ] = proj_base {
225238 let decl = & self . body . local_decls [ place. local ] ;
226239 if decl. internal {
@@ -301,7 +314,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
301314 }
302315 _ => { }
303316 }
304- self . source_info = old_source_info ;
317+ self . source_info = source_info ;
305318 }
306319 }
307320}
@@ -314,9 +327,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
314327 kind : UnsafetyViolationKind ,
315328 ) {
316329 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 ;
317335 self . register_violations (
318336 & [ UnsafetyViolation {
319337 source_info,
338+ lint_root,
320339 description : Symbol :: intern ( description) ,
321340 details : Symbol :: intern ( details) ,
322341 kind,
@@ -343,15 +362,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
343362 match violation. kind {
344363 UnsafetyViolationKind :: GeneralAndConstFn
345364 | UnsafetyViolationKind :: General => { }
346- UnsafetyViolationKind :: BorrowPacked ( _ ) => {
365+ UnsafetyViolationKind :: BorrowPacked => {
347366 if self . min_const_fn {
348367 // const fns don't need to be backwards compatible and can
349368 // emit these violations as a hard error instead of a backwards
350369 // compat lint
351370 violation. kind = UnsafetyViolationKind :: General ;
352371 }
353372 }
354- UnsafetyViolationKind :: UnsafeFn ( _ ) => {
373+ UnsafetyViolationKind :: UnsafeFn => {
355374 bug ! ( "`UnsafetyViolationKind::UnsafeFn` in an `Safe` context" )
356375 }
357376 }
@@ -365,14 +384,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
365384 Safety :: FnUnsafe if self . tcx . features ( ) . unsafe_block_in_unsafe_fn => {
366385 for violation in violations {
367386 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 ;
373387
374388 // FIXME(LeSeulArtichaut): what to do with `UnsafetyViolationKind::BorrowPacked`?
375- violation. kind = UnsafetyViolationKind :: UnsafeFn ( lint_root ) ;
389+ violation. kind = UnsafetyViolationKind :: UnsafeFn ;
376390 if !self . violations . contains ( & violation) {
377391 self . violations . push ( violation)
378392 }
@@ -394,7 +408,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
394408 UnsafetyViolationKind :: GeneralAndConstFn => { }
395409 // these things are forbidden in const fns
396410 UnsafetyViolationKind :: General
397- | UnsafetyViolationKind :: BorrowPacked ( _ ) => {
411+ | UnsafetyViolationKind :: BorrowPacked => {
398412 let mut violation = * violation;
399413 // const fns don't need to be backwards compatible and can
400414 // emit these violations as a hard error instead of a backwards
@@ -404,7 +418,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
404418 self . violations . push ( violation)
405419 }
406420 }
407- UnsafetyViolationKind :: UnsafeFn ( _ ) => bug ! (
421+ UnsafetyViolationKind :: UnsafeFn => bug ! (
408422 "`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context"
409423 ) ,
410424 }
@@ -657,47 +671,50 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
657671 let UnsafetyCheckResult { violations, unsafe_blocks } =
658672 tcx. unsafety_check_result ( def_id. expect_local ( ) ) ;
659673
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+ {
663677 // Report an error.
678+ let unsafe_fn_msg =
679+ if unsafe_op_in_unsafe_fn_allowed ( tcx, lint_root) { "" } else { " function or" } ;
680+
664681 match kind {
665682 UnsafetyViolationKind :: GeneralAndConstFn | UnsafetyViolationKind :: General => {
666683 // once
667684 struct_span_err ! (
668685 tcx. sess,
669686 source_info. span,
670687 E0133 ,
671- "{} is unsafe and requires unsafe function{} " ,
688+ "{} is unsafe and requires unsafe{} block " ,
672689 description,
673- or_block_msg ,
690+ unsafe_fn_msg ,
674691 )
675692 . span_label ( source_info. span , & * description. as_str ( ) )
676693 . note ( & details. as_str ( ) )
677694 . emit ( ) ;
678695 }
679- UnsafetyViolationKind :: BorrowPacked ( lint_hir_id ) => {
696+ UnsafetyViolationKind :: BorrowPacked => {
680697 if let Some ( impl_def_id) = builtin_derive_def_id ( tcx, def_id) {
681698 tcx. ensure ( ) . unsafe_derive_on_repr_packed ( impl_def_id) ;
682699 } else {
683700 tcx. struct_span_lint_hir (
684701 SAFE_PACKED_BORROWS ,
685- lint_hir_id ,
702+ lint_root ,
686703 source_info. span ,
687704 |lint| {
688705 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 ,
691708 ) )
692709 . note ( & details. as_str ( ) )
693710 . emit ( )
694711 } ,
695712 )
696713 }
697714 }
698- UnsafetyViolationKind :: UnsafeFn ( lint_hir_id ) => tcx. struct_span_lint_hir (
715+ UnsafetyViolationKind :: UnsafeFn => tcx. struct_span_lint_hir (
699716 UNSAFE_OP_IN_UNSAFE_FN ,
700- lint_hir_id ,
717+ lint_root ,
701718 source_info. span ,
702719 |lint| {
703720 lint. build ( & format ! (
@@ -728,3 +745,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
728745 report_unused_unsafe ( tcx, & unsafe_used, block_id) ;
729746 }
730747}
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