Skip to content

Commit 6dcebb6

Browse files
authored
Unrolled build for #132134
Rollup merge of #132134 - nnethercote:rm-ResultsVisitable, r=cjgillot Remove `ResultsVisitable` `ResultsVisitable` has annoyed me for a while. This PR removes it. Details in the individual commits. r? `@cjgillot.`
2 parents ee4a56e + c904c6a commit 6dcebb6

File tree

11 files changed

+261
-274
lines changed

11 files changed

+261
-274
lines changed

compiler/rustc_borrowck/src/dataflow.rs

+119-41
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,171 @@
1+
use std::fmt;
2+
13
use rustc_data_structures::fx::FxIndexMap;
24
use rustc_data_structures::graph;
35
use rustc_index::bit_set::BitSet;
4-
use rustc_middle::mir::{self, BasicBlock, Body, Location, Place, TerminatorEdges};
6+
use rustc_middle::mir::{
7+
self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges,
8+
};
59
use rustc_middle::ty::{RegionVid, TyCtxt};
610
use rustc_mir_dataflow::fmt::DebugWithContext;
711
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
8-
use rustc_mir_dataflow::{Analysis, Forward, GenKill, Results, ResultsVisitable};
12+
use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice, SwitchIntEdgeEffects};
913
use tracing::debug;
1014

1115
use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict};
1216

13-
/// The results of the dataflow analyses used by the borrow checker.
14-
pub(crate) struct BorrowckResults<'a, 'tcx> {
15-
pub(crate) borrows: Results<'tcx, Borrows<'a, 'tcx>>,
16-
pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>,
17-
pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'tcx>>,
18-
}
19-
20-
/// The transient state of the dataflow analyses used by the borrow checker.
21-
#[derive(Debug)]
22-
pub(crate) struct BorrowckDomain<'a, 'tcx> {
23-
pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain,
24-
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
25-
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
17+
// This analysis is different to most others. Its results aren't computed with
18+
// `iterate_to_fixpoint`, but are instead composed from the results of three sub-analyses that are
19+
// computed individually with `iterate_to_fixpoint`.
20+
pub(crate) struct Borrowck<'a, 'tcx> {
21+
pub(crate) borrows: Borrows<'a, 'tcx>,
22+
pub(crate) uninits: MaybeUninitializedPlaces<'a, 'tcx>,
23+
pub(crate) ever_inits: EverInitializedPlaces<'a, 'tcx>,
2624
}
2725

28-
impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> {
29-
type Direction = Forward;
26+
impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> {
3027
type Domain = BorrowckDomain<'a, 'tcx>;
3128

29+
const NAME: &'static str = "borrowck";
30+
3231
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
3332
BorrowckDomain {
34-
borrows: self.borrows.analysis.bottom_value(body),
35-
uninits: self.uninits.analysis.bottom_value(body),
36-
ever_inits: self.ever_inits.analysis.bottom_value(body),
33+
borrows: self.borrows.bottom_value(body),
34+
uninits: self.uninits.bottom_value(body),
35+
ever_inits: self.ever_inits.bottom_value(body),
3736
}
3837
}
3938

40-
fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) {
41-
state.borrows.clone_from(self.borrows.entry_set_for_block(block));
42-
state.uninits.clone_from(self.uninits.entry_set_for_block(block));
43-
state.ever_inits.clone_from(self.ever_inits.entry_set_for_block(block));
39+
fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _state: &mut Self::Domain) {
40+
// This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
41+
unreachable!();
4442
}
4543

46-
fn reconstruct_before_statement_effect(
44+
fn apply_before_statement_effect(
4745
&mut self,
4846
state: &mut Self::Domain,
4947
stmt: &mir::Statement<'tcx>,
5048
loc: Location,
5149
) {
52-
self.borrows.analysis.apply_before_statement_effect(&mut state.borrows, stmt, loc);
53-
self.uninits.analysis.apply_before_statement_effect(&mut state.uninits, stmt, loc);
54-
self.ever_inits.analysis.apply_before_statement_effect(&mut state.ever_inits, stmt, loc);
50+
self.borrows.apply_before_statement_effect(&mut state.borrows, stmt, loc);
51+
self.uninits.apply_before_statement_effect(&mut state.uninits, stmt, loc);
52+
self.ever_inits.apply_before_statement_effect(&mut state.ever_inits, stmt, loc);
5553
}
5654

57-
fn reconstruct_statement_effect(
55+
fn apply_statement_effect(
5856
&mut self,
5957
state: &mut Self::Domain,
6058
stmt: &mir::Statement<'tcx>,
6159
loc: Location,
6260
) {
63-
self.borrows.analysis.apply_statement_effect(&mut state.borrows, stmt, loc);
64-
self.uninits.analysis.apply_statement_effect(&mut state.uninits, stmt, loc);
65-
self.ever_inits.analysis.apply_statement_effect(&mut state.ever_inits, stmt, loc);
61+
self.borrows.apply_statement_effect(&mut state.borrows, stmt, loc);
62+
self.uninits.apply_statement_effect(&mut state.uninits, stmt, loc);
63+
self.ever_inits.apply_statement_effect(&mut state.ever_inits, stmt, loc);
6664
}
6765

68-
fn reconstruct_before_terminator_effect(
66+
fn apply_before_terminator_effect(
6967
&mut self,
7068
state: &mut Self::Domain,
7169
term: &mir::Terminator<'tcx>,
7270
loc: Location,
7371
) {
74-
self.borrows.analysis.apply_before_terminator_effect(&mut state.borrows, term, loc);
75-
self.uninits.analysis.apply_before_terminator_effect(&mut state.uninits, term, loc);
76-
self.ever_inits.analysis.apply_before_terminator_effect(&mut state.ever_inits, term, loc);
72+
self.borrows.apply_before_terminator_effect(&mut state.borrows, term, loc);
73+
self.uninits.apply_before_terminator_effect(&mut state.uninits, term, loc);
74+
self.ever_inits.apply_before_terminator_effect(&mut state.ever_inits, term, loc);
7775
}
7876

79-
fn reconstruct_terminator_effect(
77+
fn apply_terminator_effect<'mir>(
8078
&mut self,
8179
state: &mut Self::Domain,
82-
term: &mir::Terminator<'tcx>,
80+
term: &'mir mir::Terminator<'tcx>,
8381
loc: Location,
82+
) -> TerminatorEdges<'mir, 'tcx> {
83+
self.borrows.apply_terminator_effect(&mut state.borrows, term, loc);
84+
self.uninits.apply_terminator_effect(&mut state.uninits, term, loc);
85+
self.ever_inits.apply_terminator_effect(&mut state.ever_inits, term, loc);
86+
87+
// This return value doesn't matter. It's only used by `iterate_to_fixpoint`, which this
88+
// analysis doesn't use.
89+
TerminatorEdges::None
90+
}
91+
92+
fn apply_call_return_effect(
93+
&mut self,
94+
_state: &mut Self::Domain,
95+
_block: BasicBlock,
96+
_return_places: CallReturnPlaces<'_, 'tcx>,
97+
) {
98+
// This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
99+
unreachable!();
100+
}
101+
102+
fn apply_switch_int_edge_effects(
103+
&mut self,
104+
_block: BasicBlock,
105+
_discr: &mir::Operand<'tcx>,
106+
_apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
84107
) {
85-
self.borrows.analysis.apply_terminator_effect(&mut state.borrows, term, loc);
86-
self.uninits.analysis.apply_terminator_effect(&mut state.uninits, term, loc);
87-
self.ever_inits.analysis.apply_terminator_effect(&mut state.ever_inits, term, loc);
108+
// This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
109+
unreachable!();
88110
}
89111
}
90112

113+
impl JoinSemiLattice for BorrowckDomain<'_, '_> {
114+
fn join(&mut self, _other: &Self) -> bool {
115+
// This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use.
116+
unreachable!();
117+
}
118+
}
119+
120+
impl<'tcx, C> DebugWithContext<C> for BorrowckDomain<'_, 'tcx>
121+
where
122+
C: rustc_mir_dataflow::move_paths::HasMoveData<'tcx>,
123+
{
124+
fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125+
f.write_str("borrows: ")?;
126+
self.borrows.fmt_with(ctxt, f)?;
127+
f.write_str(" uninits: ")?;
128+
self.uninits.fmt_with(ctxt, f)?;
129+
f.write_str(" ever_inits: ")?;
130+
self.ever_inits.fmt_with(ctxt, f)?;
131+
Ok(())
132+
}
133+
134+
fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135+
if self == old {
136+
return Ok(());
137+
}
138+
139+
if self.borrows != old.borrows {
140+
f.write_str("borrows: ")?;
141+
self.borrows.fmt_diff_with(&old.borrows, ctxt, f)?;
142+
f.write_str("\n")?;
143+
}
144+
145+
if self.uninits != old.uninits {
146+
f.write_str("uninits: ")?;
147+
self.uninits.fmt_diff_with(&old.uninits, ctxt, f)?;
148+
f.write_str("\n")?;
149+
}
150+
151+
if self.ever_inits != old.ever_inits {
152+
f.write_str("ever_inits: ")?;
153+
self.ever_inits.fmt_diff_with(&old.ever_inits, ctxt, f)?;
154+
f.write_str("\n")?;
155+
}
156+
157+
Ok(())
158+
}
159+
}
160+
161+
/// The transient state of the dataflow analyses used by the borrow checker.
162+
#[derive(Clone, Debug, PartialEq, Eq)]
163+
pub(crate) struct BorrowckDomain<'a, 'tcx> {
164+
pub(crate) borrows: <Borrows<'a, 'tcx> as Analysis<'tcx>>::Domain,
165+
pub(crate) uninits: <MaybeUninitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
166+
pub(crate) ever_inits: <EverInitializedPlaces<'a, 'tcx> as Analysis<'tcx>>::Domain,
167+
}
168+
91169
rustc_index::newtype_index! {
92170
#[orderable]
93171
#[debug_format = "bw{}"]

compiler/rustc_borrowck/src/lib.rs

+54-39
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,21 @@ use rustc_middle::mir::*;
3636
use rustc_middle::query::Providers;
3737
use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode};
3838
use rustc_middle::{bug, span_bug};
39-
use rustc_mir_dataflow::Analysis;
4039
use rustc_mir_dataflow::impls::{
4140
EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
4241
};
4342
use rustc_mir_dataflow::move_paths::{
4443
InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex,
4544
};
45+
use rustc_mir_dataflow::{Analysis, EntrySets, Results, ResultsVisitor, visit_results};
4646
use rustc_session::lint::builtin::UNUSED_MUT;
4747
use rustc_span::{Span, Symbol};
4848
use smallvec::SmallVec;
4949
use tracing::{debug, instrument};
5050

5151
use crate::borrow_set::{BorrowData, BorrowSet};
5252
use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions};
53-
use crate::dataflow::{BorrowIndex, BorrowckDomain, BorrowckResults, Borrows};
53+
use crate::dataflow::{BorrowIndex, Borrowck, BorrowckDomain, Borrows};
5454
use crate::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName};
5555
use crate::location::LocationTable;
5656
use crate::nll::PoloniusOutput;
@@ -221,6 +221,10 @@ fn do_mir_borrowck<'tcx>(
221221
consumer_options,
222222
);
223223

224+
// `flow_inits` is large, so we drop it as soon as possible. This reduces
225+
// peak memory usage significantly on some benchmarks.
226+
drop(flow_inits);
227+
224228
// Dump MIR results into a file, if that is enabled. This let us
225229
// write unit-tests, as well as helping with debugging.
226230
nll::dump_nll_mir(&infcx, body, &regioncx, &opt_closure_req, &borrow_set);
@@ -229,27 +233,6 @@ fn do_mir_borrowck<'tcx>(
229233
// information.
230234
nll::dump_annotation(&infcx, body, &regioncx, &opt_closure_req, &opaque_type_values, diags);
231235

232-
// The various `flow_*` structures can be large. We drop `flow_inits` here
233-
// so it doesn't overlap with the others below. This reduces peak memory
234-
// usage significantly on some benchmarks.
235-
drop(flow_inits);
236-
237-
let flow_borrows = Borrows::new(tcx, body, &regioncx, &borrow_set).iterate_to_fixpoint(
238-
tcx,
239-
body,
240-
Some("borrowck"),
241-
);
242-
let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint(
243-
tcx,
244-
body,
245-
Some("borrowck"),
246-
);
247-
let flow_ever_inits = EverInitializedPlaces::new(body, &move_data).iterate_to_fixpoint(
248-
tcx,
249-
body,
250-
Some("borrowck"),
251-
);
252-
253236
let movable_coroutine =
254237
// The first argument is the coroutine type passed by value
255238
if let Some(local) = body.local_decls.raw.get(1)
@@ -334,16 +317,11 @@ fn do_mir_borrowck<'tcx>(
334317
// Compute and report region errors, if any.
335318
mbcx.report_region_errors(nll_errors);
336319

337-
let mut results = BorrowckResults {
338-
ever_inits: flow_ever_inits,
339-
uninits: flow_uninits,
340-
borrows: flow_borrows,
341-
};
342-
343-
rustc_mir_dataflow::visit_results(
320+
let mut flow_results = get_flow_results(tcx, body, &move_data, &borrow_set, &regioncx);
321+
visit_results(
344322
body,
345323
traversal::reverse_postorder(body).map(|(bb, _)| bb),
346-
&mut results,
324+
&mut flow_results,
347325
&mut mbcx,
348326
);
349327

@@ -426,6 +404,47 @@ fn do_mir_borrowck<'tcx>(
426404
(result, body_with_facts)
427405
}
428406

407+
fn get_flow_results<'a, 'tcx>(
408+
tcx: TyCtxt<'tcx>,
409+
body: &'a Body<'tcx>,
410+
move_data: &'a MoveData<'tcx>,
411+
borrow_set: &'a BorrowSet<'tcx>,
412+
regioncx: &RegionInferenceContext<'tcx>,
413+
) -> Results<'tcx, Borrowck<'a, 'tcx>> {
414+
// We compute these three analyses individually, but them combine them into
415+
// a single results so that `mbcx` can visit them all together.
416+
let borrows = Borrows::new(tcx, body, regioncx, borrow_set).iterate_to_fixpoint(
417+
tcx,
418+
body,
419+
Some("borrowck"),
420+
);
421+
let uninits = MaybeUninitializedPlaces::new(tcx, body, move_data).iterate_to_fixpoint(
422+
tcx,
423+
body,
424+
Some("borrowck"),
425+
);
426+
let ever_inits = EverInitializedPlaces::new(body, move_data).iterate_to_fixpoint(
427+
tcx,
428+
body,
429+
Some("borrowck"),
430+
);
431+
432+
let analysis = Borrowck {
433+
borrows: borrows.analysis,
434+
uninits: uninits.analysis,
435+
ever_inits: ever_inits.analysis,
436+
};
437+
438+
assert_eq!(borrows.entry_sets.len(), uninits.entry_sets.len());
439+
assert_eq!(borrows.entry_sets.len(), ever_inits.entry_sets.len());
440+
let entry_sets: EntrySets<'_, Borrowck<'_, '_>> =
441+
itertools::izip!(borrows.entry_sets, uninits.entry_sets, ever_inits.entry_sets)
442+
.map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits })
443+
.collect();
444+
445+
Results { analysis, entry_sets }
446+
}
447+
429448
pub(crate) struct BorrowckInferCtxt<'tcx> {
430449
pub(crate) infcx: InferCtxt<'tcx>,
431450
pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
@@ -588,14 +607,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
588607
// 2. loans made in overlapping scopes do not conflict
589608
// 3. assignments do not affect things loaned out as immutable
590609
// 4. moves do not affect things loaned out in any way
591-
impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
592-
for MirBorrowckCtxt<'a, '_, 'tcx>
593-
{
594-
type Domain = BorrowckDomain<'a, 'tcx>;
595-
610+
impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> {
596611
fn visit_statement_before_primary_effect(
597612
&mut self,
598-
_results: &mut R,
613+
_results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
599614
state: &BorrowckDomain<'a, 'tcx>,
600615
stmt: &'a Statement<'tcx>,
601616
location: Location,
@@ -667,7 +682,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
667682

668683
fn visit_terminator_before_primary_effect(
669684
&mut self,
670-
_results: &mut R,
685+
_results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
671686
state: &BorrowckDomain<'a, 'tcx>,
672687
term: &'a Terminator<'tcx>,
673688
loc: Location,
@@ -780,7 +795,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
780795

781796
fn visit_terminator_after_primary_effect(
782797
&mut self,
783-
_results: &mut R,
798+
_results: &mut Results<'tcx, Borrowck<'a, 'tcx>>,
784799
state: &BorrowckDomain<'a, 'tcx>,
785800
term: &'a Terminator<'tcx>,
786801
loc: Location,

0 commit comments

Comments
 (0)