]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_mir_dataflow/src/impls/init_locals.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / compiler / rustc_mir_dataflow / src / impls / init_locals.rs
CommitLineData
f035d41b
XL
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
c295e0f8 5use crate::GenKill;
f035d41b
XL
6
7use rustc_index::bit_set::BitSet;
8use rustc_middle::mir::visit::{PlaceContext, Visitor};
9use rustc_middle::mir::{self, BasicBlock, Local, Location};
10
11pub struct MaybeInitializedLocals;
12
c295e0f8 13impl crate::AnalysisDomain<'tcx> for MaybeInitializedLocals {
1b1a35ee 14 type Domain = BitSet<Local>;
f035d41b
XL
15
16 const NAME: &'static str = "maybe_init_locals";
17
1b1a35ee
XL
18 fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
19 // bottom = uninit
20 BitSet::new_empty(body.local_decls.len())
f035d41b
XL
21 }
22
1b1a35ee 23 fn initialize_start_block(&self, body: &mir::Body<'tcx>, entry_set: &mut Self::Domain) {
f035d41b
XL
24 // Function arguments are initialized to begin with.
25 for arg in body.args_iter() {
26 entry_set.insert(arg);
27 }
28 }
29}
30
c295e0f8 31impl crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals {
1b1a35ee
XL
32 type Idx = Local;
33
f035d41b
XL
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 _func: &mir::Operand<'tcx>,
57 _args: &[mir::Operand<'tcx>],
58 return_place: mir::Place<'tcx>,
59 ) {
60 trans.gen(return_place.local)
61 }
62
63 /// See `Analysis::apply_yield_resume_effect`.
64 fn yield_resume_effect(
65 &self,
66 trans: &mut impl GenKill<Self::Idx>,
67 _resume_block: BasicBlock,
68 resume_place: mir::Place<'tcx>,
69 ) {
70 trans.gen(resume_place.local)
71 }
72}
73
74struct TransferFunction<'a, T> {
75 trans: &'a mut T,
76}
77
78impl<T> Visitor<'tcx> for TransferFunction<'a, T>
79where
80 T: GenKill<Local>,
81{
82 fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
83 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext};
84 match context {
85 // These are handled specially in `call_return_effect` and `yield_resume_effect`.
86 PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => {}
87
88 // Otherwise, when a place is mutated, we must consider it possibly initialized.
89 PlaceContext::MutatingUse(_) => self.trans.gen(local),
90
91 // If the local is moved out of, or if it gets marked `StorageDead`, consider it no
92 // longer initialized.
93 PlaceContext::NonUse(NonUseContext::StorageDead)
94 | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => self.trans.kill(local),
95
96 // All other uses do not affect this analysis.
97 PlaceContext::NonUse(
98 NonUseContext::StorageLive
99 | NonUseContext::AscribeUserTy
100 | NonUseContext::VarDebugInfo,
101 )
102 | PlaceContext::NonMutatingUse(
103 NonMutatingUseContext::Inspect
104 | NonMutatingUseContext::Copy
105 | NonMutatingUseContext::SharedBorrow
106 | NonMutatingUseContext::ShallowBorrow
107 | NonMutatingUseContext::UniqueBorrow
108 | NonMutatingUseContext::AddressOf
109 | NonMutatingUseContext::Projection,
110 ) => {}
111 }
112 }
113}