@@ -5,10 +5,10 @@ use crate::dataflow::{Analysis, ResultsCursor};
5
5
use crate :: util:: storage:: AlwaysLiveLocals ;
6
6
7
7
use 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 } ;
12
12
use rustc_middle:: mir:: {
13
13
AggregateKind , BasicBlock , Body , BorrowKind , Local , Location , MirPhase , Operand , PlaceRef ,
14
14
Rvalue , SourceScope , Statement , StatementKind , Terminator , TerminatorKind , VarDebugInfo ,
@@ -52,6 +52,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
52
52
tcx,
53
53
param_env,
54
54
mir_phase,
55
+ reachable_blocks : traversal:: reachable_as_bitset ( body) ,
55
56
storage_liveness,
56
57
place_cache : Vec :: new ( ) ,
57
58
}
@@ -157,6 +158,7 @@ struct TypeChecker<'a, 'tcx> {
157
158
tcx : TyCtxt < ' tcx > ,
158
159
param_env : ParamEnv < ' tcx > ,
159
160
mir_phase : MirPhase ,
161
+ reachable_blocks : BitSet < BasicBlock > ,
160
162
storage_liveness : ResultsCursor < ' a , ' tcx , MaybeStorageLive > ,
161
163
place_cache : Vec < PlaceRef < ' tcx > > ,
162
164
}
@@ -232,7 +234,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
232
234
233
235
impl < ' a , ' tcx > Visitor < ' tcx > for TypeChecker < ' a , ' tcx > {
234
236
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 ( ) {
236
238
// Uses of locals must occur while the local's storage is allocated.
237
239
self . storage_liveness . seek_after_primary_effect ( location) ;
238
240
let locals_with_storage = self . storage_liveness . get ( ) ;
@@ -249,13 +251,16 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
249
251
}
250
252
251
253
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
+ }
259
264
}
260
265
}
261
266
@@ -341,6 +346,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
341
346
}
342
347
_ => { }
343
348
}
349
+
350
+ self . super_statement ( statement, location) ;
344
351
}
345
352
346
353
fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
@@ -489,6 +496,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
489
496
| TerminatorKind :: Unreachable
490
497
| TerminatorKind :: GeneratorDrop => { }
491
498
}
499
+
500
+ self . super_terminator ( terminator, location) ;
492
501
}
493
502
494
503
fn visit_source_scope ( & mut self , scope : & SourceScope ) {
0 commit comments