Skip to content

Commit db7352d

Browse files
committed
Adjust Analysis/GenKillAnalysis interaction.
`Analysis` has six methods of note: - `apply_statement_effect` - `apply_before_statement_effect` - `apply_terminator_effect` - `apply_before_terminator_effect` - `apply_call_return_effect` - `apply_switch_int_edge_effects` `GenKillAnalysis` has six similar methods of note: - `statement_effect` - `before_statement_effect` - `terminator_effect` - `before_terminator_effect` - `call_return_effect` - `switch_int_edge_effects` Every `GenKillAnalysis` also implicitly impls `Analysis`, thanks to this blanket impl: ``` impl<'tcx, A> Analysis<'tcx> for A where A: GenKillAnalysis<'tcx>, A::Domain: GenKill<A::Idx> + BitSetExt<A::Idx>, ``` which forwards `apply_statement_effect` to `statement_effect`, and so on. This is a nice symmetry, but it's misleading. The latter four `GenKillAnalysis` methods (`terminator_effect`, ...) are only called from the latter four `Analysis` methods (`apply_terminator_effect`, ...). In reality, to implement a `GenKillAnalysis` you want to implement the first two `GenKillAnalysis` methods (which take `impl GenKill` args) and the latter four `Analysis` methods (which can take `Self::Domain` args). This commit adjusts things accordingly. - The latter four methods in `GenKillAnalysis` are removed. - The blanket impl of `Analysis` for any type implementing `GenKillAnalysis` is removed. - Each gen-kill analysis now implements the two `GenKillAnalysis` methods and the four latter `Analysis` methods. - Each gen-kill analysis also implicitly implements the first two `Analysis` methods by using new macros `fn_apply_before_statement_effect_gen_kill!` and `fn_apply_statement_effect_gen_kill!` that just define a method that forwards on to the corresponding `GenKillAnalysis` method. Overall this is a little less code and I find the whole structure easier to understand.
1 parent 1b35beb commit db7352d

File tree

6 files changed

+123
-154
lines changed

6 files changed

+123
-154
lines changed

compiler/rustc_borrowck/src/dataflow.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_middle::ty::RegionVid;
1010
use rustc_middle::ty::TyCtxt;
1111
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
1212
use rustc_mir_dataflow::ResultsVisitable;
13-
use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
14-
use rustc_mir_dataflow::{Analysis, Direction, Results};
13+
use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill, GenKillAnalysis};
14+
use rustc_mir_dataflow::{Analysis, AnalysisDomain, Direction, Results};
1515
use std::fmt;
1616

1717
use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
@@ -506,7 +506,7 @@ impl<'mir, 'tcx> Borrows<'mir, 'tcx> {
506506
}
507507
}
508508

509-
impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
509+
impl<'tcx> AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
510510
type Domain = BitSet<BorrowIndex>;
511511

512512
const NAME: &'static str = "borrows";
@@ -529,7 +529,7 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
529529
/// region stops containing the CFG points reachable from the issuing location.
530530
/// - we also kill loans of conflicting places when overwriting a shared path: e.g. borrows of
531531
/// `a.b.c` when `a` is overwritten.
532-
impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
532+
impl<'tcx> GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
533533
type Idx = BorrowIndex;
534534

535535
fn domain_size(&self, _: &mir::Body<'tcx>) -> usize {
@@ -592,17 +592,23 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
592592
| mir::StatementKind::Nop => {}
593593
}
594594
}
595+
}
596+
597+
impl<'tcx> Analysis<'tcx> for Borrows<'_, 'tcx> {
598+
rustc_mir_dataflow::fn_apply_before_statement_effect_gen_kill!();
599+
600+
rustc_mir_dataflow::fn_apply_statement_effect_gen_kill!();
595601

596-
fn before_terminator_effect(
602+
fn apply_before_terminator_effect(
597603
&mut self,
598-
trans: &mut impl GenKill<Self::Idx>,
604+
trans: &mut Self::Domain,
599605
_terminator: &mir::Terminator<'tcx>,
600606
location: Location,
601607
) {
602608
self.kill_loans_out_of_scope_at_location(trans, location);
603609
}
604610

605-
fn terminator_effect<'mir>(
611+
fn apply_terminator_effect<'mir>(
606612
&mut self,
607613
trans: &mut Self::Domain,
608614
terminator: &'mir mir::Terminator<'tcx>,
@@ -620,9 +626,9 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
620626
terminator.edges()
621627
}
622628

623-
fn call_return_effect(
629+
fn apply_call_return_effect(
624630
&mut self,
625-
_trans: &mut impl GenKill<Self::Idx>,
631+
_trans: &mut Self::Domain,
626632
_block: mir::BasicBlock,
627633
_return_places: CallReturnPlaces<'_, 'tcx>,
628634
) {

compiler/rustc_mir_dataflow/src/framework/mod.rs

Lines changed: 34 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,9 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
253253
/// functions for each statement in this way, the transfer function for an entire basic block can
254254
/// be computed efficiently.
255255
///
256-
/// `Analysis` is automatically implemented for all implementers of `GenKillAnalysis`.
256+
/// Use `fn_apply_statement_effect_gen_kill!` and (optionally)
257+
/// `fn_apply_before_statement_effect_gen_kill!` to simplify the definition of
258+
/// `Analysis` for analyses that also impl `GenKillAnalysis`.
257259
pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
258260
type Idx: Idx;
259261

@@ -275,117 +277,40 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
275277
_location: Location,
276278
) {
277279
}
278-
279-
/// See `Analysis::apply_terminator_effect`.
280-
fn terminator_effect<'mir>(
281-
&mut self,
282-
trans: &mut Self::Domain,
283-
terminator: &'mir mir::Terminator<'tcx>,
284-
location: Location,
285-
) -> TerminatorEdges<'mir, 'tcx>;
286-
287-
/// See `Analysis::apply_before_terminator_effect`.
288-
fn before_terminator_effect(
289-
&mut self,
290-
_trans: &mut impl GenKill<Self::Idx>,
291-
_terminator: &mir::Terminator<'tcx>,
292-
_location: Location,
293-
) {
294-
}
295-
296-
/* Edge-specific effects */
297-
298-
/// See `Analysis::apply_call_return_effect`.
299-
fn call_return_effect(
300-
&mut self,
301-
trans: &mut impl GenKill<Self::Idx>,
302-
block: BasicBlock,
303-
return_places: CallReturnPlaces<'_, 'tcx>,
304-
);
305-
306-
/// See `Analysis::apply_switch_int_edge_effects`.
307-
fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
308-
&mut self,
309-
_block: BasicBlock,
310-
_discr: &mir::Operand<'tcx>,
311-
_edge_effects: &mut impl SwitchIntEdgeEffects<G>,
312-
) {
313-
}
314280
}
315281

316-
impl<'tcx, A> Analysis<'tcx> for A
317-
where
318-
A: GenKillAnalysis<'tcx>,
319-
A::Domain: GenKill<A::Idx> + BitSetExt<A::Idx>,
320-
{
321-
fn apply_statement_effect(
322-
&mut self,
323-
state: &mut A::Domain,
324-
statement: &mir::Statement<'tcx>,
325-
location: Location,
326-
) {
327-
self.statement_effect(state, statement, location);
328-
}
329-
330-
fn apply_before_statement_effect(
331-
&mut self,
332-
state: &mut A::Domain,
333-
statement: &mir::Statement<'tcx>,
334-
location: Location,
335-
) {
336-
self.before_statement_effect(state, statement, location);
337-
}
338-
339-
fn apply_terminator_effect<'mir>(
340-
&mut self,
341-
state: &mut A::Domain,
342-
terminator: &'mir mir::Terminator<'tcx>,
343-
location: Location,
344-
) -> TerminatorEdges<'mir, 'tcx> {
345-
self.terminator_effect(state, terminator, location)
346-
}
347-
348-
fn apply_before_terminator_effect(
349-
&mut self,
350-
state: &mut A::Domain,
351-
terminator: &mir::Terminator<'tcx>,
352-
location: Location,
353-
) {
354-
self.before_terminator_effect(state, terminator, location);
355-
}
356-
357-
/* Edge-specific effects */
358-
359-
fn apply_call_return_effect(
360-
&mut self,
361-
state: &mut A::Domain,
362-
block: BasicBlock,
363-
return_places: CallReturnPlaces<'_, 'tcx>,
364-
) {
365-
self.call_return_effect(state, block, return_places);
366-
}
367-
368-
fn apply_switch_int_edge_effects(
369-
&mut self,
370-
block: BasicBlock,
371-
discr: &mir::Operand<'tcx>,
372-
edge_effects: &mut impl SwitchIntEdgeEffects<A::Domain>,
373-
) {
374-
self.switch_int_edge_effects(block, discr, edge_effects);
375-
}
282+
/// Use this to define `Analysis::apply_before_statement_effect` in types that
283+
/// impl both `Analysis` and `GenKillAnalysis`. It delegates to
284+
/// `GenKillAnalysis::apply_before_statement_effect`.
285+
#[macro_export]
286+
macro_rules! fn_apply_before_statement_effect_gen_kill {
287+
() => {
288+
fn apply_before_statement_effect(
289+
&mut self,
290+
trans: &mut Self::Domain,
291+
stmt: &rustc_middle::mir::Statement<'tcx>,
292+
location: Location,
293+
) {
294+
self.before_statement_effect(trans, stmt, location);
295+
}
296+
};
297+
}
376298

377-
/* Extension methods */
378-
#[inline]
379-
fn into_engine<'mir>(
380-
self,
381-
tcx: TyCtxt<'tcx>,
382-
body: &'mir mir::Body<'tcx>,
383-
) -> Engine<'mir, 'tcx, Self>
384-
where
385-
Self: Sized,
386-
{
387-
Engine::new_gen_kill(tcx, body, self)
388-
}
299+
/// Use this to define `Analysis::apply_statement_effect` in types that impl
300+
/// both `Analysis` and `GenKillAnalysis`. It just delegates to
301+
/// `GenKillAnalysis::apply_statement_effect`.
302+
#[macro_export]
303+
macro_rules! fn_apply_statement_effect_gen_kill {
304+
() => {
305+
fn apply_statement_effect(
306+
&mut self,
307+
trans: &mut Self::Domain,
308+
stmt: &rustc_middle::mir::Statement<'tcx>,
309+
location: Location,
310+
) {
311+
self.statement_effect(trans, stmt, location);
312+
}
313+
};
389314
}
390315

391316
/// The legal operations for a transfer function in a gen/kill problem.

compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_index::bit_set::BitSet;
22
use rustc_middle::mir::visit::Visitor;
33
use rustc_middle::mir::*;
44

5-
use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
5+
use crate::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis};
66

77
/// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points
88
/// to a given local. This analysis ignores fake borrows, so it should not be used by
@@ -49,8 +49,12 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
4949
) {
5050
self.transfer_function(trans).visit_statement(statement, location);
5151
}
52+
}
53+
54+
impl<'tcx> Analysis<'tcx> for MaybeBorrowedLocals {
55+
crate::fn_apply_statement_effect_gen_kill!();
5256

53-
fn terminator_effect<'mir>(
57+
fn apply_terminator_effect<'mir>(
5458
&mut self,
5559
trans: &mut Self::Domain,
5660
terminator: &'mir Terminator<'tcx>,
@@ -60,9 +64,9 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
6064
terminator.edges()
6165
}
6266

63-
fn call_return_effect(
67+
fn apply_call_return_effect(
6468
&mut self,
65-
_trans: &mut impl GenKill<Self::Idx>,
69+
_trans: &mut Self::Domain,
6670
_block: BasicBlock,
6771
_return_places: CallReturnPlaces<'_, 'tcx>,
6872
) {

0 commit comments

Comments
 (0)