|
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