1 //! A less precise version of `MaybeInitializedPlaces` whose domain is entire locals.
3 //! A local will be maybe initialized if *any* projections of that local might be initialized.
5 use crate::dataflow
::{self, BottomValue, GenKill}
;
7 use rustc_index
::bit_set
::BitSet
;
8 use rustc_middle
::mir
::visit
::{PlaceContext, Visitor}
;
9 use rustc_middle
::mir
::{self, BasicBlock, Local, Location}
;
11 pub struct MaybeInitializedLocals
;
13 impl BottomValue
for MaybeInitializedLocals
{
15 const BOTTOM_VALUE
: bool
= false;
18 impl dataflow
::AnalysisDomain
<'tcx
> for MaybeInitializedLocals
{
21 const NAME
: &'
static str = "maybe_init_locals";
23 fn bits_per_block(&self, body
: &mir
::Body
<'tcx
>) -> usize {
24 body
.local_decls
.len()
27 fn initialize_start_block(&self, body
: &mir
::Body
<'tcx
>, entry_set
: &mut BitSet
<Self::Idx
>) {
28 // Function arguments are initialized to begin with.
29 for arg
in body
.args_iter() {
30 entry_set
.insert(arg
);
35 impl dataflow
::GenKillAnalysis
<'tcx
> for MaybeInitializedLocals
{
38 trans
: &mut impl GenKill
<Self::Idx
>,
39 statement
: &mir
::Statement
<'tcx
>,
42 TransferFunction { trans }
.visit_statement(statement
, loc
)
47 trans
: &mut impl GenKill
<Self::Idx
>,
48 terminator
: &mir
::Terminator
<'tcx
>,
51 TransferFunction { trans }
.visit_terminator(terminator
, loc
)
54 fn call_return_effect(
56 trans
: &mut impl GenKill
<Self::Idx
>,
58 _func
: &mir
::Operand
<'tcx
>,
59 _args
: &[mir
::Operand
<'tcx
>],
60 return_place
: mir
::Place
<'tcx
>,
62 trans
.gen(return_place
.local
)
65 /// See `Analysis::apply_yield_resume_effect`.
66 fn yield_resume_effect(
68 trans
: &mut impl GenKill
<Self::Idx
>,
69 _resume_block
: BasicBlock
,
70 resume_place
: mir
::Place
<'tcx
>,
72 trans
.gen(resume_place
.local
)
76 struct TransferFunction
<'a
, T
> {
80 impl<T
> Visitor
<'tcx
> for TransferFunction
<'a
, T
>
84 fn visit_local(&mut self, &local
: &Local
, context
: PlaceContext
, _
: Location
) {
85 use rustc_middle
::mir
::visit
::{MutatingUseContext, NonMutatingUseContext, NonUseContext}
;
87 // These are handled specially in `call_return_effect` and `yield_resume_effect`.
88 PlaceContext
::MutatingUse(MutatingUseContext
::Call
| MutatingUseContext
::Yield
) => {}
90 // Otherwise, when a place is mutated, we must consider it possibly initialized.
91 PlaceContext
::MutatingUse(_
) => self.trans
.gen(local
),
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
),
98 // All other uses do not affect this analysis.
100 NonUseContext
::StorageLive
101 | NonUseContext
::AscribeUserTy
102 | NonUseContext
::Coverage
103 | NonUseContext
::VarDebugInfo
,
105 | PlaceContext
::NonMutatingUse(
106 NonMutatingUseContext
::Inspect
107 | NonMutatingUseContext
::Copy
108 | NonMutatingUseContext
::SharedBorrow
109 | NonMutatingUseContext
::ShallowBorrow
110 | NonMutatingUseContext
::UniqueBorrow
111 | NonMutatingUseContext
::AddressOf
112 | NonMutatingUseContext
::Projection
,