+
+ // Determine the fake borrows that are needed to ensure that the place
+ // will evaluate to the same thing until an arm has been chosen.
+ fn add_fake_borrows<'pat>(
+ &mut self,
+ pre_binding_blocks: &[(BasicBlock, Span)],
+ fake_borrows: FxHashMap<Place<'tcx>, BorrowKind>,
+ source_info: SourceInfo,
+ start_block: BasicBlock,
+ ) {
+ let tcx = self.hir.tcx();
+
+ debug!("add_fake_borrows pre_binding_blocks = {:?}, fake_borrows = {:?}",
+ pre_binding_blocks, fake_borrows);
+
+ let mut all_fake_borrows = Vec::with_capacity(fake_borrows.len());
+
+ // Insert a Shallow borrow of the prefixes of any fake borrows.
+ for (place, borrow_kind) in fake_borrows
+ {
+ {
+ let mut prefix_cursor = &place;
+ while let Place::Projection(box Projection { base, elem }) = prefix_cursor {
+ if let ProjectionElem::Deref = elem {
+ // Insert a shallow borrow after a deref. For other
+ // projections the borrow of prefix_cursor will
+ // conflict with any mutation of base.
+ all_fake_borrows.push((base.clone(), BorrowKind::Shallow));
+ }
+ prefix_cursor = base;
+ }
+ }
+
+ all_fake_borrows.push((place, borrow_kind));
+ }
+
+ // Deduplicate and ensure a deterministic order.
+ all_fake_borrows.sort();
+ all_fake_borrows.dedup();
+
+ debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);
+
+ // Add fake borrows to the start of the match and reads of them before
+ // the start of each arm.
+ let mut borrowed_input_temps = Vec::with_capacity(all_fake_borrows.len());
+
+ for (matched_place, borrow_kind) in all_fake_borrows {
+ let borrowed_input =
+ Rvalue::Ref(tcx.types.re_empty, borrow_kind, matched_place.clone());
+ let borrowed_input_ty = borrowed_input.ty(&self.local_decls, tcx);
+ let borrowed_input_temp = self.temp(borrowed_input_ty, source_info.span);
+ self.cfg.push_assign(
+ start_block,
+ source_info,
+ &borrowed_input_temp,
+ borrowed_input
+ );
+ borrowed_input_temps.push(borrowed_input_temp);
+ }
+
+ // FIXME: This could be a lot of reads (#fake borrows * #patterns).
+ // The false edges that we currently generate would allow us to only do
+ // this on the last Candidate, but it's possible that there might not be
+ // so many false edges in the future, so we read for all Candidates for
+ // now.
+ // Another option would be to make our own block and add our own false
+ // edges to it.
+ if tcx.emit_read_for_match() {
+ for &(pre_binding_block, span) in pre_binding_blocks {
+ let pattern_source_info = self.source_info(span);
+ for temp in &borrowed_input_temps {
+ self.cfg.push(pre_binding_block, Statement {
+ source_info: pattern_source_info,
+ kind: StatementKind::FakeRead(
+ FakeReadCause::ForMatchGuard,
+ temp.clone(),
+ ),
+ });
+ }
+ }
+ }
+ }