@@ -357,21 +357,15 @@ impl<'tcx> Body<'tcx> {
357
357
//
358
358
// FIXME: Use a finer-grained API for this, so only transformations that alter terminators
359
359
// invalidate the caches.
360
- self . predecessor_cache . invalidate ( ) ;
361
- self . switch_source_cache . invalidate ( ) ;
362
- self . is_cyclic . invalidate ( ) ;
363
- self . postorder_cache . invalidate ( ) ;
360
+ self . invalidate_cfg_cache ( ) ;
364
361
& mut self . basic_blocks
365
362
}
366
363
367
364
#[ inline]
368
365
pub fn basic_blocks_and_local_decls_mut (
369
366
& mut self ,
370
367
) -> ( & mut IndexVec < BasicBlock , BasicBlockData < ' tcx > > , & mut LocalDecls < ' tcx > ) {
371
- self . predecessor_cache . invalidate ( ) ;
372
- self . switch_source_cache . invalidate ( ) ;
373
- self . is_cyclic . invalidate ( ) ;
374
- self . postorder_cache . invalidate ( ) ;
368
+ self . invalidate_cfg_cache ( ) ;
375
369
( & mut self . basic_blocks , & mut self . local_decls )
376
370
}
377
371
@@ -383,11 +377,43 @@ impl<'tcx> Body<'tcx> {
383
377
& mut LocalDecls < ' tcx > ,
384
378
& mut Vec < VarDebugInfo < ' tcx > > ,
385
379
) {
380
+ self . invalidate_cfg_cache ( ) ;
381
+ ( & mut self . basic_blocks , & mut self . local_decls , & mut self . var_debug_info )
382
+ }
383
+
384
+ /// Get mutable access to parts of the Body without invalidating the CFG cache.
385
+ ///
386
+ /// By calling this method instead of eg [`Body::basic_blocks_mut`], you promise not to change
387
+ /// the CFG. This means that
388
+ ///
389
+ /// 1) The number of basic blocks remains unchanged
390
+ /// 2) The set of successors of each terminator remains unchanged.
391
+ /// 3) For each `TerminatorKind::SwitchInt`, the `targets` remains the same and the terminator
392
+ /// kind is not changed.
393
+ ///
394
+ /// If any of these conditions cannot be upheld, you should call [`Body::invalidate_cfg_cache`].
395
+ #[ inline]
396
+ pub fn basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate (
397
+ & mut self ,
398
+ ) -> (
399
+ & mut IndexVec < BasicBlock , BasicBlockData < ' tcx > > ,
400
+ & mut LocalDecls < ' tcx > ,
401
+ & mut Vec < VarDebugInfo < ' tcx > > ,
402
+ ) {
403
+ ( & mut self . basic_blocks , & mut self . local_decls , & mut self . var_debug_info )
404
+ }
405
+
406
+ /// Invalidates cached information about the CFG.
407
+ ///
408
+ /// You will only ever need this if you have also called
409
+ /// [`Body::basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate`]. All other methods
410
+ /// that allow you to mutate the body also call this method themselves, thereby avoiding any
411
+ /// risk of accidentaly cache invalidation.
412
+ pub fn invalidate_cfg_cache ( & mut self ) {
386
413
self . predecessor_cache . invalidate ( ) ;
387
414
self . switch_source_cache . invalidate ( ) ;
388
415
self . is_cyclic . invalidate ( ) ;
389
416
self . postorder_cache . invalidate ( ) ;
390
- ( & mut self . basic_blocks , & mut self . local_decls , & mut self . var_debug_info )
391
417
}
392
418
393
419
/// Returns `true` if a cycle exists in the control-flow graph that is reachable from the
0 commit comments