]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_dataflow/src/impls/init_locals.rs
Remove `in_band_lifetimes` from `rustc_mir_dataflow`
[rust.git] / compiler / rustc_mir_dataflow / src / impls / init_locals.rs
1 //! A less precise version of `MaybeInitializedPlaces` whose domain is entire locals.
2 //!
3 //! A local will be maybe initialized if *any* projections of that local might be initialized.
4
5 use crate::{CallReturnPlaces, GenKill};
6
7 use rustc_index::bit_set::BitSet;
8 use rustc_middle::mir::visit::{PlaceContext, Visitor};
9 use rustc_middle::mir::{self, BasicBlock, Local, Location};
10
11 pub struct MaybeInitializedLocals;
12
13 impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeInitializedLocals {
14     type Domain = BitSet<Local>;
15
16     const NAME: &'static str = "maybe_init_locals";
17
18     fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
19         // bottom = uninit
20         BitSet::new_empty(body.local_decls.len())
21     }
22
23     fn initialize_start_block(&self, body: &mir::Body<'tcx>, entry_set: &mut Self::Domain) {
24         // Function arguments are initialized to begin with.
25         for arg in body.args_iter() {
26             entry_set.insert(arg);
27         }
28     }
29 }
30
31 impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals {
32     type Idx = Local;
33
34     fn statement_effect(
35         &self,
36         trans: &mut impl GenKill<Self::Idx>,
37         statement: &mir::Statement<'tcx>,
38         loc: Location,
39     ) {
40         TransferFunction { trans }.visit_statement(statement, loc)
41     }
42
43     fn terminator_effect(
44         &self,
45         trans: &mut impl GenKill<Self::Idx>,
46         terminator: &mir::Terminator<'tcx>,
47         loc: Location,
48     ) {
49         TransferFunction { trans }.visit_terminator(terminator, loc)
50     }
51
52     fn call_return_effect(
53         &self,
54         trans: &mut impl GenKill<Self::Idx>,
55         _block: BasicBlock,
56         return_places: CallReturnPlaces<'_, 'tcx>,
57     ) {
58         return_places.for_each(|place| trans.gen(place.local));
59     }
60
61     /// See `Analysis::apply_yield_resume_effect`.
62     fn yield_resume_effect(
63         &self,
64         trans: &mut impl GenKill<Self::Idx>,
65         _resume_block: BasicBlock,
66         resume_place: mir::Place<'tcx>,
67     ) {
68         trans.gen(resume_place.local)
69     }
70 }
71
72 struct TransferFunction<'a, T> {
73     trans: &'a mut T,
74 }
75
76 impl<T> Visitor<'_> for TransferFunction<'_, T>
77 where
78     T: GenKill<Local>,
79 {
80     fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
81         use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext};
82         match context {
83             // These are handled specially in `call_return_effect` and `yield_resume_effect`.
84             PlaceContext::MutatingUse(
85                 MutatingUseContext::Call
86                 | MutatingUseContext::AsmOutput
87                 | MutatingUseContext::Yield,
88             ) => {}
89
90             // Otherwise, when a place is mutated, we must consider it possibly initialized.
91             PlaceContext::MutatingUse(_) => self.trans.gen(local),
92
93             // If the local is moved out of, or if it gets marked `StorageDead`, consider it no
94             // longer initialized.
95             PlaceContext::NonUse(NonUseContext::StorageDead)
96             | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => self.trans.kill(local),
97
98             // All other uses do not affect this analysis.
99             PlaceContext::NonUse(
100                 NonUseContext::StorageLive
101                 | NonUseContext::AscribeUserTy
102                 | NonUseContext::VarDebugInfo,
103             )
104             | PlaceContext::NonMutatingUse(
105                 NonMutatingUseContext::Inspect
106                 | NonMutatingUseContext::Copy
107                 | NonMutatingUseContext::SharedBorrow
108                 | NonMutatingUseContext::ShallowBorrow
109                 | NonMutatingUseContext::UniqueBorrow
110                 | NonMutatingUseContext::AddressOf
111                 | NonMutatingUseContext::Projection,
112             ) => {}
113         }
114     }
115 }