@@ -20,6 +20,8 @@ use rustc_mir_dataflow::{Analysis, ResultsCursor};
2020use rustc_target:: abi:: { Size , FIRST_VARIANT } ;
2121use rustc_target:: spec:: abi:: Abi ;
2222
23+ use crate :: util:: is_within_packed;
24+
2325#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
2426enum EdgeKind {
2527 Unwind ,
@@ -93,6 +95,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
9395 cfg_checker. visit_body ( body) ;
9496 cfg_checker. check_cleanup_control_flow ( ) ;
9597
98+ // Also run the TypeChecker.
9699 for ( location, msg) in validate_types ( tcx, self . mir_phase , param_env, body) {
97100 cfg_checker. fail ( location, msg) ;
98101 }
@@ -427,22 +430,42 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
427430 self . check_unwind_edge ( location, * unwind) ;
428431
429432 // The call destination place and Operand::Move place used as an argument might be
430- // passed by a reference to the callee. Consequently they must be non-overlapping.
431- // Currently this simply checks for duplicate places.
433+ // passed by a reference to the callee. Consequently they must be non-overlapping
434+ // and cannot be packed. Currently this simply checks for duplicate places.
432435 self . place_cache . clear ( ) ;
433436 self . place_cache . insert ( destination. as_ref ( ) ) ;
437+ if is_within_packed ( self . tcx , & self . body . local_decls , * destination) . is_some ( ) {
438+ // This is bad! The callee will expect the memory to be aligned.
439+ self . fail (
440+ location,
441+ format ! (
442+ "encountered packed place in `Call` terminator destination: {:?}" ,
443+ terminator. kind,
444+ ) ,
445+ ) ;
446+ }
434447 let mut has_duplicates = false ;
435448 for arg in args {
436449 if let Operand :: Move ( place) = arg {
437450 has_duplicates |= !self . place_cache . insert ( place. as_ref ( ) ) ;
451+ if is_within_packed ( self . tcx , & self . body . local_decls , * place) . is_some ( ) {
452+ // This is bad! The callee will expect the memory to be aligned.
453+ self . fail (
454+ location,
455+ format ! (
456+ "encountered `Move` of a packed place in `Call` terminator: {:?}" ,
457+ terminator. kind,
458+ ) ,
459+ ) ;
460+ }
438461 }
439462 }
440463
441464 if has_duplicates {
442465 self . fail (
443466 location,
444467 format ! (
445- "encountered overlapping memory in `Call` terminator: {:?}" ,
468+ "encountered overlapping memory in `Move` arguments to ` Call` terminator: {:?}" ,
446469 terminator. kind,
447470 ) ,
448471 ) ;
@@ -541,6 +564,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
541564 }
542565}
543566
567+ /// A faster version of the validation pass that only checks those things which may break when apply
568+ /// generic substitutions.
544569pub fn validate_types < ' tcx > (
545570 tcx : TyCtxt < ' tcx > ,
546571 mir_phase : MirPhase ,
0 commit comments