]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_mir_dataflow/src/impls/init_locals.rs
83ce4c44b7144e5cfa97c5d5c67feb5f55364396
[rustc.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 // FIXME: Using `visit_local` here is a bug. For example, on `move _5.field` we mark `_5` as
81 // deinitialized, although clearly it is only partially deinitialized. This analysis is not
82 // actually used anywhere at the moment, so this is not critical, but this does need to be fixed
83 // before it starts being used again.
84 fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
85 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext};
86 match context {
87 // These are handled specially in `call_return_effect` and `yield_resume_effect`.
88 PlaceContext::MutatingUse(
89 MutatingUseContext::Call
90 | MutatingUseContext::AsmOutput
91 | MutatingUseContext::Yield,
92 ) => {}
93
94 // If it's deinitialized, it's no longer init
95 PlaceContext::MutatingUse(MutatingUseContext::Deinit) => self.trans.kill(local),
96
97 // Otherwise, when a place is mutated, we must consider it possibly initialized.
98 PlaceContext::MutatingUse(_) => self.trans.gen(local),
99
100 // If the local is moved out of, or if it gets marked `StorageDead`, consider it no
101 // longer initialized.
102 PlaceContext::NonUse(NonUseContext::StorageDead)
103 | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => self.trans.kill(local),
104
105 // All other uses do not affect this analysis.
106 PlaceContext::NonUse(
107 NonUseContext::StorageLive
108 | NonUseContext::AscribeUserTy
109 | NonUseContext::VarDebugInfo,
110 )
111 | PlaceContext::NonMutatingUse(
112 NonMutatingUseContext::Inspect
113 | NonMutatingUseContext::Copy
114 | NonMutatingUseContext::SharedBorrow
115 | NonMutatingUseContext::ShallowBorrow
116 | NonMutatingUseContext::UniqueBorrow
117 | NonMutatingUseContext::AddressOf
118 | NonMutatingUseContext::Projection,
119 ) => {}
120 }
121 }
122 }