@@ -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 }
@@ -418,22 +421,42 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
418421 self . check_unwind_edge ( location, * unwind) ;
419422
420423 // The call destination place and Operand::Move place used as an argument might be
421- // passed by a reference to the callee. Consequently they must be non-overlapping.
422- // Currently this simply checks for duplicate places.
424+ // passed by a reference to the callee. Consequently they must be non-overlapping
425+ // and cannot be packed. Currently this simply checks for duplicate places.
423426 self . place_cache . clear ( ) ;
424427 self . place_cache . insert ( destination. as_ref ( ) ) ;
428+ if is_within_packed ( self . tcx , & self . body . local_decls , * destination) . is_some ( ) {
429+ // This is bad! The callee will expect the memory to be aligned.
430+ self . fail (
431+ location,
432+ format ! (
433+ "encountered packed place in `Call` terminator destination: {:?}" ,
434+ terminator. kind,
435+ ) ,
436+ ) ;
437+ }
425438 let mut has_duplicates = false ;
426439 for arg in args {
427440 if let Operand :: Move ( place) = arg {
428441 has_duplicates |= !self . place_cache . insert ( place. as_ref ( ) ) ;
442+ if is_within_packed ( self . tcx , & self . body . local_decls , * place) . is_some ( ) {
443+ // This is bad! The callee will expect the memory to be aligned.
444+ self . fail (
445+ location,
446+ format ! (
447+ "encountered `Move` of a packed place in `Call` terminator: {:?}" ,
448+ terminator. kind,
449+ ) ,
450+ ) ;
451+ }
429452 }
430453 }
431454
432455 if has_duplicates {
433456 self . fail (
434457 location,
435458 format ! (
436- "encountered overlapping memory in `Call` terminator: {:?}" ,
459+ "encountered overlapping memory in `Move` arguments to ` Call` terminator: {:?}" ,
437460 terminator. kind,
438461 ) ,
439462 ) ;
@@ -532,6 +555,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
532555 }
533556}
534557
558+ /// A faster version of the validation pass that only checks those things which may break when apply
559+ /// generic substitutions.
535560pub fn validate_types < ' tcx > (
536561 tcx : TyCtxt < ' tcx > ,
537562 mir_phase : MirPhase ,
0 commit comments