Skip to content

Commit 82c99c4

Browse files
Rollup merge of #140234 - nnethercote:separate-Analysis-and-Results, r=davidtwco
Separate dataflow analysis and results `Analysis` gets put into `Results` with `EntryStates`, by `iterate_to_fixpoint`. This has two problems: - `Results` is passed various places where only `Analysis` is needed. - `EntryStates` is passed around mutably everywhere even though it is immutable. This commit mostly separates `Analysis` from `Results` and fixes these two problems. r? `@davidtwco`
2 parents 3ef8e64 + 92799b6 commit 82c99c4

16 files changed

Lines changed: 235 additions & 227 deletions

File tree

‎compiler/rustc_borrowck/src/lib.rs‎

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use rustc_mir_dataflow::impls::{
4747
use rustc_mir_dataflow::move_paths::{
4848
InitIndex,InitLocation,LookupResult,MoveData,MovePathIndex,
4949
};
50-
use rustc_mir_dataflow::{Analysis,EntryStates,Results,ResultsVisitor, visit_results};
50+
use rustc_mir_dataflow::{Analysis,Results,ResultsVisitor, visit_results};
5151
use rustc_session::lint::builtin::{TAIL_EXPR_DROP_ORDER,UNUSED_MUT};
5252
use rustc_span::{ErrorGuaranteed,Span,Symbol};
5353
use smallvec::SmallVec;
@@ -461,11 +461,13 @@ fn do_mir_borrowck<'tcx>(
461461
// Compute and report region errors, if any.
462462
mbcx.report_region_errors(nll_errors);
463463

464-
letmut flow_results = get_flow_results(tcx, body,&move_data,&borrow_set,&regioncx);
464+
let(mut flow_analysis, flow_entry_states) =
465+
get_flow_results(tcx, body,&move_data,&borrow_set,&regioncx);
465466
visit_results(
466467
body,
467468
traversal::reverse_postorder(body).map(|(bb, _)| bb),
468-
&mut flow_results,
469+
&mut flow_analysis,
470+
&flow_entry_states,
469471
&mut mbcx,
470472
);
471473

@@ -525,7 +527,7 @@ fn get_flow_results<'a, 'tcx>(
525527
move_data:&'aMoveData<'tcx>,
526528
borrow_set:&'aBorrowSet<'tcx>,
527529
regioncx:&RegionInferenceContext<'tcx>,
528-
) -> Results<'tcx,Borrowck<'a,'tcx>>{
530+
) -> (Borrowck<'a,'tcx>,Results<BorrowckDomain>){
529531
// We compute these three analyses individually, but them combine them into
530532
// a single results so that `mbcx` can visit them all together.
531533
let borrows = Borrows::new(tcx, body, regioncx, borrow_set).iterate_to_fixpoint(
@@ -550,14 +552,14 @@ fn get_flow_results<'a, 'tcx>(
550552
ever_inits: ever_inits.analysis,
551553
};
552554

553-
assert_eq!(borrows.entry_states.len(), uninits.entry_states.len());
554-
assert_eq!(borrows.entry_states.len(), ever_inits.entry_states.len());
555-
letentry_states:EntryStates<'_,Borrowck<'_,'_>> =
556-
itertools::izip!(borrows.entry_states, uninits.entry_states, ever_inits.entry_states)
555+
assert_eq!(borrows.results.len(), uninits.results.len());
556+
assert_eq!(borrows.results.len(), ever_inits.results.len());
557+
letresults:Results<_> =
558+
itertools::izip!(borrows.results, uninits.results, ever_inits.results)
557559
.map(|(borrows, uninits, ever_inits)| BorrowckDomain{ borrows, uninits, ever_inits })
558560
.collect();
559561

560-
Results{analysis,entry_states }
562+
(analysis,results)
561563
}
562564

563565
pub(crate)structBorrowckInferCtxt<'tcx>{
@@ -705,7 +707,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
705707
impl<'a,'tcx>ResultsVisitor<'tcx,Borrowck<'a,'tcx>>forMirBorrowckCtxt<'a,'_,'tcx>{
706708
fnvisit_after_early_statement_effect(
707709
&mutself,
708-
_results:&mutResults<'tcx,Borrowck<'a,'tcx>>,
710+
_analysis:&mutBorrowck<'a,'tcx>,
709711
state:&BorrowckDomain,
710712
stmt:&Statement<'tcx>,
711713
location:Location,
@@ -781,7 +783,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a,
781783

782784
fnvisit_after_early_terminator_effect(
783785
&mutself,
784-
_results:&mutResults<'tcx,Borrowck<'a,'tcx>>,
786+
_analysis:&mutBorrowck<'a,'tcx>,
785787
state:&BorrowckDomain,
786788
term:&Terminator<'tcx>,
787789
loc:Location,
@@ -901,7 +903,7 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a,
901903

902904
fnvisit_after_primary_terminator_effect(
903905
&mutself,
904-
_results:&mutResults<'tcx,Borrowck<'a,'tcx>>,
906+
_analysis:&mutBorrowck<'a,'tcx>,
905907
state:&BorrowckDomain,
906908
term:&Terminator<'tcx>,
907909
loc:Location,

‎compiler/rustc_mir_dataflow/src/framework/cursor.rs‎

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Random access inspection of the results of a dataflow analysis.
22
3+
use std::borrow::Cow;
34
use std::cmp::Ordering;
45
use std::ops::{Deref,DerefMut};
56

@@ -9,38 +10,30 @@ use rustc_middle::mir::{self, BasicBlock, Location};
910

1011
usesuper::{Analysis,Direction,Effect,EffectIndex,Results};
1112

12-
/// Some `ResultsCursor`s want to own a `Results`, and some want to borrow a `Results`, either
13-
/// mutable or immutably. This type allows all of the above. It's similar to `Cow`.
14-
pubenumResultsHandle<'a,'tcx,A>
15-
where
16-
A:Analysis<'tcx>,
17-
{
18-
BorrowedMut(&'amutResults<'tcx,A>),
19-
Owned(Results<'tcx,A>),
13+
/// Some `ResultsCursor`s want to own an `Analysis`, and some want to borrow an `Analysis`, either
14+
/// mutable or immutably. This type allows all of the above. It's similar to `Cow`, but `Cow`
15+
/// doesn't allow mutable borrowing.
16+
enumCowMut<'a,T>{
17+
BorrowedMut(&'amutT),
18+
Owned(T),
2019
}
2120

22-
impl<'tcx,A>DerefforResultsHandle<'_,'tcx,A>
23-
where
24-
A:Analysis<'tcx>,
25-
{
26-
typeTarget = Results<'tcx,A>;
21+
impl<T>DerefforCowMut<'_,T>{
22+
typeTarget = T;
2723

28-
fnderef(&self) -> &Results<'tcx,A>{
24+
fnderef(&self) -> &T{
2925
matchself{
30-
ResultsHandle::BorrowedMut(borrowed) => borrowed,
31-
ResultsHandle::Owned(owned) => owned,
26+
CowMut::BorrowedMut(borrowed) => borrowed,
27+
CowMut::Owned(owned) => owned,
3228
}
3329
}
3430
}
3531

36-
impl<'tcx,A>DerefMutforResultsHandle<'_,'tcx,A>
37-
where
38-
A:Analysis<'tcx>,
39-
{
40-
fnderef_mut(&mutself) -> &mutResults<'tcx,A>{
32+
impl<T>DerefMutforCowMut<'_,T>{
33+
fnderef_mut(&mutself) -> &mutT{
4134
matchself{
42-
ResultsHandle::BorrowedMut(borrowed) => borrowed,
43-
ResultsHandle::Owned(owned) => owned,
35+
CowMut::BorrowedMut(borrowed) => borrowed,
36+
CowMut::Owned(owned) => owned,
4437
}
4538
}
4639
}
@@ -60,7 +53,8 @@ where
6053
A:Analysis<'tcx>,
6154
{
6255
body:&'mir mir::Body<'tcx>,
63-
results:ResultsHandle<'mir,'tcx,A>,
56+
analysis:CowMut<'mir,A>,
57+
results:Cow<'mir,Results<A::Domain>>,
6458
state:A::Domain,
6559

6660
pos:CursorPosition,
@@ -88,11 +82,15 @@ where
8882
self.body
8983
}
9084

91-
/// Returns a new cursor that can inspect `results`.
92-
pubfnnew(body:&'mir mir::Body<'tcx>,results:ResultsHandle<'mir,'tcx,A>) -> Self{
93-
let bottom_value = results.analysis.bottom_value(body);
85+
fnnew(
86+
body:&'mir mir::Body<'tcx>,
87+
analysis:CowMut<'mir,A>,
88+
results:Cow<'mir,Results<A::Domain>>,
89+
) -> Self{
90+
let bottom_value = analysis.bottom_value(body);
9491
ResultsCursor{
9592
body,
93+
analysis,
9694
results,
9795

9896
// Initialize to the `bottom_value` and set `state_needs_reset` to tell the cursor that
@@ -107,6 +105,24 @@ where
107105
}
108106
}
109107

108+
/// Returns a new cursor that takes ownership of and inspects analysis results.
109+
pubfnnew_owning(
110+
body:&'mir mir::Body<'tcx>,
111+
analysis:A,
112+
results:Results<A::Domain>,
113+
) -> Self{
114+
Self::new(body,CowMut::Owned(analysis),Cow::Owned(results))
115+
}
116+
117+
/// Returns a new cursor that borrows and inspects analysis results.
118+
pubfnnew_borrowing(
119+
body:&'mir mir::Body<'tcx>,
120+
analysis:&'mirmutA,
121+
results:&'mirResults<A::Domain>,
122+
) -> Self{
123+
Self::new(body,CowMut::BorrowedMut(analysis),Cow::Borrowed(results))
124+
}
125+
110126
/// Allows inspection of unreachable basic blocks even with `debug_assertions` enabled.
111127
#[cfg(test)]
112128
pub(crate)fnallow_unreachable(&mutself){
@@ -116,7 +132,7 @@ where
116132

117133
/// Returns the `Analysis` used to generate the underlying `Results`.
118134
pubfnanalysis(&self) -> &A{
119-
&self.results.analysis
135+
&self.analysis
120136
}
121137

122138
/// Resets the cursor to hold the entry set for the given basic block.
@@ -128,7 +144,7 @@ where
128144
#[cfg(debug_assertions)]
129145
assert!(self.reachable_blocks.contains(block));
130146

131-
self.state.clone_from(self.results.entry_set_for_block(block));
147+
self.state.clone_from(&self.results[block]);
132148
self.pos = CursorPosition::block_entry(block);
133149
self.state_needs_reset = false;
134150
}
@@ -220,7 +236,7 @@ where
220236
let target_effect_index = effect.at_index(target.statement_index);
221237

222238
A::Direction::apply_effects_in_range(
223-
&mutself.results.analysis,
239+
&mut*self.analysis,
224240
&mutself.state,
225241
target.block,
226242
block_data,
@@ -236,7 +252,7 @@ where
236252
/// This can be used, e.g., to apply the call return effect directly to the cursor without
237253
/// creating an extra copy of the dataflow state.
238254
pubfnapply_custom_effect(&mutself,f:implFnOnce(&mutA,&mutA::Domain)){
239-
f(&mutself.results.analysis,&mutself.state);
255+
f(&mutself.analysis,&mutself.state);
240256
self.state_needs_reset = true;
241257
}
242258
}

‎compiler/rustc_mir_dataflow/src/framework/direction.rs‎

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_middle::mir::{
55
};
66

77
usesuper::visitor::ResultsVisitor;
8-
usesuper::{Analysis,Effect,EffectIndex,Results};
8+
usesuper::{Analysis,Effect,EffectIndex};
99

1010
pubtraitDirection{
1111
constIS_FORWARD:bool;
@@ -36,13 +36,13 @@ pub trait Direction {
3636
A:Analysis<'tcx>;
3737

3838
/// Called by `ResultsVisitor` to recompute the analysis domain values for
39-
/// all locations in a basic block (starting from the entry value stored
40-
/// in `Results`) and to visit them with `vis`.
39+
/// all locations in a basic block (starting from `entry_state` and to
40+
/// visit them with `vis`.
4141
fnvisit_results_in_block<'mir,'tcx,A>(
4242
state:&mutA::Domain,
4343
block:BasicBlock,
4444
block_data:&'mir mir::BasicBlockData<'tcx>,
45-
results:&mutResults<'tcx,A>,
45+
analysis:&mutA,
4646
vis:&mutimplResultsVisitor<'tcx,A>,
4747
)where
4848
A:Analysis<'tcx>;
@@ -211,28 +211,26 @@ impl Direction for Backward {
211211
state:&mutA::Domain,
212212
block:BasicBlock,
213213
block_data:&'mir mir::BasicBlockData<'tcx>,
214-
results:&mutResults<'tcx,A>,
214+
analysis:&mutA,
215215
vis:&mutimplResultsVisitor<'tcx,A>,
216216
)where
217217
A:Analysis<'tcx>,
218218
{
219-
state.clone_from(results.entry_set_for_block(block));
220-
221219
vis.visit_block_end(state);
222220

223221
let loc = Location{ block,statement_index: block_data.statements.len()};
224222
let term = block_data.terminator();
225-
results.analysis.apply_early_terminator_effect(state, term, loc);
226-
vis.visit_after_early_terminator_effect(results, state, term, loc);
227-
results.analysis.apply_primary_terminator_effect(state, term, loc);
228-
vis.visit_after_primary_terminator_effect(results, state, term, loc);
223+
analysis.apply_early_terminator_effect(state, term, loc);
224+
vis.visit_after_early_terminator_effect(analysis, state, term, loc);
225+
analysis.apply_primary_terminator_effect(state, term, loc);
226+
vis.visit_after_primary_terminator_effect(analysis, state, term, loc);
229227

230228
for(statement_index, stmt)in block_data.statements.iter().enumerate().rev(){
231229
let loc = Location{ block, statement_index };
232-
results.analysis.apply_early_statement_effect(state, stmt, loc);
233-
vis.visit_after_early_statement_effect(results, state, stmt, loc);
234-
results.analysis.apply_primary_statement_effect(state, stmt, loc);
235-
vis.visit_after_primary_statement_effect(results, state, stmt, loc);
230+
analysis.apply_early_statement_effect(state, stmt, loc);
231+
vis.visit_after_early_statement_effect(analysis, state, stmt, loc);
232+
analysis.apply_primary_statement_effect(state, stmt, loc);
233+
vis.visit_after_primary_statement_effect(analysis, state, stmt, loc);
236234
}
237235

238236
vis.visit_block_start(state);
@@ -393,29 +391,27 @@ impl Direction for Forward {
393391
state:&mutA::Domain,
394392
block:BasicBlock,
395393
block_data:&'mir mir::BasicBlockData<'tcx>,
396-
results:&mutResults<'tcx,A>,
394+
analysis:&mutA,
397395
vis:&mutimplResultsVisitor<'tcx,A>,
398396
)where
399397
A:Analysis<'tcx>,
400398
{
401-
state.clone_from(results.entry_set_for_block(block));
402-
403399
vis.visit_block_start(state);
404400

405401
for(statement_index, stmt)in block_data.statements.iter().enumerate(){
406402
let loc = Location{ block, statement_index };
407-
results.analysis.apply_early_statement_effect(state, stmt, loc);
408-
vis.visit_after_early_statement_effect(results, state, stmt, loc);
409-
results.analysis.apply_primary_statement_effect(state, stmt, loc);
410-
vis.visit_after_primary_statement_effect(results, state, stmt, loc);
403+
analysis.apply_early_statement_effect(state, stmt, loc);
404+
vis.visit_after_early_statement_effect(analysis, state, stmt, loc);
405+
analysis.apply_primary_statement_effect(state, stmt, loc);
406+
vis.visit_after_primary_statement_effect(analysis, state, stmt, loc);
411407
}
412408

413409
let loc = Location{ block,statement_index: block_data.statements.len()};
414410
let term = block_data.terminator();
415-
results.analysis.apply_early_terminator_effect(state, term, loc);
416-
vis.visit_after_early_terminator_effect(results, state, term, loc);
417-
results.analysis.apply_primary_terminator_effect(state, term, loc);
418-
vis.visit_after_primary_terminator_effect(results, state, term, loc);
411+
analysis.apply_early_terminator_effect(state, term, loc);
412+
vis.visit_after_early_terminator_effect(analysis, state, term, loc);
413+
analysis.apply_primary_terminator_effect(state, term, loc);
414+
vis.visit_after_primary_terminator_effect(analysis, state, term, loc);
419415

420416
vis.visit_block_end(state);
421417
}

0 commit comments

Comments
 (0)