@@ -47,8 +47,7 @@ impl Cache {
4747 }
4848
4949 #[ inline]
50- /// This will recompute the predecessors cache if it is not available
51- pub fn predecessors ( & mut self , body : & Body < ' _ > ) -> & IndexVec < BasicBlock , Vec < BasicBlock > > {
50+ pub fn ensure_predecessors ( & mut self , body : & Body < ' _ > ) {
5251 if self . predecessors . is_none ( ) {
5352 let mut result = IndexVec :: from_elem ( vec ! [ ] , body. basic_blocks ( ) ) ;
5453 for ( bb, data) in body. basic_blocks ( ) . iter_enumerated ( ) {
@@ -61,7 +60,12 @@ impl Cache {
6160
6261 self . predecessors = Some ( result)
6362 }
63+ }
6464
65+ #[ inline]
66+ /// This will recompute the predecessors cache if it is not available
67+ pub fn predecessors ( & mut self , body : & Body < ' _ > ) -> & IndexVec < BasicBlock , Vec < BasicBlock > > {
68+ self . ensure_predecessors ( body) ;
6569 self . predecessors . as_ref ( ) . unwrap ( )
6670 }
6771
@@ -70,6 +74,11 @@ impl Cache {
7074 & self . predecessors ( body) [ bb]
7175 }
7276
77+ #[ inline]
78+ fn unwrap_predecessors_for ( & self , bb : BasicBlock ) -> & [ BasicBlock ] {
79+ & self . predecessors . as_ref ( ) . unwrap ( ) [ bb]
80+ }
81+
7382 #[ inline]
7483 pub fn predecessor_locations < ' a > ( & ' a mut self , loc : Location , body : & ' a Body < ' a > ) -> impl Iterator < Item = Location > + ' a {
7584 let if_zero_locations = if loc. statement_index == 0 {
@@ -137,13 +146,17 @@ impl<'a, 'tcx> BodyCache<&'a Body<'tcx>> {
137146 }
138147
139148 #[ inline]
140- pub fn basic_blocks ( & self ) -> & IndexVec < BasicBlock , BasicBlockData < ' tcx > > {
141- & self . body . basic_blocks
149+ pub fn read_only ( mut self ) -> ReadOnlyBodyCache < ' a , ' tcx > {
150+ self . cache . ensure_predecessors ( self . body ) ;
151+ ReadOnlyBodyCache {
152+ cache : self . cache ,
153+ body : self . body ,
154+ }
142155 }
143156
144157 #[ inline]
145- pub fn dominators ( & mut self ) -> Dominators < BasicBlock > {
146- dominators ( self )
158+ pub fn basic_blocks ( & self ) -> & IndexVec < BasicBlock , BasicBlockData < ' tcx > > {
159+ & self . body . basic_blocks
147160 }
148161}
149162
@@ -164,50 +177,6 @@ impl<'a, 'tcx> Index<BasicBlock> for BodyCache<&'a Body<'tcx>> {
164177 }
165178}
166179
167- impl < ' a , ' tcx > graph:: DirectedGraph for BodyCache < & ' a Body < ' tcx > > {
168- type Node = BasicBlock ;
169- }
170-
171- impl < ' a , ' graph , ' tcx > graph:: GraphPredecessors < ' graph > for BodyCache < & ' a Body < ' tcx > > {
172- type Item = BasicBlock ;
173- type Iter = IntoIter < BasicBlock > ;
174- }
175-
176- impl < ' a , ' tcx > graph:: WithPredecessors for BodyCache < & ' a Body < ' tcx > > {
177- fn predecessors (
178- & mut self ,
179- node : Self :: Node ,
180- ) -> <Self as GraphPredecessors < ' _ > >:: Iter {
181- self . predecessors_for ( node) . to_vec ( ) . into_iter ( )
182- }
183- }
184-
185- impl < ' a , ' tcx > graph:: WithNumNodes for BodyCache < & ' a Body < ' tcx > > {
186- fn num_nodes ( & self ) -> usize {
187- self . body . num_nodes ( )
188- }
189- }
190-
191- impl < ' a , ' tcx > graph:: WithStartNode for BodyCache < & ' a Body < ' tcx > > {
192- fn start_node ( & self ) -> Self :: Node {
193- self . body . start_node ( )
194- }
195- }
196-
197- impl < ' a , ' tcx > graph:: WithSuccessors for BodyCache < & ' a Body < ' tcx > > {
198- fn successors (
199- & self ,
200- node : Self :: Node ,
201- ) -> <Self as GraphSuccessors < ' _ > >:: Iter {
202- self . body . successors ( node)
203- }
204- }
205-
206- impl < ' a , ' b , ' tcx > graph:: GraphSuccessors < ' b > for BodyCache < & ' a Body < ' tcx > > {
207- type Item = BasicBlock ;
208- type Iter = iter:: Cloned < Successors < ' b > > ;
209- }
210-
211180impl < ' a , ' tcx > BodyCache < & ' a mut Body < ' tcx > > {
212181 #[ inline]
213182 pub fn body ( & self ) -> & Body < ' tcx > {
@@ -259,3 +228,99 @@ impl<'a, 'tcx> IndexMut<BasicBlock> for BodyCache<&'a mut Body<'tcx>> {
259228 & mut self . body . basic_blocks [ index]
260229 }
261230}
231+
232+ pub struct ReadOnlyBodyCache < ' a , ' tcx > {
233+ cache : Cache ,
234+ body : & ' a Body < ' tcx > ,
235+ }
236+
237+ impl ReadOnlyBodyCache < ' a , ' tcx > {
238+ #[ inline]
239+ pub fn predecessors_for ( & self , bb : BasicBlock ) -> & [ BasicBlock ] {
240+ self . cache . unwrap_predecessors_for ( bb)
241+ }
242+
243+ #[ inline]
244+ pub fn body ( & self ) -> & ' a Body < ' tcx > {
245+ self . body
246+ }
247+
248+ #[ inline]
249+ pub fn basic_blocks ( & self ) -> & IndexVec < BasicBlock , BasicBlockData < ' tcx > > {
250+ & self . body . basic_blocks
251+ }
252+
253+ #[ inline]
254+ pub fn dominators ( & self ) -> Dominators < BasicBlock > {
255+ dominators ( self )
256+ }
257+
258+ pub fn to_owned ( self ) -> BodyCache < & ' a Body < ' tcx > > {
259+ BodyCache {
260+ cache : self . cache ,
261+ body : self . body ,
262+ }
263+ }
264+ }
265+
266+ impl graph:: DirectedGraph for ReadOnlyBodyCache < ' a , ' tcx > {
267+ type Node = BasicBlock ;
268+ }
269+
270+ impl graph:: GraphPredecessors < ' graph > for ReadOnlyBodyCache < ' a , ' tcx > {
271+ type Item = BasicBlock ;
272+ type Iter = IntoIter < BasicBlock > ;
273+ }
274+
275+ impl graph:: WithPredecessors for ReadOnlyBodyCache < ' a , ' tcx > {
276+ fn predecessors (
277+ & self ,
278+ node : Self :: Node ,
279+ ) -> <Self as GraphPredecessors < ' _ > >:: Iter {
280+ self . cache . unwrap_predecessors_for ( node) . to_vec ( ) . into_iter ( )
281+ }
282+ }
283+
284+ impl graph:: WithNumNodes for ReadOnlyBodyCache < ' a , ' tcx > {
285+ fn num_nodes ( & self ) -> usize {
286+ self . body . num_nodes ( )
287+ }
288+ }
289+
290+ impl graph:: WithStartNode for ReadOnlyBodyCache < ' a , ' tcx > {
291+ fn start_node ( & self ) -> Self :: Node {
292+ self . body . start_node ( )
293+ }
294+ }
295+
296+ impl graph:: WithSuccessors for ReadOnlyBodyCache < ' a , ' tcx > {
297+ fn successors (
298+ & self ,
299+ node : Self :: Node ,
300+ ) -> <Self as GraphSuccessors < ' _ > >:: Iter {
301+ self . body . successors ( node)
302+ }
303+ }
304+
305+ impl < ' a , ' b , ' tcx > graph:: GraphSuccessors < ' b > for ReadOnlyBodyCache < ' a , ' tcx > {
306+ type Item = BasicBlock ;
307+ type Iter = iter:: Cloned < Successors < ' b > > ;
308+ }
309+
310+
311+ impl Deref for ReadOnlyBodyCache < ' a , ' tcx > {
312+ type Target = Body < ' tcx > ;
313+
314+ fn deref ( & self ) -> & Self :: Target {
315+ self . body
316+ }
317+ }
318+
319+ impl Index < BasicBlock > for ReadOnlyBodyCache < ' a , ' tcx > {
320+ type Output = BasicBlockData < ' tcx > ;
321+
322+ #[ inline]
323+ fn index ( & self , index : BasicBlock ) -> & BasicBlockData < ' tcx > {
324+ & self . body [ index]
325+ }
326+ }
0 commit comments