]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/dataflow/impls/mod.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / librustc_mir / dataflow / impls / mod.rs
CommitLineData
041b39d2
XL
1//! Dataflow analyses are built upon some interpretation of the
2//! bitvectors attached to each basic block, represented via a
3//! zero-sized structure.
4
e74abb32
XL
5use rustc_index::bit_set::BitSet;
6use rustc_index::vec::Idx;
ba9703b0
XL
7use rustc_middle::mir::{self, Body, Location};
8use rustc_middle::ty::{self, TyCtxt};
9use rustc_target::abi::VariantIdx;
3157f602 10
041b39d2 11use super::MoveDataParamEnv;
83c7162d 12
9fa01778 13use crate::util::elaborate_drops::DropFlagState;
3157f602 14
74b04a01 15use super::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
ba9703b0 16use super::{AnalysisDomain, BottomValue, GenKill, GenKillAnalysis};
3157f602 17
041b39d2
XL
18use super::drop_flag_effects_for_function_entry;
19use super::drop_flag_effects_for_location;
b7449926 20use super::on_lookup_result_bits;
74b04a01 21use crate::dataflow::drop_flag_effects;
3157f602 22
2c00a5a8 23mod borrowed_locals;
e74abb32 24mod storage_liveness;
2c00a5a8
XL
25
26pub use self::borrowed_locals::*;
e74abb32 27pub use self::storage_liveness::*;
2c00a5a8 28
3b2f2976
XL
29pub(super) mod borrows;
30
2c00a5a8 31/// `MaybeInitializedPlaces` tracks all places that might be
3157f602
XL
32/// initialized upon reaching a particular point in the control flow
33/// for a function.
34///
35/// For example, in code like the following, we have corresponding
36/// dataflow information shown in the right-hand comments.
37///
38/// ```rust
39/// struct S;
40/// fn foo(pred: bool) { // maybe-init:
41/// // {}
42/// let a = S; let b = S; let c; let d; // {a, b}
43///
44/// if pred {
45/// drop(a); // { b}
46/// b = S; // { b}
47///
48/// } else {
49/// drop(b); // {a}
50/// d = S; // {a, d}
51///
52/// } // {a, b, d}
53///
54/// c = S; // {a, b, c, d}
55/// }
56/// ```
57///
2c00a5a8 58/// To determine whether a place *must* be initialized at a
3157f602 59/// particular control-flow point, one can take the set-difference
2c00a5a8 60/// between this data and the data from `MaybeUninitializedPlaces` at the
3157f602
XL
61/// corresponding control-flow point.
62///
63/// Similarly, at a given `drop` statement, the set-intersection
2c00a5a8
XL
64/// between this data and `MaybeUninitializedPlaces` yields the set of
65/// places that would require a dynamic drop-flag at that statement.
dc9dc135
XL
66pub struct MaybeInitializedPlaces<'a, 'tcx> {
67 tcx: TyCtxt<'tcx>,
68 body: &'a Body<'tcx>,
69 mdpe: &'a MoveDataParamEnv<'tcx>,
3157f602
XL
70}
71
dc9dc135
XL
72impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
73 pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
60c5eb7d 74 MaybeInitializedPlaces { tcx, body, mdpe }
3157f602
XL
75 }
76}
77
dc9dc135 78impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
dfeec247
XL
79 fn move_data(&self) -> &MoveData<'tcx> {
80 &self.mdpe.move_data
81 }
32a655c1
SL
82}
83
2c00a5a8 84/// `MaybeUninitializedPlaces` tracks all places that might be
3157f602
XL
85/// uninitialized upon reaching a particular point in the control flow
86/// for a function.
87///
88/// For example, in code like the following, we have corresponding
89/// dataflow information shown in the right-hand comments.
90///
91/// ```rust
92/// struct S;
93/// fn foo(pred: bool) { // maybe-uninit:
94/// // {a, b, c, d}
95/// let a = S; let b = S; let c; let d; // { c, d}
96///
97/// if pred {
98/// drop(a); // {a, c, d}
99/// b = S; // {a, c, d}
100///
101/// } else {
102/// drop(b); // { b, c, d}
103/// d = S; // { b, c }
104///
105/// } // {a, b, c, d}
106///
107/// c = S; // {a, b, d}
108/// }
109/// ```
110///
2c00a5a8 111/// To determine whether a place *must* be uninitialized at a
3157f602 112/// particular control-flow point, one can take the set-difference
2c00a5a8 113/// between this data and the data from `MaybeInitializedPlaces` at the
3157f602
XL
114/// corresponding control-flow point.
115///
116/// Similarly, at a given `drop` statement, the set-intersection
2c00a5a8
XL
117/// between this data and `MaybeInitializedPlaces` yields the set of
118/// places that would require a dynamic drop-flag at that statement.
dc9dc135
XL
119pub struct MaybeUninitializedPlaces<'a, 'tcx> {
120 tcx: TyCtxt<'tcx>,
121 body: &'a Body<'tcx>,
122 mdpe: &'a MoveDataParamEnv<'tcx>,
3157f602
XL
123}
124
dc9dc135
XL
125impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
126 pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
60c5eb7d 127 MaybeUninitializedPlaces { tcx, body, mdpe }
3157f602
XL
128 }
129}
130
dc9dc135 131impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
dfeec247
XL
132 fn move_data(&self) -> &MoveData<'tcx> {
133 &self.mdpe.move_data
134 }
32a655c1
SL
135}
136
2c00a5a8 137/// `DefinitelyInitializedPlaces` tracks all places that are definitely
3157f602
XL
138/// initialized upon reaching a particular point in the control flow
139/// for a function.
140///
3157f602
XL
141/// For example, in code like the following, we have corresponding
142/// dataflow information shown in the right-hand comments.
143///
144/// ```rust
145/// struct S;
146/// fn foo(pred: bool) { // definite-init:
147/// // { }
148/// let a = S; let b = S; let c; let d; // {a, b }
149///
150/// if pred {
151/// drop(a); // { b, }
152/// b = S; // { b, }
153///
154/// } else {
155/// drop(b); // {a, }
156/// d = S; // {a, d}
157///
158/// } // { }
159///
160/// c = S; // { c }
161/// }
162/// ```
163///
2c00a5a8 164/// To determine whether a place *may* be uninitialized at a
3157f602
XL
165/// particular control-flow point, one can take the set-complement
166/// of this data.
167///
168/// Similarly, at a given `drop` statement, the set-difference between
2c00a5a8 169/// this data and `MaybeInitializedPlaces` yields the set of places
3157f602 170/// that would require a dynamic drop-flag at that statement.
dc9dc135
XL
171pub struct DefinitelyInitializedPlaces<'a, 'tcx> {
172 tcx: TyCtxt<'tcx>,
173 body: &'a Body<'tcx>,
174 mdpe: &'a MoveDataParamEnv<'tcx>,
3157f602
XL
175}
176
dc9dc135
XL
177impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
178 pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
60c5eb7d 179 DefinitelyInitializedPlaces { tcx, body, mdpe }
3157f602
XL
180 }
181}
182
dc9dc135 183impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
dfeec247
XL
184 fn move_data(&self) -> &MoveData<'tcx> {
185 &self.mdpe.move_data
186 }
32a655c1
SL
187}
188
2c00a5a8 189/// `EverInitializedPlaces` tracks all places that might have ever been
ff7c6d11
XL
190/// initialized upon reaching a particular point in the control flow
191/// for a function, without an intervening `Storage Dead`.
192///
193/// This dataflow is used to determine if an immutable local variable may
194/// be assigned to.
195///
196/// For example, in code like the following, we have corresponding
197/// dataflow information shown in the right-hand comments.
198///
199/// ```rust
200/// struct S;
201/// fn foo(pred: bool) { // ever-init:
202/// // { }
203/// let a = S; let b = S; let c; let d; // {a, b }
204///
205/// if pred {
206/// drop(a); // {a, b, }
207/// b = S; // {a, b, }
208///
209/// } else {
210/// drop(b); // {a, b, }
211/// d = S; // {a, b, d }
212///
213/// } // {a, b, d }
214///
215/// c = S; // {a, b, c, d }
216/// }
217/// ```
dc9dc135 218pub struct EverInitializedPlaces<'a, 'tcx> {
74b04a01 219 #[allow(dead_code)]
dc9dc135
XL
220 tcx: TyCtxt<'tcx>,
221 body: &'a Body<'tcx>,
222 mdpe: &'a MoveDataParamEnv<'tcx>,
ff7c6d11
XL
223}
224
dc9dc135
XL
225impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
226 pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
60c5eb7d 227 EverInitializedPlaces { tcx, body, mdpe }
ff7c6d11
XL
228 }
229}
230
dc9dc135 231impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'tcx> {
dfeec247
XL
232 fn move_data(&self) -> &MoveData<'tcx> {
233 &self.mdpe.move_data
234 }
ff7c6d11
XL
235}
236
dc9dc135 237impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
dfeec247 238 fn update_bits(
74b04a01 239 trans: &mut impl GenKill<MovePathIndex>,
dfeec247
XL
240 path: MovePathIndex,
241 state: DropFlagState,
242 ) {
3157f602 243 match state {
dc9dc135
XL
244 DropFlagState::Absent => trans.kill(path),
245 DropFlagState::Present => trans.gen(path),
3157f602
XL
246 }
247 }
248}
249
dc9dc135 250impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
dfeec247 251 fn update_bits(
74b04a01 252 trans: &mut impl GenKill<MovePathIndex>,
dfeec247
XL
253 path: MovePathIndex,
254 state: DropFlagState,
255 ) {
3157f602 256 match state {
dc9dc135
XL
257 DropFlagState::Absent => trans.gen(path),
258 DropFlagState::Present => trans.kill(path),
3157f602
XL
259 }
260 }
261}
262
dc9dc135 263impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
dfeec247 264 fn update_bits(
74b04a01 265 trans: &mut impl GenKill<MovePathIndex>,
dfeec247
XL
266 path: MovePathIndex,
267 state: DropFlagState,
268 ) {
3157f602 269 match state {
dc9dc135
XL
270 DropFlagState::Absent => trans.kill(path),
271 DropFlagState::Present => trans.gen(path),
3157f602
XL
272 }
273 }
274}
275
74b04a01 276impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
3157f602 277 type Idx = MovePathIndex;
74b04a01
XL
278
279 const NAME: &'static str = "maybe_init";
280
281 fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
32a655c1 282 self.move_data().move_paths.len()
3157f602
XL
283 }
284
74b04a01 285 fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
dfeec247
XL
286 drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
287 assert!(s == DropFlagState::Present);
74b04a01 288 state.insert(path);
dfeec247
XL
289 });
290 }
291
74b04a01
XL
292 fn pretty_print_idx(&self, w: &mut impl std::io::Write, mpi: Self::Idx) -> std::io::Result<()> {
293 write!(w, "{}", self.move_data().move_paths[mpi])
294 }
295}
296
297impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
298 fn statement_effect(
299 &self,
300 trans: &mut impl GenKill<Self::Idx>,
301 _statement: &mir::Statement<'tcx>,
302 location: Location,
303 ) {
dfeec247
XL
304 drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
305 Self::update_bits(trans, path, s)
306 })
307 }
308
74b04a01
XL
309 fn terminator_effect(
310 &self,
311 trans: &mut impl GenKill<Self::Idx>,
312 _terminator: &mir::Terminator<'tcx>,
313 location: Location,
314 ) {
dfeec247
XL
315 drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
316 Self::update_bits(trans, path, s)
317 })
3157f602
XL
318 }
319
74b04a01 320 fn call_return_effect(
0731742a 321 &self,
74b04a01
XL
322 trans: &mut impl GenKill<Self::Idx>,
323 _block: mir::BasicBlock,
324 _func: &mir::Operand<'tcx>,
325 _args: &[mir::Operand<'tcx>],
ba9703b0 326 dest_place: mir::Place<'tcx>,
0731742a 327 ) {
3157f602 328 // when a call returns successfully, that means we need to set
ff7c6d11 329 // the bits for that dest_place to 1 (initialized).
dfeec247
XL
330 on_lookup_result_bits(
331 self.tcx,
332 self.body,
333 self.move_data(),
334 self.move_data().rev_lookup.find(dest_place.as_ref()),
335 |mpi| {
74b04a01 336 trans.gen(mpi);
dfeec247
XL
337 },
338 );
3157f602 339 }
74b04a01
XL
340
341 fn discriminant_switch_effect(
342 &self,
343 trans: &mut impl GenKill<Self::Idx>,
344 _block: mir::BasicBlock,
ba9703b0 345 enum_place: mir::Place<'tcx>,
74b04a01
XL
346 _adt: &ty::AdtDef,
347 variant: VariantIdx,
348 ) {
349 let enum_mpi = match self.move_data().rev_lookup.find(enum_place.as_ref()) {
350 LookupResult::Exact(mpi) => mpi,
351 LookupResult::Parent(_) => return,
352 };
353
354 // Kill all move paths that correspond to variants other than this one
355 let move_paths = &self.move_data().move_paths;
356 let enum_path = &move_paths[enum_mpi];
357 for (mpi, variant_path) in enum_path.children(move_paths) {
358 trans.kill(mpi);
359 match variant_path.place.projection.last().unwrap() {
360 mir::ProjectionElem::Downcast(_, idx) if *idx == variant => continue,
361 _ => drop_flag_effects::on_all_children_bits(
362 self.tcx,
363 self.body,
364 self.move_data(),
365 mpi,
366 |mpi| trans.kill(mpi),
367 ),
368 }
369 }
370 }
3157f602
XL
371}
372
74b04a01 373impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
3157f602 374 type Idx = MovePathIndex;
74b04a01
XL
375
376 const NAME: &'static str = "maybe_uninit";
377
378 fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
32a655c1 379 self.move_data().move_paths.len()
3157f602
XL
380 }
381
ff7c6d11 382 // sets on_entry bits for Arg places
74b04a01 383 fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
3157f602 384 // set all bits to 1 (uninit) before gathering counterevidence
74b04a01
XL
385 assert!(self.bits_per_block(body) == state.domain_size());
386 state.insert_all();
3157f602 387
dfeec247
XL
388 drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
389 assert!(s == DropFlagState::Present);
74b04a01 390 state.remove(path);
dfeec247 391 });
3157f602
XL
392 }
393
74b04a01
XL
394 fn pretty_print_idx(&self, w: &mut impl std::io::Write, mpi: Self::Idx) -> std::io::Result<()> {
395 write!(w, "{}", self.move_data().move_paths[mpi])
396 }
397}
398
399impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
400 fn statement_effect(
401 &self,
402 trans: &mut impl GenKill<Self::Idx>,
403 _statement: &mir::Statement<'tcx>,
404 location: Location,
405 ) {
dfeec247
XL
406 drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
407 Self::update_bits(trans, path, s)
408 })
3157f602
XL
409 }
410
74b04a01
XL
411 fn terminator_effect(
412 &self,
413 trans: &mut impl GenKill<Self::Idx>,
414 _terminator: &mir::Terminator<'tcx>,
415 location: Location,
416 ) {
dfeec247
XL
417 drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
418 Self::update_bits(trans, path, s)
419 })
3157f602
XL
420 }
421
74b04a01 422 fn call_return_effect(
0731742a 423 &self,
74b04a01
XL
424 trans: &mut impl GenKill<Self::Idx>,
425 _block: mir::BasicBlock,
426 _func: &mir::Operand<'tcx>,
427 _args: &[mir::Operand<'tcx>],
ba9703b0 428 dest_place: mir::Place<'tcx>,
0731742a 429 ) {
3157f602 430 // when a call returns successfully, that means we need to set
ff7c6d11 431 // the bits for that dest_place to 0 (initialized).
dfeec247
XL
432 on_lookup_result_bits(
433 self.tcx,
434 self.body,
435 self.move_data(),
436 self.move_data().rev_lookup.find(dest_place.as_ref()),
437 |mpi| {
74b04a01 438 trans.kill(mpi);
dfeec247
XL
439 },
440 );
3157f602
XL
441 }
442}
443
74b04a01 444impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
3157f602 445 type Idx = MovePathIndex;
74b04a01
XL
446
447 const NAME: &'static str = "definite_init";
448
449 fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
32a655c1 450 self.move_data().move_paths.len()
3157f602
XL
451 }
452
ff7c6d11 453 // sets on_entry bits for Arg places
74b04a01
XL
454 fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
455 state.clear();
3157f602 456
dfeec247
XL
457 drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
458 assert!(s == DropFlagState::Present);
74b04a01 459 state.insert(path);
dfeec247 460 });
3157f602
XL
461 }
462
74b04a01
XL
463 fn pretty_print_idx(&self, w: &mut impl std::io::Write, mpi: Self::Idx) -> std::io::Result<()> {
464 write!(w, "{}", self.move_data().move_paths[mpi])
465 }
466}
467
468impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
469 fn statement_effect(
470 &self,
471 trans: &mut impl GenKill<Self::Idx>,
472 _statement: &mir::Statement<'tcx>,
473 location: Location,
474 ) {
dfeec247
XL
475 drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
476 Self::update_bits(trans, path, s)
477 })
3157f602
XL
478 }
479
74b04a01
XL
480 fn terminator_effect(
481 &self,
482 trans: &mut impl GenKill<Self::Idx>,
483 _terminator: &mir::Terminator<'tcx>,
484 location: Location,
485 ) {
dfeec247
XL
486 drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
487 Self::update_bits(trans, path, s)
488 })
3157f602
XL
489 }
490
74b04a01 491 fn call_return_effect(
0731742a 492 &self,
74b04a01
XL
493 trans: &mut impl GenKill<Self::Idx>,
494 _block: mir::BasicBlock,
495 _func: &mir::Operand<'tcx>,
496 _args: &[mir::Operand<'tcx>],
ba9703b0 497 dest_place: mir::Place<'tcx>,
0731742a 498 ) {
3157f602 499 // when a call returns successfully, that means we need to set
ff7c6d11 500 // the bits for that dest_place to 1 (initialized).
dfeec247
XL
501 on_lookup_result_bits(
502 self.tcx,
503 self.body,
504 self.move_data(),
505 self.move_data().rev_lookup.find(dest_place.as_ref()),
506 |mpi| {
74b04a01 507 trans.gen(mpi);
dfeec247
XL
508 },
509 );
3157f602
XL
510 }
511}
512
74b04a01 513impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
ff7c6d11 514 type Idx = InitIndex;
74b04a01
XL
515
516 const NAME: &'static str = "ever_init";
517
518 fn bits_per_block(&self, _: &mir::Body<'tcx>) -> usize {
ff7c6d11
XL
519 self.move_data().inits.len()
520 }
abe05a73 521
74b04a01
XL
522 fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>) {
523 for arg_init in 0..body.arg_count {
524 state.insert(InitIndex::new(arg_init));
ff7c6d11
XL
525 }
526 }
74b04a01 527}
ff7c6d11 528
74b04a01
XL
529impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
530 fn statement_effect(
531 &self,
532 trans: &mut impl GenKill<Self::Idx>,
533 stmt: &mir::Statement<'tcx>,
534 location: Location,
535 ) {
536 let move_data = self.move_data();
ff7c6d11
XL
537 let init_path_map = &move_data.init_path_map;
538 let init_loc_map = &move_data.init_loc_map;
539 let rev_lookup = &move_data.rev_lookup;
540
dfeec247
XL
541 debug!(
542 "statement {:?} at loc {:?} initializes move_indexes {:?}",
543 stmt, location, &init_loc_map[location]
544 );
74b04a01 545 trans.gen_all(init_loc_map[location].iter().copied());
ff7c6d11 546
ba9703b0
XL
547 if let mir::StatementKind::StorageDead(local) = stmt.kind {
548 // End inits for StorageDead, so that an immutable variable can
549 // be reinitialized on the next iteration of the loop.
550 let move_path_index = rev_lookup.find_local(local);
551 debug!(
552 "stmt {:?} at loc {:?} clears the ever initialized status of {:?}",
553 stmt, location, &init_path_map[move_path_index]
554 );
555 trans.kill_all(init_path_map[move_path_index].iter().copied());
ff7c6d11
XL
556 }
557 }
558
74b04a01
XL
559 fn terminator_effect(
560 &self,
561 trans: &mut impl GenKill<Self::Idx>,
562 _terminator: &mir::Terminator<'tcx>,
563 location: Location,
564 ) {
dc9dc135
XL
565 let (body, move_data) = (self.body, self.move_data());
566 let term = body[location.block].terminator();
ff7c6d11 567 let init_loc_map = &move_data.init_loc_map;
dfeec247
XL
568 debug!(
569 "terminator {:?} at loc {:?} initializes move_indexes {:?}",
570 term, location, &init_loc_map[location]
571 );
dc9dc135 572 trans.gen_all(
74b04a01
XL
573 init_loc_map[location]
574 .iter()
575 .filter(|init_index| {
576 move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly
577 })
578 .copied(),
ff7c6d11
XL
579 );
580 }
581
74b04a01 582 fn call_return_effect(
0731742a 583 &self,
74b04a01
XL
584 trans: &mut impl GenKill<Self::Idx>,
585 block: mir::BasicBlock,
586 _func: &mir::Operand<'tcx>,
587 _args: &[mir::Operand<'tcx>],
ba9703b0 588 _dest_place: mir::Place<'tcx>,
0731742a 589 ) {
ff7c6d11 590 let move_data = self.move_data();
ff7c6d11
XL
591 let init_loc_map = &move_data.init_loc_map;
592
74b04a01 593 let call_loc = self.body.terminator_loc(block);
ff7c6d11 594 for init_index in &init_loc_map[call_loc] {
74b04a01 595 trans.gen(*init_index);
ff7c6d11
XL
596 }
597 }
598}
abe05a73 599
dc9dc135
XL
600impl<'a, 'tcx> BottomValue for MaybeInitializedPlaces<'a, 'tcx> {
601 /// bottom = uninitialized
602 const BOTTOM_VALUE: bool = false;
3157f602
XL
603}
604
dc9dc135
XL
605impl<'a, 'tcx> BottomValue for MaybeUninitializedPlaces<'a, 'tcx> {
606 /// bottom = initialized (start_block_effect counters this at outset)
607 const BOTTOM_VALUE: bool = false;
3157f602
XL
608}
609
dc9dc135
XL
610impl<'a, 'tcx> BottomValue for DefinitelyInitializedPlaces<'a, 'tcx> {
611 /// bottom = initialized (start_block_effect counters this at outset)
612 const BOTTOM_VALUE: bool = true;
ff7c6d11
XL
613}
614
dc9dc135
XL
615impl<'a, 'tcx> BottomValue for EverInitializedPlaces<'a, 'tcx> {
616 /// bottom = no initialized variables by default
617 const BOTTOM_VALUE: bool = false;
ff7c6d11 618}