|
1 | 1 | use rustc::ty; |
2 | 2 | use rustc_ast::ast::{self, MetaItem}; |
3 | | -use rustc_index::bit_set::BitSet; |
4 | | -use rustc_index::vec::Idx; |
5 | 3 | use rustc_span::symbol::{sym, Symbol}; |
6 | 4 |
|
7 | 5 | pub(crate) use self::drop_flag_effects::*; |
8 | 6 | pub use self::framework::{ |
9 | | - visit_results, Analysis, AnalysisDomain, BorrowckFlowState, BorrowckResults, Engine, GenKill, |
10 | | - GenKillAnalysis, Results, ResultsCursor, ResultsRefCursor, ResultsVisitor, |
| 7 | + visit_results, Analysis, AnalysisDomain, BorrowckFlowState, BorrowckResults, BottomValue, |
| 8 | + Engine, GenKill, GenKillAnalysis, Results, ResultsCursor, ResultsRefCursor, ResultsVisitor, |
11 | 9 | }; |
12 | 10 | pub use self::impls::{ |
13 | 11 | borrows::Borrows, DefinitelyInitializedPlaces, EverInitializedPlaces, MaybeBorrowedLocals, |
@@ -48,44 +46,3 @@ pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: Symbol) -> Opti |
48 | 46 | } |
49 | 47 | None |
50 | 48 | } |
51 | | - |
52 | | -/// Parameterization for the precise form of data flow that is used. |
53 | | -/// |
54 | | -/// `BottomValue` determines whether the initial entry set for each basic block is empty or full. |
55 | | -/// This also determines the semantics of the lattice `join` operator used to merge dataflow |
56 | | -/// results, since dataflow works by starting at the bottom and moving monotonically to a fixed |
57 | | -/// point. |
58 | | -/// |
59 | | -/// This means, for propagation across the graph, that you either want to start at all-zeroes and |
60 | | -/// then use Union as your merge when propagating, or you start at all-ones and then use Intersect |
61 | | -/// as your merge when propagating. |
62 | | -pub trait BottomValue { |
63 | | - /// Specifies the initial value for each bit in the entry set for each basic block. |
64 | | - const BOTTOM_VALUE: bool; |
65 | | - |
66 | | - /// Merges `in_set` into `inout_set`, returning `true` if `inout_set` changed. |
67 | | - /// |
68 | | - /// It is almost certainly wrong to override this, since it automatically applies |
69 | | - /// * `inout_set & in_set` if `BOTTOM_VALUE == true` |
70 | | - /// * `inout_set | in_set` if `BOTTOM_VALUE == false` |
71 | | - /// |
72 | | - /// This means that if a bit is not `BOTTOM_VALUE`, it is propagated into all target blocks. |
73 | | - /// For clarity, the above statement again from a different perspective: |
74 | | - /// A bit in the block's entry set is `!BOTTOM_VALUE` if *any* predecessor block's bit value is |
75 | | - /// `!BOTTOM_VALUE`. |
76 | | - /// |
77 | | - /// There are situations where you want the opposite behaviour: propagate only if *all* |
78 | | - /// predecessor blocks's value is `!BOTTOM_VALUE`. |
79 | | - /// E.g. if you want to know whether a bit is *definitely* set at a specific location. This |
80 | | - /// means that all code paths leading to the location must have set the bit, instead of any |
81 | | - /// code path leading there. |
82 | | - /// |
83 | | - /// If you want this kind of "definitely set" analysis, you need to |
84 | | - /// 1. Invert `BOTTOM_VALUE` |
85 | | - /// 2. Reset the `entry_set` in `start_block_effect` to `!BOTTOM_VALUE` |
86 | | - /// 3. Override `join` to do the opposite from what it's doing now. |
87 | | - #[inline] |
88 | | - fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool { |
89 | | - if !Self::BOTTOM_VALUE { inout_set.union(in_set) } else { inout_set.intersect(in_set) } |
90 | | - } |
91 | | -} |
0 commit comments