@@ -5,10 +5,10 @@ use crate::dataflow::{Analysis, ResultsCursor};
55use crate :: util:: storage:: AlwaysLiveLocals ;
66
77use super :: MirPass ;
8- use rustc_middle :: mir :: {
9- interpret:: Scalar ,
10- visit :: { PlaceContext , Visitor } ,
11- } ;
8+ use rustc_index :: bit_set :: BitSet ;
9+ use rustc_middle :: mir :: interpret:: Scalar ;
10+ use rustc_middle :: mir :: traversal ;
11+ use rustc_middle :: mir :: visit :: { PlaceContext , Visitor } ;
1212use rustc_middle:: mir:: {
1313 AggregateKind , BasicBlock , Body , BorrowKind , Local , Location , MirPhase , Operand , PlaceRef ,
1414 Rvalue , SourceScope , Statement , StatementKind , Terminator , TerminatorKind , VarDebugInfo ,
@@ -52,6 +52,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
5252 tcx,
5353 param_env,
5454 mir_phase,
55+ reachable_blocks : traversal:: reachable_as_bitset ( body) ,
5556 storage_liveness,
5657 place_cache : Vec :: new ( ) ,
5758 }
@@ -157,6 +158,7 @@ struct TypeChecker<'a, 'tcx> {
157158 tcx : TyCtxt < ' tcx > ,
158159 param_env : ParamEnv < ' tcx > ,
159160 mir_phase : MirPhase ,
161+ reachable_blocks : BitSet < BasicBlock > ,
160162 storage_liveness : ResultsCursor < ' a , ' tcx , MaybeStorageLive > ,
161163 place_cache : Vec < PlaceRef < ' tcx > > ,
162164}
@@ -232,7 +234,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
232234
233235impl < ' a , ' tcx > Visitor < ' tcx > for TypeChecker < ' a , ' tcx > {
234236 fn visit_local ( & mut self , local : & Local , context : PlaceContext , location : Location ) {
235- if context. is_use ( ) {
237+ if self . reachable_blocks . contains ( location . block ) && context. is_use ( ) {
236238 // Uses of locals must occur while the local's storage is allocated.
237239 self . storage_liveness . seek_after_primary_effect ( location) ;
238240 let locals_with_storage = self . storage_liveness . get ( ) ;
@@ -249,13 +251,16 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
249251 }
250252
251253 fn visit_operand ( & mut self , operand : & Operand < ' tcx > , location : Location ) {
252- // `Operand::Copy` is only supposed to be used with `Copy` types.
253- if let Operand :: Copy ( place) = operand {
254- let ty = place. ty ( & self . body . local_decls , self . tcx ) . ty ;
255- let span = self . body . source_info ( location) . span ;
256-
257- if !ty. is_copy_modulo_regions ( self . tcx . at ( span) , self . param_env ) {
258- self . fail ( location, format ! ( "`Operand::Copy` with non-`Copy` type {}" , ty) ) ;
254+ // This check is somewhat expensive, so only run it when -Zvalidate-mir is passed.
255+ if self . tcx . sess . opts . debugging_opts . validate_mir {
256+ // `Operand::Copy` is only supposed to be used with `Copy` types.
257+ if let Operand :: Copy ( place) = operand {
258+ let ty = place. ty ( & self . body . local_decls , self . tcx ) . ty ;
259+ let span = self . body . source_info ( location) . span ;
260+
261+ if !ty. is_copy_modulo_regions ( self . tcx . at ( span) , self . param_env ) {
262+ self . fail ( location, format ! ( "`Operand::Copy` with non-`Copy` type {}" , ty) ) ;
263+ }
259264 }
260265 }
261266
@@ -341,6 +346,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
341346 }
342347 _ => { }
343348 }
349+
350+ self . super_statement ( statement, location) ;
344351 }
345352
346353 fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
@@ -489,6 +496,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
489496 | TerminatorKind :: Unreachable
490497 | TerminatorKind :: GeneratorDrop => { }
491498 }
499+
500+ self . super_terminator ( terminator, location) ;
492501 }
493502
494503 fn visit_source_scope ( & mut self , scope : & SourceScope ) {
0 commit comments