]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_mir_dataflow/src/move_paths/builder.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_mir_dataflow / src / move_paths / builder.rs
CommitLineData
064997fb
FG
1use crate::move_paths::FxHashMap;
2use crate::un_derefer::UnDerefer;
e74abb32 3use rustc_index::vec::IndexVec;
ba9703b0
XL
4use rustc_middle::mir::tcx::RvalueInitializationState;
5use rustc_middle::mir::*;
6use rustc_middle::ty::{self, TyCtxt};
e1599b0c 7use smallvec::{smallvec, SmallVec};
3b2f2976 8
3b2f2976
XL
9use std::mem;
10
11use super::abs_domain::Lift;
ea8adc8c 12use super::IllegalMoveOriginKind::*;
e1599b0c
XL
13use super::{Init, InitIndex, InitKind, InitLocation, LookupResult, MoveError};
14use super::{
15 LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup,
16};
3b2f2976 17
dc9dc135
XL
18struct MoveDataBuilder<'a, 'tcx> {
19 body: &'a Body<'tcx>,
20 tcx: TyCtxt<'tcx>,
60c5eb7d 21 param_env: ty::ParamEnv<'tcx>,
3b2f2976 22 data: MoveData<'tcx>,
b7449926 23 errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
064997fb 24 un_derefer: UnDerefer<'tcx>,
3b2f2976
XL
25}
26
dc9dc135 27impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
60c5eb7d 28 fn new(body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
3b2f2976
XL
29 let mut move_paths = IndexVec::new();
30 let mut path_map = IndexVec::new();
ff7c6d11 31 let mut init_path_map = IndexVec::new();
3b2f2976
XL
32
33 MoveDataBuilder {
dc9dc135 34 body,
3b2f2976 35 tcx,
60c5eb7d 36 param_env,
ea8adc8c 37 errors: Vec::new(),
064997fb 38 un_derefer: UnDerefer { tcx: tcx, derefer_sidetable: Default::default() },
3b2f2976
XL
39 data: MoveData {
40 moves: IndexVec::new(),
dc9dc135 41 loc_map: LocationMap::new(body),
3b2f2976 42 rev_lookup: MovePathLookup {
e1599b0c
XL
43 locals: body
44 .local_decls
45 .indices()
46 .map(|i| {
47 Self::new_move_path(
48 &mut move_paths,
49 &mut path_map,
50 &mut init_path_map,
51 None,
52 Place::from(i),
53 )
54 })
55 .collect(),
0bf4aa26 56 projections: Default::default(),
3b2f2976
XL
57 },
58 move_paths,
59 path_map,
ff7c6d11 60 inits: IndexVec::new(),
dc9dc135 61 init_loc_map: LocationMap::new(body),
ff7c6d11 62 init_path_map,
e1599b0c 63 },
3b2f2976
XL
64 }
65 }
66
e1599b0c
XL
67 fn new_move_path(
68 move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
69 path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
70 init_path_map: &mut IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>,
71 parent: Option<MovePathIndex>,
72 place: Place<'tcx>,
73 ) -> MovePathIndex {
74 let move_path =
75 move_paths.push(MovePath { next_sibling: None, first_child: None, parent, place });
3b2f2976
XL
76
77 if let Some(parent) = parent {
e1599b0c 78 let next_sibling = mem::replace(&mut move_paths[parent].first_child, Some(move_path));
3b2f2976
XL
79 move_paths[move_path].next_sibling = next_sibling;
80 }
81
a1dfa0c6 82 let path_map_ent = path_map.push(smallvec![]);
3b2f2976 83 assert_eq!(path_map_ent, move_path);
ff7c6d11 84
a1dfa0c6 85 let init_path_map_ent = init_path_map.push(smallvec![]);
ff7c6d11
XL
86 assert_eq!(init_path_map_ent, move_path);
87
3b2f2976
XL
88 move_path
89 }
ea8adc8c 90}
3b2f2976 91
dc9dc135 92impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
ff7c6d11
XL
93 /// This creates a MovePath for a given place, returning an `MovePathError`
94 /// if that place can't be moved from.
3b2f2976 95 ///
ff7c6d11 96 /// NOTE: places behind references *do not* get a move path, which is
3b2f2976
XL
97 /// problematic for borrowck.
98 ///
99 /// Maybe we should have separate "borrowck" and "moveck" modes.
ba9703b0 100 fn move_path_for(&mut self, place: Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
064997fb
FG
101 if let Some(new_place) = self.builder.un_derefer.derefer(place.as_ref(), self.builder.body)
102 {
103 return self.move_path_for(new_place);
104 }
105
ff7c6d11 106 debug!("lookup({:?})", place);
dfeec247 107 let mut base = self.builder.data.rev_lookup.locals[place.local];
dc9dc135 108
60c5eb7d
XL
109 // The move path index of the first union that we find. Once this is
110 // some we stop creating child move paths, since moves from unions
111 // move the whole thing.
112 // We continue looking for other move errors though so that moving
113 // from `*(u.f: &_)` isn't allowed.
114 let mut union_path = None;
115
e1599b0c
XL
116 for (i, elem) in place.projection.iter().enumerate() {
117 let proj_base = &place.projection[..i];
118 let body = self.builder.body;
119 let tcx = self.builder.tcx;
74b04a01 120 let place_ty = Place::ty_from(place.local, proj_base, body, tcx).ty;
1b1a35ee 121 match place_ty.kind() {
e1599b0c 122 ty::Ref(..) | ty::RawPtr(..) => {
dfeec247 123 let proj = &place.projection[..i + 1];
e1599b0c
XL
124 return Err(MoveError::cannot_move_out_of(
125 self.loc,
126 BorrowedContent {
127 target_place: Place {
dfeec247 128 local: place.local,
9ffffee4 129 projection: tcx.mk_place_elems(proj),
e1599b0c
XL
130 },
131 },
132 ));
133 }
134 ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
135 return Err(MoveError::cannot_move_out_of(
136 self.loc,
137 InteriorOfTypeWithDestructor { container_ty: place_ty },
138 ));
139 }
e1599b0c 140 ty::Adt(adt, _) if adt.is_union() => {
60c5eb7d 141 union_path.get_or_insert(base);
e1599b0c
XL
142 }
143 ty::Slice(_) => {
144 return Err(MoveError::cannot_move_out_of(
145 self.loc,
146 InteriorOfSliceOrArray {
147 ty: place_ty,
17df50a5 148 is_index: matches!(elem, ProjectionElem::Index(..)),
e1599b0c
XL
149 },
150 ));
151 }
ba9703b0
XL
152
153 ty::Array(..) => {
154 if let ProjectionElem::Index(..) = elem {
dc9dc135
XL
155 return Err(MoveError::cannot_move_out_of(
156 self.loc,
e1599b0c
XL
157 InteriorOfSliceOrArray { ty: place_ty, is_index: true },
158 ));
159 }
ba9703b0
XL
160 }
161
e1599b0c
XL
162 _ => {}
163 };
dc9dc135 164
60c5eb7d 165 if union_path.is_none() {
dfeec247
XL
166 base = self.add_move_path(base, elem, |tcx| Place {
167 local: place.local,
9ffffee4 168 projection: tcx.mk_place_elems(&place.projection[..i + 1]),
60c5eb7d
XL
169 });
170 }
e1599b0c 171 }
dc9dc135 172
60c5eb7d
XL
173 if let Some(base) = union_path {
174 // Move out of union - always move the entire union.
175 Err(MoveError::UnionMove { path: base })
176 } else {
177 Ok(base)
178 }
179 }
180
181 fn add_move_path(
182 &mut self,
183 base: MovePathIndex,
f9f354fc 184 elem: PlaceElem<'tcx>,
60c5eb7d
XL
185 mk_place: impl FnOnce(TyCtxt<'tcx>) -> Place<'tcx>,
186 ) -> MovePathIndex {
187 let MoveDataBuilder {
188 data: MoveData { rev_lookup, move_paths, path_map, init_path_map, .. },
189 tcx,
190 ..
191 } = self.builder;
dfeec247 192 *rev_lookup.projections.entry((base, elem.lift())).or_insert_with(move || {
ba9703b0 193 MoveDataBuilder::new_move_path(
dfeec247
XL
194 move_paths,
195 path_map,
196 init_path_map,
197 Some(base),
198 mk_place(*tcx),
ba9703b0 199 )
dfeec247 200 })
3b2f2976
XL
201 }
202
ba9703b0 203 fn create_move_path(&mut self, place: Place<'tcx>) {
94b46f34
XL
204 // This is an non-moving access (such as an overwrite or
205 // drop), so this not being a valid move path is OK.
ff7c6d11 206 let _ = self.move_path_for(place);
3b2f2976 207 }
ea8adc8c 208}
3b2f2976 209
064997fb
FG
210pub type MoveDat<'tcx> = Result<
211 (FxHashMap<Local, Place<'tcx>>, MoveData<'tcx>),
212 (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>),
213>;
214
dc9dc135 215impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
064997fb 216 fn finalize(self) -> MoveDat<'tcx> {
3b2f2976 217 debug!("{}", {
dc9dc135 218 debug!("moves for {:?}:", self.body.span);
3b2f2976
XL
219 for (j, mo) in self.data.moves.iter_enumerated() {
220 debug!(" {:?} = {:?}", j, mo);
221 }
dc9dc135 222 debug!("move paths for {:?}:", self.body.span);
3b2f2976
XL
223 for (j, path) in self.data.move_paths.iter_enumerated() {
224 debug!(" {:?} = {:?}", j, path);
225 }
226 "done dumping moves"
227 });
ea8adc8c 228
064997fb
FG
229 if self.errors.is_empty() {
230 Ok((self.un_derefer.derefer_sidetable, self.data))
231 } else {
232 Err((self.data, self.errors))
233 }
3b2f2976
XL
234 }
235}
236
dc9dc135
XL
237pub(super) fn gather_moves<'tcx>(
238 body: &Body<'tcx>,
239 tcx: TyCtxt<'tcx>,
60c5eb7d 240 param_env: ty::ParamEnv<'tcx>,
064997fb 241) -> MoveDat<'tcx> {
60c5eb7d 242 let mut builder = MoveDataBuilder::new(body, tcx, param_env);
ff7c6d11
XL
243
244 builder.gather_args();
3b2f2976 245
f2b60f7d 246 for (bb, block) in body.basic_blocks.iter_enumerated() {
3b2f2976
XL
247 for (i, stmt) in block.statements.iter().enumerate() {
248 let source = Location { block: bb, statement_index: i };
249 builder.gather_statement(source, stmt);
250 }
251
e1599b0c 252 let terminator_loc = Location { block: bb, statement_index: block.statements.len() };
3b2f2976
XL
253 builder.gather_terminator(terminator_loc, block.terminator());
254 }
255
256 builder.finalize()
257}
258
dc9dc135 259impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
ff7c6d11 260 fn gather_args(&mut self) {
dc9dc135 261 for arg in self.body.args_iter() {
ff7c6d11 262 let path = self.data.rev_lookup.locals[arg];
ff7c6d11
XL
263
264 let init = self.data.inits.push(Init {
e1599b0c
XL
265 path,
266 kind: InitKind::Deep,
267 location: InitLocation::Argument(arg),
ff7c6d11
XL
268 });
269
e1599b0c 270 debug!("gather_args: adding init {:?} of {:?} for argument {:?}", init, path, arg);
ff7c6d11
XL
271
272 self.data.init_path_map[path].push(init);
273 }
274 }
275
3b2f2976
XL
276 fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) {
277 debug!("gather_statement({:?}, {:?})", loc, stmt);
ea8adc8c
XL
278 (Gatherer { builder: self, loc }).gather_statement(stmt);
279 }
280
281 fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) {
282 debug!("gather_terminator({:?}, {:?})", loc, term);
283 (Gatherer { builder: self, loc }).gather_terminator(term);
284 }
285}
286
dc9dc135
XL
287struct Gatherer<'b, 'a, 'tcx> {
288 builder: &'b mut MoveDataBuilder<'a, 'tcx>,
ea8adc8c
XL
289 loc: Location,
290}
291
dc9dc135 292impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
ea8adc8c 293 fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
ba9703b0 294 match &stmt.kind {
064997fb
FG
295 StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => {
296 assert!(place.projection.is_empty());
297 if self.builder.body.local_decls[place.local].is_deref_temp() {
298 self.builder.un_derefer.derefer_sidetable.insert(place.local, *reffed);
299 }
300 }
ba9703b0
XL
301 StatementKind::Assign(box (place, rval)) => {
302 self.create_move_path(*place);
3b2f2976
XL
303 if let RvalueInitializationState::Shallow = rval.initialization_state() {
304 // Box starts out uninitialized - need to create a separate
305 // move-path for the interior so it will be separate from
306 // the exterior.
ba9703b0 307 self.create_move_path(self.builder.tcx.mk_place_deref(*place));
416331ca 308 self.gather_init(place.as_ref(), InitKind::Shallow);
ff7c6d11 309 } else {
416331ca 310 self.gather_init(place.as_ref(), InitKind::Deep);
3b2f2976 311 }
ea8adc8c 312 self.gather_rvalue(rval);
3b2f2976 313 }
cdc7bbd5
XL
314 StatementKind::FakeRead(box (_, place)) => {
315 self.create_move_path(*place);
94b46f34 316 }
abe05a73
XL
317 StatementKind::StorageLive(_) => {}
318 StatementKind::StorageDead(local) => {
064997fb
FG
319 // DerefTemp locals (results of CopyForDeref) don't actually move anything.
320 if !self.builder.un_derefer.derefer_sidetable.contains_key(&local) {
321 self.gather_move(Place::from(*local));
322 }
abe05a73 323 }
04454e1e 324 StatementKind::SetDiscriminant { .. } | StatementKind::Deinit(..) => {
e1599b0c
XL
325 span_bug!(
326 stmt.source_info.span,
04454e1e 327 "SetDiscriminant/Deinit should not exist during borrowck"
e1599b0c 328 );
3b2f2976 329 }
e1599b0c
XL
330 StatementKind::Retag { .. }
331 | StatementKind::AscribeUserType(..)
353b0b11 332 | StatementKind::PlaceMention(..)
3dfed10e 333 | StatementKind::Coverage(..)
f2b60f7d 334 | StatementKind::Intrinsic(..)
9ffffee4 335 | StatementKind::ConstEvalCounter
e1599b0c 336 | StatementKind::Nop => {}
3b2f2976
XL
337 }
338 }
339
ea8adc8c 340 fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
3b2f2976 341 match *rvalue {
f9f354fc 342 Rvalue::ThreadLocalRef(_) => {} // not-a-move
e1599b0c
XL
343 Rvalue::Use(ref operand)
344 | Rvalue::Repeat(ref operand, _)
345 | Rvalue::Cast(_, ref operand, _)
c295e0f8 346 | Rvalue::ShallowInitBox(ref operand, _)
e1599b0c 347 | Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand),
6a06907d
XL
348 Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs))
349 | Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => {
ea8adc8c
XL
350 self.gather_operand(lhs);
351 self.gather_operand(rhs);
3b2f2976
XL
352 }
353 Rvalue::Aggregate(ref _kind, ref operands) => {
354 for operand in operands {
ea8adc8c 355 self.gather_operand(operand);
3b2f2976
XL
356 }
357 }
064997fb 358 Rvalue::CopyForDeref(..) => unreachable!(),
e1599b0c 359 Rvalue::Ref(..)
dfeec247 360 | Rvalue::AddressOf(..)
e1599b0c
XL
361 | Rvalue::Discriminant(..)
362 | Rvalue::Len(..)
a2a8927a 363 | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
3b2f2976
XL
364 }
365 }
366
ea8adc8c 367 fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
3b2f2976 368 match term.kind {
e1599b0c 369 TerminatorKind::Goto { target: _ }
29967ef6
XL
370 | TerminatorKind::FalseEdge { .. }
371 | TerminatorKind::FalseUnwind { .. }
372 // In some sense returning moves the return place into the current
373 // call's destination, however, since there are no statements after
374 // this that could possibly access the return place, this doesn't
375 // need recording.
376 | TerminatorKind::Return
e1599b0c 377 | TerminatorKind::Resume
353b0b11 378 | TerminatorKind::Terminate
e1599b0c 379 | TerminatorKind::GeneratorDrop
9ffffee4
FG
380 | TerminatorKind::Unreachable
381 | TerminatorKind::Drop { .. } => {}
3b2f2976 382
0531ce1d
XL
383 TerminatorKind::Assert { ref cond, .. } => {
384 self.gather_operand(cond);
385 }
386
387 TerminatorKind::SwitchInt { ref discr, .. } => {
388 self.gather_operand(discr);
3b2f2976
XL
389 }
390
ba9703b0 391 TerminatorKind::Yield { ref value, resume_arg: place, .. } => {
ea8adc8c 392 self.gather_operand(value);
74b04a01
XL
393 self.create_move_path(place);
394 self.gather_init(place.as_ref(), InitKind::Deep);
ea8adc8c 395 }
0bf4aa26
XL
396 TerminatorKind::Call {
397 ref func,
398 ref args,
923072b8
FG
399 destination,
400 target,
353b0b11 401 unwind: _,
0bf4aa26 402 from_hir_call: _,
f035d41b 403 fn_span: _,
0bf4aa26 404 } => {
ea8adc8c 405 self.gather_operand(func);
3b2f2976 406 for arg in args {
ea8adc8c 407 self.gather_operand(arg);
3b2f2976 408 }
923072b8 409 if let Some(_bb) = target {
3b2f2976 410 self.create_move_path(destination);
416331ca 411 self.gather_init(destination.as_ref(), InitKind::NonPanicPathOnly);
3b2f2976
XL
412 }
413 }
f9f354fc
XL
414 TerminatorKind::InlineAsm {
415 template: _,
416 ref operands,
417 options: _,
418 line_spans: _,
419 destination: _,
353b0b11 420 unwind: _,
f9f354fc
XL
421 } => {
422 for op in operands {
423 match *op {
424 InlineAsmOperand::In { reg: _, ref value }
cdc7bbd5 425 => {
f9f354fc
XL
426 self.gather_operand(value);
427 }
428 InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
429 if let Some(place) = place {
430 self.create_move_path(place);
431 self.gather_init(place.as_ref(), InitKind::Deep);
432 }
433 }
434 InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
435 self.gather_operand(in_value);
436 if let Some(out_place) = out_place {
437 self.create_move_path(out_place);
438 self.gather_init(out_place.as_ref(), InitKind::Deep);
439 }
440 }
cdc7bbd5
XL
441 InlineAsmOperand::Const { value: _ }
442 | InlineAsmOperand::SymFn { value: _ }
f035d41b 443 | InlineAsmOperand::SymStatic { def_id: _ } => {}
f9f354fc
XL
444 }
445 }
446 }
3b2f2976
XL
447 }
448 }
449
ea8adc8c 450 fn gather_operand(&mut self, operand: &Operand<'tcx>) {
3b2f2976 451 match *operand {
e1599b0c 452 Operand::Constant(..) | Operand::Copy(..) => {} // not-a-move
ba9703b0 453 Operand::Move(place) => {
e1599b0c 454 // a move
ff7c6d11 455 self.gather_move(place);
3b2f2976
XL
456 }
457 }
458 }
459
ba9703b0 460 fn gather_move(&mut self, place: Place<'tcx>) {
ff7c6d11 461 debug!("gather_move({:?}, {:?})", self.loc, place);
064997fb
FG
462 if let Some(new_place) = self.builder.un_derefer.derefer(place.as_ref(), self.builder.body)
463 {
464 self.gather_move(new_place);
465 return;
466 }
3b2f2976 467
dfeec247
XL
468 if let [ref base @ .., ProjectionElem::Subslice { from, to, from_end: false }] =
469 **place.projection
470 {
60c5eb7d
XL
471 // Split `Subslice` patterns into the corresponding list of
472 // `ConstIndex` patterns. This is done to ensure that all move paths
473 // are disjoint, which is expected by drop elaboration.
dfeec247 474 let base_place =
9ffffee4 475 Place { local: place.local, projection: self.builder.tcx.mk_place_elems(base) };
ba9703b0 476 let base_path = match self.move_path_for(base_place) {
60c5eb7d
XL
477 Ok(path) => path,
478 Err(MoveError::UnionMove { path }) => {
479 self.record_move(place, path);
480 return;
481 }
482 Err(error @ MoveError::IllegalMove { .. }) => {
483 self.builder.errors.push((base_place, error));
484 return;
485 }
486 };
487 let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty;
1b1a35ee 488 let len: u64 = match base_ty.kind() {
9ffffee4
FG
489 ty::Array(_, size) => {
490 size.eval_target_usize(self.builder.tcx, self.builder.param_env)
491 }
60c5eb7d
XL
492 _ => bug!("from_end: false slice pattern of non-array type"),
493 };
494 for offset in from..to {
dfeec247
XL
495 let elem =
496 ProjectionElem::ConstantIndex { offset, min_length: len, from_end: false };
ba9703b0 497 let path =
f9f354fc 498 self.add_move_path(base_path, elem, |tcx| tcx.mk_place_elem(base_place, elem));
60c5eb7d 499 self.record_move(place, path);
3b2f2976 500 }
60c5eb7d
XL
501 } else {
502 match self.move_path_for(place) {
503 Ok(path) | Err(MoveError::UnionMove { path }) => self.record_move(place, path),
504 Err(error @ MoveError::IllegalMove { .. }) => {
ba9703b0 505 self.builder.errors.push((place, error));
60c5eb7d
XL
506 }
507 };
508 }
509 }
3b2f2976 510
ba9703b0 511 fn record_move(&mut self, place: Place<'tcx>, path: MovePathIndex) {
74b04a01 512 let move_out = self.builder.data.moves.push(MoveOut { path, source: self.loc });
e1599b0c
XL
513 debug!(
514 "gather_move({:?}, {:?}): adding move {:?} of {:?}",
515 self.loc, place, move_out, path
516 );
ea8adc8c
XL
517 self.builder.data.path_map[path].push(move_out);
518 self.builder.data.loc_map[self.loc].push(move_out);
3b2f2976 519 }
ff7c6d11 520
74b04a01 521 fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
ff7c6d11
XL
522 debug!("gather_init({:?}, {:?})", self.loc, place);
523
064997fb
FG
524 if let Some(new_place) = self.builder.un_derefer.derefer(place, self.builder.body) {
525 self.gather_init(new_place.as_ref(), kind);
526 return;
527 }
528
416331ca
XL
529 let mut place = place;
530
531 // Check if we are assigning into a field of a union, if so, lookup the place
532 // of the union so it is marked as initialized again.
5869c6ff 533 if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() {
17df50a5
XL
534 if place_base.ty(self.builder.body, self.builder.tcx).ty.is_union() {
535 place = place_base;
416331ca
XL
536 }
537 }
a1dfa0c6 538
ff7c6d11
XL
539 if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place) {
540 let init = self.builder.data.inits.push(Init {
b7449926 541 location: InitLocation::Statement(self.loc),
ff7c6d11
XL
542 path,
543 kind,
544 });
545
e1599b0c
XL
546 debug!(
547 "gather_init({:?}, {:?}): adding init {:?} of {:?}",
548 self.loc, place, init, path
549 );
ff7c6d11
XL
550
551 self.builder.data.init_path_map[path].push(init);
552 self.builder.data.init_loc_map[self.loc].push(init);
553 }
554 }
3b2f2976 555}