about summary refs log tree commit diff
path: root/compiler/rustc_middle/src/mir/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/mir/mod.rs')
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs44
1 files changed, 35 insertions, 9 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index ad33a54e0a2..11d20b886c9 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -357,10 +357,7 @@ impl<'tcx> Body<'tcx> {
         //
         // FIXME: Use a finer-grained API for this, so only transformations that alter terminators
         // invalidate the caches.
-        self.predecessor_cache.invalidate();
-        self.switch_source_cache.invalidate();
-        self.is_cyclic.invalidate();
-        self.postorder_cache.invalidate();
+        self.invalidate_cfg_cache();
         &mut self.basic_blocks
     }
 
@@ -368,10 +365,7 @@ impl<'tcx> Body<'tcx> {
     pub fn basic_blocks_and_local_decls_mut(
         &mut self,
     ) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
-        self.predecessor_cache.invalidate();
-        self.switch_source_cache.invalidate();
-        self.is_cyclic.invalidate();
-        self.postorder_cache.invalidate();
+        self.invalidate_cfg_cache();
         (&mut self.basic_blocks, &mut self.local_decls)
     }
 
@@ -383,11 +377,43 @@ impl<'tcx> Body<'tcx> {
         &mut LocalDecls<'tcx>,
         &mut Vec<VarDebugInfo<'tcx>>,
     ) {
+        self.invalidate_cfg_cache();
+        (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
+    }
+
+    /// Get mutable access to parts of the Body without invalidating the CFG cache.
+    ///
+    /// By calling this method instead of eg [`Body::basic_blocks_mut`], you promise not to change
+    /// the CFG. This means that
+    ///
+    ///  1) The number of basic blocks remains unchanged
+    ///  2) The set of successors of each terminator remains unchanged.
+    ///  3) For each `TerminatorKind::SwitchInt`, the `targets` remains the same and the terminator
+    ///     kind is not changed.
+    ///
+    /// If any of these conditions cannot be upheld, you should call [`Body::invalidate_cfg_cache`].
+    #[inline]
+    pub fn basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(
+        &mut self,
+    ) -> (
+        &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
+        &mut LocalDecls<'tcx>,
+        &mut Vec<VarDebugInfo<'tcx>>,
+    ) {
+        (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
+    }
+
+    /// Invalidates cached information about the CFG.
+    ///
+    /// You will only ever need this if you have also called
+    /// [`Body::basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate`]. All other methods
+    /// that allow you to mutate the body also call this method themselves, thereby avoiding any
+    /// risk of accidentaly cache invalidation.
+    pub fn invalidate_cfg_cache(&mut self) {
         self.predecessor_cache.invalidate();
         self.switch_source_cache.invalidate();
         self.is_cyclic.invalidate();
         self.postorder_cache.invalidate();
-        (&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
     }
 
     /// Returns `true` if a cycle exists in the control-flow graph that is reachable from the