]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/build/matches/mod.rs
c2a7172d54cca22cf2a105366bf4d27a510d2c67
[rust.git] / src / librustc_mir / build / matches / mod.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Code related to match expressions. These are sufficiently complex
12 //! to warrant their own module and submodules. :) This main module
13 //! includes the high-level algorithm, the submodules contain the
14 //! details.
15
16 use build::scope::{CachedBlock, DropKind};
17 use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
18 use build::{BlockAnd, BlockAndExtension, Builder};
19 use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
20 use hair::*;
21 use rustc::hir;
22 use rustc::mir::*;
23 use rustc::ty::{self, CanonicalTy, Ty};
24 use rustc_data_structures::bit_set::BitSet;
25 use rustc_data_structures::fx::FxHashMap;
26 use syntax::ast::{Name, NodeId};
27 use syntax_pos::Span;
28
29 // helper functions, broken out by category:
30 mod simplify;
31 mod test;
32 mod util;
33
34 /// ArmHasGuard is isomorphic to a boolean flag. It indicates whether
35 /// a match arm has a guard expression attached to it.
36 #[derive(Copy, Clone, Debug)]
37 pub(crate) struct ArmHasGuard(pub bool);
38
39 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
40     pub fn match_expr(
41         &mut self,
42         destination: &Place<'tcx>,
43         span: Span,
44         mut block: BasicBlock,
45         discriminant: ExprRef<'tcx>,
46         arms: Vec<Arm<'tcx>>,
47     ) -> BlockAnd<()> {
48         let tcx = self.hir.tcx();
49         let discriminant_span = discriminant.span();
50         let discriminant_place = unpack!(block = self.as_place(block, discriminant));
51
52         // Matching on a `discriminant_place` with an uninhabited type doesn't
53         // generate any memory reads by itself, and so if the place "expression"
54         // contains unsafe operations like raw pointer dereferences or union
55         // field projections, we wouldn't know to require an `unsafe` block
56         // around a `match` equivalent to `std::intrinsics::unreachable()`.
57         // See issue #47412 for this hole being discovered in the wild.
58         //
59         // HACK(eddyb) Work around the above issue by adding a dummy inspection
60         // of `discriminant_place`, specifically by applying `ReadForMatch`.
61         //
62         // NOTE: ReadForMatch also checks that the discriminant is initialized.
63         // This is currently needed to not allow matching on an uninitialized,
64         // uninhabited value. If we get never patterns, those will check that
65         // the place is initialized, and so this read would only be used to
66         // check safety.
67
68         let source_info = self.source_info(discriminant_span);
69         self.cfg.push(block, Statement {
70             source_info,
71             kind: StatementKind::FakeRead(
72                 FakeReadCause::ForMatchedPlace,
73                 discriminant_place.clone(),
74             ),
75         });
76
77         let mut arm_blocks = ArmBlocks {
78             blocks: arms.iter().map(|_| self.cfg.start_new_block()).collect(),
79         };
80
81         // Get the arm bodies and their scopes, while declaring bindings.
82         let arm_bodies: Vec<_> = arms.iter()
83             .map(|arm| {
84                 // BUG: use arm lint level
85                 let body = self.hir.mirror(arm.body.clone());
86                 let scope = self.declare_bindings(
87                     None,
88                     body.span,
89                     LintLevel::Inherited,
90                     &arm.patterns[..],
91                     ArmHasGuard(arm.guard.is_some()),
92                     Some((Some(&discriminant_place), discriminant_span)),
93                 );
94                 (body, scope.unwrap_or(self.source_scope))
95             })
96             .collect();
97
98         // create binding start block for link them by false edges
99         let candidate_count = arms.iter().fold(0, |ac, c| ac + c.patterns.len());
100         let pre_binding_blocks: Vec<_> = (0..candidate_count + 1)
101             .map(|_| self.cfg.start_new_block())
102             .collect();
103
104         let mut has_guard = false;
105
106         // assemble a list of candidates: there is one candidate per
107         // pattern, which means there may be more than one candidate
108         // *per arm*. These candidates are kept sorted such that the
109         // highest priority candidate comes first in the list.
110         // (i.e. same order as in source)
111
112         let candidates: Vec<_> = arms.iter()
113             .enumerate()
114             .flat_map(|(arm_index, arm)| {
115                 arm.patterns
116                     .iter()
117                     .enumerate()
118                     .map(move |(pat_index, pat)| (arm_index, pat_index, pat, arm.guard.clone()))
119             })
120             .zip(
121                 pre_binding_blocks
122                     .iter()
123                     .zip(pre_binding_blocks.iter().skip(1)),
124             )
125             .map(
126                 |(
127                     (arm_index, pat_index, pattern, guard),
128                     (pre_binding_block, next_candidate_pre_binding_block)
129                 )| {
130                     has_guard |= guard.is_some();
131
132                     // One might ask: why not build up the match pair such that it
133                     // matches via `borrowed_input_temp.deref()` instead of
134                     // using the `discriminant_place` directly, as it is doing here?
135                     //
136                     // The basic answer is that if you do that, then you end up with
137                     // accceses to a shared borrow of the input and that conflicts with
138                     // any arms that look like e.g.
139                     //
140                     // match Some(&4) {
141                     //     ref mut foo => {
142                     //         ... /* mutate `foo` in arm body */ ...
143                     //     }
144                     // }
145                     //
146                     // (Perhaps we could further revise the MIR
147                     //  construction here so that it only does a
148                     //  shared borrow at the outset and delays doing
149                     //  the mutable borrow until after the pattern is
150                     //  matched *and* the guard (if any) for the arm
151                     //  has been run.)
152
153                     Candidate {
154                         span: pattern.span,
155                         match_pairs: vec![MatchPair::new(discriminant_place.clone(), pattern)],
156                         bindings: vec![],
157                         ascriptions: vec![],
158                         guard,
159                         arm_index,
160                         pat_index,
161                         pre_binding_block: *pre_binding_block,
162                         next_candidate_pre_binding_block: *next_candidate_pre_binding_block,
163                     }
164                 },
165             )
166             .collect();
167
168         let outer_source_info = self.source_info(span);
169         self.cfg.terminate(
170             *pre_binding_blocks.last().unwrap(),
171             outer_source_info,
172             TerminatorKind::Unreachable,
173         );
174
175         // Maps a place to the kind of Fake borrow that we want to perform on
176         // it: either Shallow or Shared, depending on whether the place is
177         // bound in the match, or just switched on.
178         // If there are no match guards then we don't need any fake borrows,
179         // so don't track them.
180         let mut fake_borrows = if has_guard && tcx.generate_borrow_of_any_match_input() {
181             Some(FxHashMap())
182         } else {
183             None
184         };
185
186         let pre_binding_blocks: Vec<_> = candidates
187             .iter()
188             .map(|cand| (cand.pre_binding_block, cand.span))
189             .collect();
190
191         // this will generate code to test discriminant_place and
192         // branch to the appropriate arm block
193         let otherwise = self.match_candidates(
194             discriminant_span,
195             &mut arm_blocks,
196             candidates,
197             block,
198             &mut fake_borrows,
199         );
200
201         if !otherwise.is_empty() {
202             // All matches are exhaustive. However, because some matches
203             // only have exponentially-large exhaustive decision trees, we
204             // sometimes generate an inexhaustive decision tree.
205             //
206             // In that case, the inexhaustive tips of the decision tree
207             // can't be reached - terminate them with an `unreachable`.
208             let source_info = self.source_info(span);
209
210             let mut otherwise = otherwise;
211             otherwise.sort();
212             otherwise.dedup(); // variant switches can introduce duplicate target blocks
213             for block in otherwise {
214                 self.cfg
215                     .terminate(block, source_info, TerminatorKind::Unreachable);
216             }
217         }
218
219         if let Some(fake_borrows) = fake_borrows {
220             self.add_fake_borrows(&pre_binding_blocks, fake_borrows, source_info, block);
221         }
222
223         // all the arm blocks will rejoin here
224         let end_block = self.cfg.start_new_block();
225
226         let outer_source_info = self.source_info(span);
227         for (arm_index, (body, source_scope)) in arm_bodies.into_iter().enumerate() {
228             let mut arm_block = arm_blocks.blocks[arm_index];
229             // Re-enter the source scope we created the bindings in.
230             self.source_scope = source_scope;
231             unpack!(arm_block = self.into(destination, arm_block, body));
232             self.cfg.terminate(
233                 arm_block,
234                 outer_source_info,
235                 TerminatorKind::Goto { target: end_block },
236             );
237         }
238         self.source_scope = outer_source_info.scope;
239
240         end_block.unit()
241     }
242
243     pub fn expr_into_pattern(
244         &mut self,
245         mut block: BasicBlock,
246         irrefutable_pat: Pattern<'tcx>,
247         initializer: ExprRef<'tcx>,
248     ) -> BlockAnd<()> {
249         match *irrefutable_pat.kind {
250             // Optimize the case of `let x = ...` to write directly into `x`
251             PatternKind::Binding {
252                 mode: BindingMode::ByValue,
253                 var,
254                 subpattern: None,
255                 ..
256             } => {
257                 let place =
258                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard);
259                 unpack!(block = self.into(&place, block, initializer));
260
261
262                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
263                 let source_info = self.source_info(irrefutable_pat.span);
264                 self.cfg.push(
265                     block,
266                     Statement {
267                         source_info,
268                         kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()),
269                     },
270                 );
271
272                 self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
273                 block.unit()
274             }
275
276             // Optimize the case of `let x: T = ...` to write directly
277             // into `x` and then require that `T == typeof(x)`.
278             //
279             // Weirdly, this is needed to prevent the
280             // `intrinsic-move-val.rs` test case from crashing. That
281             // test works with uninitialized values in a rather
282             // dubious way, so it may be that the test is kind of
283             // broken.
284             PatternKind::AscribeUserType {
285                 subpattern: Pattern {
286                     kind: box PatternKind::Binding {
287                         mode: BindingMode::ByValue,
288                         var,
289                         subpattern: None,
290                         ..
291                     },
292                     ..
293                 },
294                 user_ty: ascription_user_ty,
295             } => {
296                 let place =
297                     self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard);
298                 unpack!(block = self.into(&place, block, initializer));
299
300                 let source_info = self.source_info(irrefutable_pat.span);
301                 self.cfg.push(
302                     block,
303                     Statement {
304                         source_info,
305                         kind: StatementKind::AscribeUserType(
306                             place.clone(),
307                             ty::Variance::Invariant,
308                             ascription_user_ty,
309                         ),
310                     },
311                 );
312
313                 // Inject a fake read, see comments on `FakeReadCause::ForLet`.
314                 self.cfg.push(
315                     block,
316                     Statement {
317                         source_info,
318                         kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()),
319                     },
320                 );
321
322                 self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard);
323                 block.unit()
324             }
325             _ => {
326                 let place = unpack!(block = self.as_place(block, initializer));
327                 self.place_into_pattern(block, irrefutable_pat, &place, true)
328             }
329         }
330     }
331
332     pub fn place_into_pattern(
333         &mut self,
334         mut block: BasicBlock,
335         irrefutable_pat: Pattern<'tcx>,
336         initializer: &Place<'tcx>,
337         set_match_place: bool,
338     ) -> BlockAnd<()> {
339         // create a dummy candidate
340         let mut candidate = Candidate {
341             span: irrefutable_pat.span,
342             match_pairs: vec![MatchPair::new(initializer.clone(), &irrefutable_pat)],
343             bindings: vec![],
344             ascriptions: vec![],
345             guard: None,
346
347             // since we don't call `match_candidates`, next fields is unused
348             arm_index: 0,
349             pat_index: 0,
350             pre_binding_block: block,
351             next_candidate_pre_binding_block: block,
352         };
353
354         // Simplify the candidate. Since the pattern is irrefutable, this should
355         // always convert all match-pairs into bindings.
356         unpack!(block = self.simplify_candidate(block, &mut candidate));
357
358         if !candidate.match_pairs.is_empty() {
359             span_bug!(
360                 candidate.match_pairs[0].pattern.span,
361                 "match pairs {:?} remaining after simplifying \
362                  irrefutable pattern",
363                 candidate.match_pairs
364             );
365         }
366
367         // for matches and function arguments, the place that is being matched
368         // can be set when creating the variables. But the place for
369         // let PATTERN = ... might not even exist until we do the assignment.
370         // so we set it here instead
371         if set_match_place {
372             for binding in &candidate.bindings {
373                 let local = self.var_local_id(binding.var_id, OutsideGuard);
374
375                 if let Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
376                     opt_match_place: Some((ref mut match_place, _)),
377                     ..
378                 }))) = self.local_decls[local].is_user_variable
379                 {
380                     *match_place = Some(initializer.clone());
381                 } else {
382                     bug!("Let binding to non-user variable.")
383                 }
384             }
385         }
386
387         self.ascribe_types(block, &candidate.ascriptions);
388
389         // now apply the bindings, which will also declare the variables
390         self.bind_matched_candidate_for_arm_body(block, &candidate.bindings);
391
392         block.unit()
393     }
394
395     /// Declares the bindings of the given patterns and returns the visibility
396     /// scope for the bindings in these patterns, if such a scope had to be
397     /// created. NOTE: Declaring the bindings should always be done in their
398     /// drop scope.
399     pub fn declare_bindings(
400         &mut self,
401         mut visibility_scope: Option<SourceScope>,
402         scope_span: Span,
403         lint_level: LintLevel,
404         patterns: &[Pattern<'tcx>],
405         has_guard: ArmHasGuard,
406         opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
407     ) -> Option<SourceScope> {
408         assert!(
409             !(visibility_scope.is_some() && lint_level.is_explicit()),
410             "can't have both a visibility and a lint scope at the same time"
411         );
412         let mut scope = self.source_scope;
413         let num_patterns = patterns.len();
414         self.visit_bindings(
415             &patterns[0],
416             None,
417             &mut |this, mutability, name, mode, var, span, ty, user_ty| {
418                 if visibility_scope.is_none() {
419                     visibility_scope =
420                         Some(this.new_source_scope(scope_span, LintLevel::Inherited, None));
421                     // If we have lints, create a new source scope
422                     // that marks the lints for the locals. See the comment
423                     // on the `source_info` field for why this is needed.
424                     if lint_level.is_explicit() {
425                         scope = this.new_source_scope(scope_span, lint_level, None);
426                     }
427                 }
428                 let source_info = SourceInfo { span, scope };
429                 let visibility_scope = visibility_scope.unwrap();
430                 this.declare_binding(
431                     source_info,
432                     visibility_scope,
433                     mutability,
434                     name,
435                     mode,
436                     num_patterns,
437                     var,
438                     ty,
439                     user_ty,
440                     has_guard,
441                     opt_match_place.map(|(x, y)| (x.cloned(), y)),
442                     patterns[0].span,
443                 );
444             },
445         );
446         visibility_scope
447     }
448
449     pub fn storage_live_binding(
450         &mut self,
451         block: BasicBlock,
452         var: NodeId,
453         span: Span,
454         for_guard: ForGuard,
455     ) -> Place<'tcx> {
456         let local_id = self.var_local_id(var, for_guard);
457         let source_info = self.source_info(span);
458         self.cfg.push(
459             block,
460             Statement {
461                 source_info,
462                 kind: StatementKind::StorageLive(local_id),
463             },
464         );
465         let place = Place::Local(local_id);
466         let var_ty = self.local_decls[local_id].ty;
467         let hir_id = self.hir.tcx().hir.node_to_hir_id(var);
468         let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
469         self.schedule_drop(span, region_scope, &place, var_ty, DropKind::Storage);
470         place
471     }
472
473     pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span, for_guard: ForGuard) {
474         let local_id = self.var_local_id(var, for_guard);
475         let var_ty = self.local_decls[local_id].ty;
476         let hir_id = self.hir.tcx().hir.node_to_hir_id(var);
477         let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id);
478         self.schedule_drop(
479             span,
480             region_scope,
481             &Place::Local(local_id),
482             var_ty,
483             DropKind::Value {
484                 cached_block: CachedBlock::default(),
485             },
486         );
487     }
488
489     pub fn visit_bindings(
490         &mut self,
491         pattern: &Pattern<'tcx>,
492         mut pattern_user_ty: Option<CanonicalTy<'tcx>>,
493         f: &mut impl FnMut(
494             &mut Self,
495             Mutability,
496             Name,
497             BindingMode,
498             NodeId,
499             Span,
500             Ty<'tcx>,
501             Option<CanonicalTy<'tcx>>,
502         ),
503     ) {
504         match *pattern.kind {
505             PatternKind::Binding {
506                 mutability,
507                 name,
508                 mode,
509                 var,
510                 ty,
511                 ref subpattern,
512                 ..
513             } => {
514                 match mode {
515                     BindingMode::ByValue => { }
516                     BindingMode::ByRef(..) => {
517                         // If this is a `ref` binding (e.g., `let ref
518                         // x: T = ..`), then the type of `x` is not
519                         // `T` but rather `&T`, so ignore
520                         // `pattern_user_ty` for now.
521                         //
522                         // FIXME(#47184): extract or handle `pattern_user_ty` somehow
523                         pattern_user_ty = None;
524                     }
525                 }
526
527                 f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty);
528                 if let Some(subpattern) = subpattern.as_ref() {
529                     self.visit_bindings(subpattern, pattern_user_ty, f);
530                 }
531             }
532             PatternKind::Array {
533                 ref prefix,
534                 ref slice,
535                 ref suffix,
536             }
537             | PatternKind::Slice {
538                 ref prefix,
539                 ref slice,
540                 ref suffix,
541             } => {
542                 // FIXME(#47184): extract or handle `pattern_user_ty` somehow
543                 for subpattern in prefix.iter().chain(slice).chain(suffix) {
544                     self.visit_bindings(subpattern, None, f);
545                 }
546             }
547             PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
548             PatternKind::Deref { ref subpattern } => {
549                 // FIXME(#47184): extract or handle `pattern_user_ty` somehow
550                 self.visit_bindings(subpattern, None, f);
551             }
552             PatternKind::AscribeUserType { ref subpattern, user_ty } => {
553                 // This corresponds to something like
554                 //
555                 // ```
556                 // let (p1: T1): T2 = ...;
557                 // ```
558                 //
559                 // Not presently possible, though maybe someday.
560                 assert!(pattern_user_ty.is_none());
561                 self.visit_bindings(subpattern, Some(user_ty), f)
562             }
563             PatternKind::Leaf { ref subpatterns }
564             | PatternKind::Variant {
565                 ref subpatterns, ..
566             } => {
567                 // FIXME(#47184): extract or handle `pattern_user_ty` somehow
568                 for subpattern in subpatterns {
569                     self.visit_bindings(&subpattern.pattern, None, f);
570                 }
571             }
572         }
573     }
574 }
575
576 /// List of blocks for each arm (and potentially other metadata in the
577 /// future).
578 struct ArmBlocks {
579     blocks: Vec<BasicBlock>,
580 }
581
582 #[derive(Clone, Debug)]
583 pub struct Candidate<'pat, 'tcx: 'pat> {
584     // span of the original pattern that gave rise to this candidate
585     span: Span,
586
587     // all of these must be satisfied...
588     match_pairs: Vec<MatchPair<'pat, 'tcx>>,
589
590     // ...these bindings established...
591     bindings: Vec<Binding<'tcx>>,
592
593     // ...these types asserted...
594     ascriptions: Vec<Ascription<'tcx>>,
595
596     // ...and the guard must be evaluated...
597     guard: Option<Guard<'tcx>>,
598
599     // ...and then we branch to arm with this index.
600     arm_index: usize,
601
602     // ...and the blocks for add false edges between candidates
603     pre_binding_block: BasicBlock,
604     next_candidate_pre_binding_block: BasicBlock,
605
606     // This uniquely identifies this candidate *within* the arm.
607     pat_index: usize,
608 }
609
610 #[derive(Clone, Debug)]
611 struct Binding<'tcx> {
612     span: Span,
613     source: Place<'tcx>,
614     name: Name,
615     var_id: NodeId,
616     var_ty: Ty<'tcx>,
617     mutability: Mutability,
618     binding_mode: BindingMode<'tcx>,
619 }
620
621 /// Indicates that the type of `source` must be a subtype of the
622 /// user-given type `user_ty`; this is basically a no-op but can
623 /// influence region inference.
624 #[derive(Clone, Debug)]
625 struct Ascription<'tcx> {
626     span: Span,
627     source: Place<'tcx>,
628     user_ty: CanonicalTy<'tcx>,
629 }
630
631 #[derive(Clone, Debug)]
632 pub struct MatchPair<'pat, 'tcx: 'pat> {
633     // this place...
634     place: Place<'tcx>,
635
636     // ... must match this pattern.
637     pattern: &'pat Pattern<'tcx>,
638
639     // HACK(eddyb) This is used to toggle whether a Slice pattern
640     // has had its length checked. This is only necessary because
641     // the "rest" part of the pattern right now has type &[T] and
642     // as such, it requires an Rvalue::Slice to be generated.
643     // See RFC 495 / issue #23121 for the eventual (proper) solution.
644     slice_len_checked: bool,
645 }
646
647 #[derive(Clone, Debug, PartialEq)]
648 enum TestKind<'tcx> {
649     // test the branches of enum
650     Switch {
651         adt_def: &'tcx ty::AdtDef,
652         variants: BitSet<usize>,
653     },
654
655     // test the branches of enum
656     SwitchInt {
657         switch_ty: Ty<'tcx>,
658         options: Vec<u128>,
659         indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>,
660     },
661
662     // test for equality
663     Eq {
664         value: &'tcx ty::Const<'tcx>,
665         ty: Ty<'tcx>,
666     },
667
668     // test whether the value falls within an inclusive or exclusive range
669     Range {
670         lo: &'tcx ty::Const<'tcx>,
671         hi: &'tcx ty::Const<'tcx>,
672         ty: Ty<'tcx>,
673         end: hir::RangeEnd,
674     },
675
676     // test length of the slice is equal to len
677     Len {
678         len: u64,
679         op: BinOp,
680     },
681 }
682
683 #[derive(Debug)]
684 pub struct Test<'tcx> {
685     span: Span,
686     kind: TestKind<'tcx>,
687 }
688
689 ///////////////////////////////////////////////////////////////////////////
690 // Main matching algorithm
691
692 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
693     /// The main match algorithm. It begins with a set of candidates
694     /// `candidates` and has the job of generating code to determine
695     /// which of these candidates, if any, is the correct one. The
696     /// candidates are sorted such that the first item in the list
697     /// has the highest priority. When a candidate is found to match
698     /// the value, we will generate a branch to the appropriate
699     /// block found in `arm_blocks`.
700     ///
701     /// The return value is a list of "otherwise" blocks. These are
702     /// points in execution where we found that *NONE* of the
703     /// candidates apply.  In principle, this means that the input
704     /// list was not exhaustive, though at present we sometimes are
705     /// not smart enough to recognize all exhaustive inputs.
706     ///
707     /// It might be surprising that the input can be inexhaustive.
708     /// Indeed, initially, it is not, because all matches are
709     /// exhaustive in Rust. But during processing we sometimes divide
710     /// up the list of candidates and recurse with a non-exhaustive
711     /// list. This is important to keep the size of the generated code
712     /// under control. See `test_candidates` for more details.
713     ///
714     /// If `add_fake_borrows` is true, then places which need fake borrows
715     /// will be added to it.
716     fn match_candidates<'pat>(
717         &mut self,
718         span: Span,
719         arm_blocks: &mut ArmBlocks,
720         mut candidates: Vec<Candidate<'pat, 'tcx>>,
721         mut block: BasicBlock,
722         fake_borrows: &mut Option<FxHashMap<Place<'tcx>, BorrowKind>>,
723     ) -> Vec<BasicBlock> {
724         debug!(
725             "matched_candidate(span={:?}, block={:?}, candidates={:?})",
726             span, block, candidates
727         );
728
729         // Start by simplifying candidates. Once this process is
730         // complete, all the match pairs which remain require some
731         // form of test, whether it be a switch or pattern comparison.
732         for candidate in &mut candidates {
733             unpack!(block = self.simplify_candidate(block, candidate));
734         }
735
736         // The candidates are sorted by priority. Check to see
737         // whether the higher priority candidates (and hence at
738         // the front of the vec) have satisfied all their match
739         // pairs.
740         let fully_matched = candidates
741             .iter()
742             .take_while(|c| c.match_pairs.is_empty())
743             .count();
744         debug!(
745             "match_candidates: {:?} candidates fully matched",
746             fully_matched
747         );
748         let mut unmatched_candidates = candidates.split_off(fully_matched);
749
750         // Insert a *Shared* borrow of any places that are bound.
751         if let Some(fake_borrows) = fake_borrows {
752             for Binding { source, .. }
753                 in candidates.iter().flat_map(|candidate| &candidate.bindings)
754             {
755                 fake_borrows.insert(source.clone(), BorrowKind::Shared);
756             }
757         }
758
759         let fully_matched_with_guard = candidates.iter().take_while(|c| c.guard.is_some()).count();
760
761         let unreachable_candidates = if fully_matched_with_guard + 1 < candidates.len() {
762             candidates.split_off(fully_matched_with_guard + 1)
763         } else {
764             vec![]
765         };
766
767         for candidate in candidates {
768             // If so, apply any bindings, test the guard (if any), and
769             // branch to the arm.
770             if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, candidate) {
771                 block = b;
772             } else {
773                 // if None is returned, then any remaining candidates
774                 // are unreachable (at least not through this path).
775                 // Link them with false edges.
776                 debug!(
777                     "match_candidates: add false edges for unreachable {:?} and unmatched {:?}",
778                     unreachable_candidates, unmatched_candidates
779                 );
780                 for candidate in unreachable_candidates {
781                     let source_info = self.source_info(candidate.span);
782                     let target = self.cfg.start_new_block();
783                     if let Some(otherwise) =
784                         self.bind_and_guard_matched_candidate(target, arm_blocks, candidate)
785                     {
786                         self.cfg
787                             .terminate(otherwise, source_info, TerminatorKind::Unreachable);
788                     }
789                 }
790
791                 if unmatched_candidates.is_empty() {
792                     return vec![];
793                 } else {
794                     let target = self.cfg.start_new_block();
795                     return self.match_candidates(
796                         span,
797                         arm_blocks,
798                         unmatched_candidates,
799                         target,
800                         &mut None,
801                     );
802                 }
803             }
804         }
805
806         // If there are no candidates that still need testing, we're done.
807         // Since all matches are exhaustive, execution should never reach this point.
808         if unmatched_candidates.is_empty() {
809             return vec![block];
810         }
811
812         // Test candidates where possible.
813         let (otherwise, tested_candidates) =
814             self.test_candidates(span, arm_blocks, &unmatched_candidates, block, fake_borrows);
815
816         // If the target candidates were exhaustive, then we are done.
817         // But for borrowck continue build decision tree.
818
819         // If all candidates were sorted into `target_candidates` somewhere, then
820         // the initial set was inexhaustive.
821         let untested_candidates = unmatched_candidates.split_off(tested_candidates);
822         if untested_candidates.len() == 0 {
823             return otherwise;
824         }
825
826         // Otherwise, let's process those remaining candidates.
827         let join_block = self.join_otherwise_blocks(span, otherwise);
828         self.match_candidates(span, arm_blocks, untested_candidates, join_block, &mut None)
829     }
830
831     fn join_otherwise_blocks(&mut self, span: Span, mut otherwise: Vec<BasicBlock>) -> BasicBlock {
832         let source_info = self.source_info(span);
833         otherwise.sort();
834         otherwise.dedup(); // variant switches can introduce duplicate target blocks
835         if otherwise.len() == 1 {
836             otherwise[0]
837         } else {
838             let join_block = self.cfg.start_new_block();
839             for block in otherwise {
840                 self.cfg.terminate(
841                     block,
842                     source_info,
843                     TerminatorKind::Goto { target: join_block },
844                 );
845             }
846             join_block
847         }
848     }
849
850     /// This is the most subtle part of the matching algorithm.  At
851     /// this point, the input candidates have been fully simplified,
852     /// and so we know that all remaining match-pairs require some
853     /// sort of test. To decide what test to do, we take the highest
854     /// priority candidate (last one in the list) and extract the
855     /// first match-pair from the list. From this we decide what kind
856     /// of test is needed using `test`, defined in the `test` module.
857     ///
858     /// *Note:* taking the first match pair is somewhat arbitrary, and
859     /// we might do better here by choosing more carefully what to
860     /// test.
861     ///
862     /// For example, consider the following possible match-pairs:
863     ///
864     /// 1. `x @ Some(P)` -- we will do a `Switch` to decide what variant `x` has
865     /// 2. `x @ 22` -- we will do a `SwitchInt`
866     /// 3. `x @ 3..5` -- we will do a range test
867     /// 4. etc.
868     ///
869     /// Once we know what sort of test we are going to perform, this
870     /// test may also help us with other candidates. So we walk over
871     /// the candidates (from high to low priority) and check. This
872     /// gives us, for each outcome of the test, a transformed list of
873     /// candidates.  For example, if we are testing the current
874     /// variant of `x.0`, and we have a candidate `{x.0 @ Some(v), x.1
875     /// @ 22}`, then we would have a resulting candidate of `{(x.0 as
876     /// Some).0 @ v, x.1 @ 22}`. Note that the first match-pair is now
877     /// simpler (and, in fact, irrefutable).
878     ///
879     /// But there may also be candidates that the test just doesn't
880     /// apply to. The classical example involves wildcards:
881     ///
882     /// ```
883     /// # let (x, y, z) = (true, true, true);
884     /// match (x, y, z) {
885     ///     (true, _, true) => true,    // (0)
886     ///     (_, true, _) => true,       // (1)
887     ///     (false, false, _) => false, // (2)
888     ///     (true, _, false) => false,  // (3)
889     /// }
890     /// ```
891     ///
892     /// In that case, after we test on `x`, there are 2 overlapping candidate
893     /// sets:
894     ///
895     /// - If the outcome is that `x` is true, candidates 0, 1, and 3
896     /// - If the outcome is that `x` is false, candidates 1 and 2
897     ///
898     /// Here, the traditional "decision tree" method would generate 2
899     /// separate code-paths for the 2 separate cases.
900     ///
901     /// In some cases, this duplication can create an exponential amount of
902     /// code. This is most easily seen by noticing that this method terminates
903     /// with precisely the reachable arms being reachable - but that problem
904     /// is trivially NP-complete:
905     ///
906     /// ```rust
907     ///     match (var0, var1, var2, var3, ..) {
908     ///         (true, _, _, false, true, ...) => false,
909     ///         (_, true, true, false, _, ...) => false,
910     ///         (false, _, false, false, _, ...) => false,
911     ///         ...
912     ///         _ => true
913     ///     }
914     /// ```
915     ///
916     /// Here the last arm is reachable only if there is an assignment to
917     /// the variables that does not match any of the literals. Therefore,
918     /// compilation would take an exponential amount of time in some cases.
919     ///
920     /// That kind of exponential worst-case might not occur in practice, but
921     /// our simplistic treatment of constants and guards would make it occur
922     /// in very common situations - for example #29740:
923     ///
924     /// ```rust
925     /// match x {
926     ///     "foo" if foo_guard => ...,
927     ///     "bar" if bar_guard => ...,
928     ///     "baz" if baz_guard => ...,
929     ///     ...
930     /// }
931     /// ```
932     ///
933     /// Here we first test the match-pair `x @ "foo"`, which is an `Eq` test.
934     ///
935     /// It might seem that we would end up with 2 disjoint candidate
936     /// sets, consisting of the first candidate or the other 3, but our
937     /// algorithm doesn't reason about "foo" being distinct from the other
938     /// constants; it considers the latter arms to potentially match after
939     /// both outcomes, which obviously leads to an exponential amount
940     /// of tests.
941     ///
942     /// To avoid these kinds of problems, our algorithm tries to ensure
943     /// the amount of generated tests is linear. When we do a k-way test,
944     /// we return an additional "unmatched" set alongside the obvious `k`
945     /// sets. When we encounter a candidate that would be present in more
946     /// than one of the sets, we put it and all candidates below it into the
947     /// "unmatched" set. This ensures these `k+1` sets are disjoint.
948     ///
949     /// After we perform our test, we branch into the appropriate candidate
950     /// set and recurse with `match_candidates`. These sub-matches are
951     /// obviously inexhaustive - as we discarded our otherwise set - so
952     /// we set their continuation to do `match_candidates` on the
953     /// "unmatched" set (which is again inexhaustive).
954     ///
955     /// If you apply this to the above test, you basically wind up
956     /// with an if-else-if chain, testing each candidate in turn,
957     /// which is precisely what we want.
958     ///
959     /// In addition to avoiding exponential-time blowups, this algorithm
960     /// also has nice property that each guard and arm is only generated
961     /// once.
962     fn test_candidates<'pat>(
963         &mut self,
964         span: Span,
965         arm_blocks: &mut ArmBlocks,
966         candidates: &[Candidate<'pat, 'tcx>],
967         block: BasicBlock,
968         fake_borrows: &mut Option<FxHashMap<Place<'tcx>, BorrowKind>>,
969     ) -> (Vec<BasicBlock>, usize) {
970         // extract the match-pair from the highest priority candidate
971         let match_pair = &candidates.first().unwrap().match_pairs[0];
972         let mut test = self.test(match_pair);
973
974         // most of the time, the test to perform is simply a function
975         // of the main candidate; but for a test like SwitchInt, we
976         // may want to add cases based on the candidates that are
977         // available
978         match test.kind {
979             TestKind::SwitchInt {
980                 switch_ty,
981                 ref mut options,
982                 ref mut indices,
983             } => {
984                 for candidate in candidates.iter() {
985                     if !self.add_cases_to_switch(
986                         &match_pair.place,
987                         candidate,
988                         switch_ty,
989                         options,
990                         indices,
991                     ) {
992                         break;
993                     }
994                 }
995             }
996             TestKind::Switch {
997                 adt_def: _,
998                 ref mut variants,
999             } => {
1000                 for candidate in candidates.iter() {
1001                     if !self.add_variants_to_switch(&match_pair.place, candidate, variants) {
1002                         break;
1003                     }
1004                 }
1005             }
1006             _ => {}
1007         }
1008
1009         // Insert a Shallow borrow of any places that is switched on.
1010         fake_borrows.as_mut().map(|fb| {
1011             fb.entry(match_pair.place.clone()).or_insert(BorrowKind::Shallow)
1012         });
1013
1014         // perform the test, branching to one of N blocks. For each of
1015         // those N possible outcomes, create a (initially empty)
1016         // vector of candidates. Those are the candidates that still
1017         // apply if the test has that particular outcome.
1018         debug!(
1019             "match_candidates: test={:?} match_pair={:?}",
1020             test, match_pair
1021         );
1022         let target_blocks = self.perform_test(block, &match_pair.place, &test);
1023         let mut target_candidates: Vec<_> = (0..target_blocks.len()).map(|_| vec![]).collect();
1024
1025         // Sort the candidates into the appropriate vector in
1026         // `target_candidates`. Note that at some point we may
1027         // encounter a candidate where the test is not relevant; at
1028         // that point, we stop sorting.
1029         let tested_candidates = candidates
1030             .iter()
1031             .take_while(|c| {
1032                 self.sort_candidate(&match_pair.place, &test, c, &mut target_candidates)
1033             })
1034             .count();
1035         assert!(tested_candidates > 0); // at least the last candidate ought to be tested
1036         debug!("tested_candidates: {}", tested_candidates);
1037         debug!(
1038             "untested_candidates: {}",
1039             candidates.len() - tested_candidates
1040         );
1041
1042         // For each outcome of test, process the candidates that still
1043         // apply. Collect a list of blocks where control flow will
1044         // branch if one of the `target_candidate` sets is not
1045         // exhaustive.
1046         let otherwise: Vec<_> = target_blocks
1047             .into_iter()
1048             .zip(target_candidates)
1049             .flat_map(|(target_block, target_candidates)| {
1050                 self.match_candidates(
1051                     span,
1052                     arm_blocks,
1053                     target_candidates,
1054                     target_block,
1055                     fake_borrows,
1056                 )
1057             })
1058             .collect();
1059
1060         (otherwise, tested_candidates)
1061     }
1062
1063     /// Initializes each of the bindings from the candidate by
1064     /// moving/copying/ref'ing the source as appropriate. Tests the
1065     /// guard, if any, and then branches to the arm. Returns the block
1066     /// for the case where the guard fails.
1067     ///
1068     /// Note: we check earlier that if there is a guard, there cannot
1069     /// be move bindings.  This isn't really important for the
1070     /// self-consistency of this fn, but the reason for it should be
1071     /// clear: after we've done the assignments, if there were move
1072     /// bindings, further tests would be a use-after-move (which would
1073     /// in turn be detected by the borrowck code that runs on the
1074     /// MIR).
1075     fn bind_and_guard_matched_candidate<'pat>(
1076         &mut self,
1077         mut block: BasicBlock,
1078         arm_blocks: &mut ArmBlocks,
1079         candidate: Candidate<'pat, 'tcx>,
1080     ) -> Option<BasicBlock> {
1081         debug!(
1082             "bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
1083             block, candidate
1084         );
1085
1086         debug_assert!(candidate.match_pairs.is_empty());
1087
1088         self.ascribe_types(block, &candidate.ascriptions);
1089
1090         let arm_block = arm_blocks.blocks[candidate.arm_index];
1091         let candidate_source_info = self.source_info(candidate.span);
1092
1093         self.cfg.terminate(
1094             block,
1095             candidate_source_info,
1096             TerminatorKind::Goto {
1097                 target: candidate.pre_binding_block,
1098             },
1099         );
1100
1101         block = self.cfg.start_new_block();
1102         self.cfg.terminate(
1103             candidate.pre_binding_block,
1104             candidate_source_info,
1105             TerminatorKind::FalseEdges {
1106                 real_target: block,
1107                 imaginary_targets: vec![candidate.next_candidate_pre_binding_block],
1108             },
1109         );
1110
1111         // rust-lang/rust#27282: The `autoref` business deserves some
1112         // explanation here.
1113         //
1114         // The intent of the `autoref` flag is that when it is true,
1115         // then any pattern bindings of type T will map to a `&T`
1116         // within the context of the guard expression, but will
1117         // continue to map to a `T` in the context of the arm body. To
1118         // avoid surfacing this distinction in the user source code
1119         // (which would be a severe change to the language and require
1120         // far more revision to the compiler), when `autoref` is true,
1121         // then any occurrence of the identifier in the guard
1122         // expression will automatically get a deref op applied to it.
1123         //
1124         // So an input like:
1125         //
1126         // ```
1127         // let place = Foo::new();
1128         // match place { foo if inspect(foo)
1129         //     => feed(foo), ...  }
1130         // ```
1131         //
1132         // will be treated as if it were really something like:
1133         //
1134         // ```
1135         // let place = Foo::new();
1136         // match place { Foo { .. } if { let tmp1 = &place; inspect(*tmp1) }
1137         //     => { let tmp2 = place; feed(tmp2) }, ... }
1138         //
1139         // And an input like:
1140         //
1141         // ```
1142         // let place = Foo::new();
1143         // match place { ref mut foo if inspect(foo)
1144         //     => feed(foo), ...  }
1145         // ```
1146         //
1147         // will be treated as if it were really something like:
1148         //
1149         // ```
1150         // let place = Foo::new();
1151         // match place { Foo { .. } if { let tmp1 = & &mut place; inspect(*tmp1) }
1152         //     => { let tmp2 = &mut place; feed(tmp2) }, ... }
1153         // ```
1154         //
1155         // In short, any pattern binding will always look like *some*
1156         // kind of `&T` within the guard at least in terms of how the
1157         // MIR-borrowck views it, and this will ensure that guard
1158         // expressions cannot mutate their the match inputs via such
1159         // bindings. (It also ensures that guard expressions can at
1160         // most *copy* values from such bindings; non-Copy things
1161         // cannot be moved via pattern bindings in guard expressions.)
1162         //
1163         // ----
1164         //
1165         // Implementation notes (under assumption `autoref` is true).
1166         //
1167         // To encode the distinction above, we must inject the
1168         // temporaries `tmp1` and `tmp2`.
1169         //
1170         // There are two cases of interest: binding by-value, and binding by-ref.
1171         //
1172         // 1. Binding by-value: Things are simple.
1173         //
1174         //    * Establishing `tmp1` creates a reference into the
1175         //      matched place. This code is emitted by
1176         //      bind_matched_candidate_for_guard.
1177         //
1178         //    * `tmp2` is only initialized "lazily", after we have
1179         //      checked the guard. Thus, the code that can trigger
1180         //      moves out of the candidate can only fire after the
1181         //      guard evaluated to true. This initialization code is
1182         //      emitted by bind_matched_candidate_for_arm.
1183         //
1184         // 2. Binding by-reference: Things are tricky.
1185         //
1186         //    * Here, the guard expression wants a `&&` or `&&mut`
1187         //      into the original input. This means we need to borrow
1188         //      a reference that we do not immediately have at hand
1189         //      (because all we have is the places associated with the
1190         //      match input itself; it is up to us to create a place
1191         //      holding a `&` or `&mut` that we can then borrow).
1192
1193         let autoref = self.hir
1194             .tcx()
1195             .all_pat_vars_are_implicit_refs_within_guards();
1196         if let Some(guard) = candidate.guard {
1197             if autoref {
1198                 self.bind_matched_candidate_for_guard(
1199                     block,
1200                     candidate.pat_index,
1201                     &candidate.bindings,
1202                 );
1203                 let guard_frame = GuardFrame {
1204                     locals: candidate
1205                         .bindings
1206                         .iter()
1207                         .map(|b| GuardFrameLocal::new(b.var_id, b.binding_mode))
1208                         .collect(),
1209                 };
1210                 debug!("Entering guard building context: {:?}", guard_frame);
1211                 self.guard_context.push(guard_frame);
1212             } else {
1213                 self.bind_matched_candidate_for_arm_body(block, &candidate.bindings);
1214             }
1215
1216             // the block to branch to if the guard fails; if there is no
1217             // guard, this block is simply unreachable
1218             let guard = match guard {
1219                 Guard::If(e) => self.hir.mirror(e),
1220             };
1221             let source_info = self.source_info(guard.span);
1222             let cond = unpack!(block = self.as_local_operand(block, guard));
1223             if autoref {
1224                 let guard_frame = self.guard_context.pop().unwrap();
1225                 debug!(
1226                     "Exiting guard building context with locals: {:?}",
1227                     guard_frame
1228                 );
1229             }
1230
1231             let false_edge_block = self.cfg.start_new_block();
1232
1233             // We want to ensure that the matched candidates are bound
1234             // after we have confirmed this candidate *and* any
1235             // associated guard; Binding them on `block` is too soon,
1236             // because that would be before we've checked the result
1237             // from the guard.
1238             //
1239             // But binding them on `arm_block` is *too late*, because
1240             // then all of the candidates for a single arm would be
1241             // bound in the same place, that would cause a case like:
1242             //
1243             // ```rust
1244             // match (30, 2) {
1245             //     (mut x, 1) | (2, mut x) if { true } => { ... }
1246             //     ...                                 // ^^^^^^^ (this is `arm_block`)
1247             // }
1248             // ```
1249             //
1250             // would yield a `arm_block` something like:
1251             //
1252             // ```
1253             // StorageLive(_4);        // _4 is `x`
1254             // _4 = &mut (_1.0: i32);  // this is handling `(mut x, 1)` case
1255             // _4 = &mut (_1.1: i32);  // this is handling `(2, mut x)` case
1256             // ```
1257             //
1258             // and that is clearly not correct.
1259             let post_guard_block = self.cfg.start_new_block();
1260             self.cfg.terminate(
1261                 block,
1262                 source_info,
1263                 TerminatorKind::if_(self.hir.tcx(), cond, post_guard_block, false_edge_block),
1264             );
1265
1266             if autoref {
1267                 self.bind_matched_candidate_for_arm_body(post_guard_block, &candidate.bindings);
1268             }
1269
1270             self.cfg.terminate(
1271                 post_guard_block,
1272                 source_info,
1273                 TerminatorKind::Goto { target: arm_block },
1274             );
1275
1276             let otherwise = self.cfg.start_new_block();
1277
1278             self.cfg.terminate(
1279                 false_edge_block,
1280                 source_info,
1281                 TerminatorKind::FalseEdges {
1282                     real_target: otherwise,
1283                     imaginary_targets: vec![candidate.next_candidate_pre_binding_block],
1284                 },
1285             );
1286             Some(otherwise)
1287         } else {
1288             // (Here, it is not too early to bind the matched
1289             // candidate on `block`, because there is no guard result
1290             // that we have to inspect before we bind them.)
1291             self.bind_matched_candidate_for_arm_body(block, &candidate.bindings);
1292             self.cfg.terminate(
1293                 block,
1294                 candidate_source_info,
1295                 TerminatorKind::Goto { target: arm_block },
1296             );
1297             None
1298         }
1299     }
1300
1301     /// Append `AscribeUserType` statements onto the end of `block`
1302     /// for each ascription
1303     fn ascribe_types<'pat>(
1304         &mut self,
1305         block: BasicBlock,
1306         ascriptions: &[Ascription<'tcx>],
1307     ) {
1308         for ascription in ascriptions {
1309             let source_info = self.source_info(ascription.span);
1310
1311             debug!(
1312                 "adding user ascription at span {:?} of place {:?} and {:?}",
1313                 source_info.span,
1314                 ascription.source,
1315                 ascription.user_ty,
1316             );
1317
1318             self.cfg.push(
1319                 block,
1320                 Statement {
1321                     source_info,
1322                     kind: StatementKind::AscribeUserType(
1323                         ascription.source.clone(),
1324                         ty::Variance::Covariant,
1325                         ascription.user_ty,
1326                     ),
1327                 },
1328             );
1329         }
1330     }
1331
1332     // Only called when all_pat_vars_are_implicit_refs_within_guards,
1333     // and thus all code/comments assume we are in that context.
1334     fn bind_matched_candidate_for_guard(
1335         &mut self,
1336         block: BasicBlock,
1337         pat_index: usize,
1338         bindings: &[Binding<'tcx>],
1339     ) {
1340         debug!(
1341             "bind_matched_candidate_for_guard(block={:?}, pat_index={:?}, bindings={:?})",
1342             block, pat_index, bindings
1343         );
1344
1345         // Assign each of the bindings. Since we are binding for a
1346         // guard expression, this will never trigger moves out of the
1347         // candidate.
1348         let re_empty = self.hir.tcx().types.re_empty;
1349         for binding in bindings {
1350             let source_info = self.source_info(binding.span);
1351
1352             // For each pattern ident P of type T, `ref_for_guard` is
1353             // a reference R: &T pointing to the location matched by
1354             // the pattern, and every occurrence of P within a guard
1355             // denotes *R.
1356             let ref_for_guard =
1357                 self.storage_live_binding(block, binding.var_id, binding.span, RefWithinGuard);
1358             // Question: Why schedule drops if bindings are all
1359             // shared-&'s?  Answer: Because schedule_drop_for_binding
1360             // also emits StorageDead's for those locals.
1361             self.schedule_drop_for_binding(binding.var_id, binding.span, RefWithinGuard);
1362             match binding.binding_mode {
1363                 BindingMode::ByValue => {
1364                     let rvalue = Rvalue::Ref(re_empty, BorrowKind::Shared, binding.source.clone());
1365                     self.cfg
1366                         .push_assign(block, source_info, &ref_for_guard, rvalue);
1367                 }
1368                 BindingMode::ByRef(region, borrow_kind) => {
1369                     // Tricky business: For `ref id` and `ref mut id`
1370                     // patterns, we want `id` within the guard to
1371                     // correspond to a temp of type `& &T` or `& &mut
1372                     // T` (i.e. a "borrow of a borrow") that is
1373                     // implicitly dereferenced.
1374                     //
1375                     // To borrow a borrow, we need that inner borrow
1376                     // to point to. So, create a temp for the inner
1377                     // borrow, and then take a reference to it.
1378                     //
1379                     // Note: the temp created here is *not* the one
1380                     // used by the arm body itself. This eases
1381                     // observing two-phase borrow restrictions.
1382                     let val_for_guard = self.storage_live_binding(
1383                         block,
1384                         binding.var_id,
1385                         binding.span,
1386                         ValWithinGuard(pat_index),
1387                     );
1388                     self.schedule_drop_for_binding(
1389                         binding.var_id,
1390                         binding.span,
1391                         ValWithinGuard(pat_index),
1392                     );
1393
1394                     // rust-lang/rust#27282: We reuse the two-phase
1395                     // borrow infrastructure so that the mutable
1396                     // borrow (whose mutabilty is *unusable* within
1397                     // the guard) does not conflict with the implicit
1398                     // borrow of the whole match input. See additional
1399                     // discussion on rust-lang/rust#49870.
1400                     let borrow_kind = match borrow_kind {
1401                         BorrowKind::Shared
1402                         | BorrowKind::Shallow
1403                         | BorrowKind::Unique => borrow_kind,
1404                         BorrowKind::Mut { .. } => BorrowKind::Mut {
1405                             allow_two_phase_borrow: true,
1406                         },
1407                     };
1408                     let rvalue = Rvalue::Ref(region, borrow_kind, binding.source.clone());
1409                     self.cfg
1410                         .push_assign(block, source_info, &val_for_guard, rvalue);
1411                     let rvalue = Rvalue::Ref(region, BorrowKind::Shared, val_for_guard);
1412                     self.cfg
1413                         .push_assign(block, source_info, &ref_for_guard, rvalue);
1414                 }
1415             }
1416         }
1417     }
1418
1419     fn bind_matched_candidate_for_arm_body(
1420         &mut self,
1421         block: BasicBlock,
1422         bindings: &[Binding<'tcx>],
1423     ) {
1424         debug!(
1425             "bind_matched_candidate_for_arm_body(block={:?}, bindings={:?}",
1426             block, bindings
1427         );
1428
1429         // Assign each of the bindings. This may trigger moves out of the candidate.
1430         for binding in bindings {
1431             let source_info = self.source_info(binding.span);
1432             let local =
1433                 self.storage_live_binding(block, binding.var_id, binding.span, OutsideGuard);
1434             self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard);
1435             let rvalue = match binding.binding_mode {
1436                 BindingMode::ByValue => {
1437                     Rvalue::Use(self.consume_by_copy_or_move(binding.source.clone()))
1438                 }
1439                 BindingMode::ByRef(region, borrow_kind) => {
1440                     Rvalue::Ref(region, borrow_kind, binding.source.clone())
1441                 }
1442             };
1443             self.cfg.push_assign(block, source_info, &local, rvalue);
1444         }
1445     }
1446
1447     /// Each binding (`ref mut var`/`ref var`/`mut var`/`var`, where
1448     /// the bound `var` has type `T` in the arm body) in a pattern
1449     /// maps to `2+N` locals. The first local is a binding for
1450     /// occurrences of `var` in the guard, which will all have type
1451     /// `&T`. The N locals are bindings for the `T` that is referenced
1452     /// by the first local; they are not used outside of the
1453     /// guard. The last local is a binding for occurrences of `var` in
1454     /// the arm body, which will have type `T`.
1455     ///
1456     /// The reason we have N locals rather than just 1 is to
1457     /// accommodate rust-lang/rust#51348: If the arm has N candidate
1458     /// patterns, then in general they can correspond to distinct
1459     /// parts of the matched data, and we want them to be distinct
1460     /// temps in order to simplify checks performed by our internal
1461     /// leveraging of two-phase borrows).
1462     fn declare_binding(
1463         &mut self,
1464         source_info: SourceInfo,
1465         visibility_scope: SourceScope,
1466         mutability: Mutability,
1467         name: Name,
1468         mode: BindingMode,
1469         num_patterns: usize,
1470         var_id: NodeId,
1471         var_ty: Ty<'tcx>,
1472         user_var_ty: Option<CanonicalTy<'tcx>>,
1473         has_guard: ArmHasGuard,
1474         opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
1475         pat_span: Span,
1476     ) {
1477         debug!(
1478             "declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
1479              visibility_scope={:?}, source_info={:?})",
1480             var_id, name, mode, var_ty, visibility_scope, source_info
1481         );
1482
1483         let tcx = self.hir.tcx();
1484         let binding_mode = match mode {
1485             BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
1486             BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()),
1487         };
1488         let local = LocalDecl::<'tcx> {
1489             mutability,
1490             ty: var_ty,
1491             user_ty: user_var_ty,
1492             name: Some(name),
1493             source_info,
1494             visibility_scope,
1495             internal: false,
1496             is_block_tail: None,
1497             is_user_variable: Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
1498                 binding_mode,
1499                 // hypothetically, `visit_bindings` could try to unzip
1500                 // an outermost hir::Ty as we descend, matching up
1501                 // idents in pat; but complex w/ unclear UI payoff.
1502                 // Instead, just abandon providing diagnostic info.
1503                 opt_ty_info: None,
1504                 opt_match_place,
1505                 pat_span,
1506             }))),
1507         };
1508         let for_arm_body = self.local_decls.push(local.clone());
1509         let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() {
1510             let mut vals_for_guard = Vec::with_capacity(num_patterns);
1511             for _ in 0..num_patterns {
1512                 let val_for_guard_idx = self.local_decls.push(LocalDecl {
1513                     // This variable isn't mutated but has a name, so has to be
1514                     // immutable to avoid the unused mut lint.
1515                     mutability: Mutability::Not,
1516                     ..local.clone()
1517                 });
1518                 vals_for_guard.push(val_for_guard_idx);
1519             }
1520             let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
1521                 // See previous comment.
1522                 mutability: Mutability::Not,
1523                 ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
1524                 user_ty: None,
1525                 name: Some(name),
1526                 source_info,
1527                 visibility_scope,
1528                 // FIXME: should these secretly injected ref_for_guard's be marked as `internal`?
1529                 internal: false,
1530                 is_block_tail: None,
1531                 is_user_variable: Some(ClearCrossCrate::Set(BindingForm::RefForGuard)),
1532             });
1533             LocalsForNode::ForGuard {
1534                 vals_for_guard,
1535                 ref_for_guard,
1536                 for_arm_body,
1537             }
1538         } else {
1539             LocalsForNode::One(for_arm_body)
1540         };
1541         debug!("declare_binding: vars={:?}", locals);
1542         self.var_indices.insert(var_id, locals);
1543     }
1544
1545     // Determine the fake borrows that are needed to ensure that the place
1546     // will evaluate to the same thing until an arm has been chosen.
1547     fn add_fake_borrows<'pat>(
1548         &mut self,
1549         pre_binding_blocks: &[(BasicBlock, Span)],
1550         fake_borrows: FxHashMap<Place<'tcx>, BorrowKind>,
1551         source_info: SourceInfo,
1552         start_block: BasicBlock,
1553     ) {
1554         let tcx = self.hir.tcx();
1555
1556         debug!("add_fake_borrows pre_binding_blocks = {:?}, fake_borrows = {:?}",
1557                pre_binding_blocks, fake_borrows);
1558
1559         let mut all_fake_borrows = Vec::with_capacity(fake_borrows.len());
1560
1561         // Insert a Shallow borrow of the prefixes of any fake borrows.
1562         for (place, borrow_kind) in fake_borrows
1563         {
1564             {
1565                 let mut prefix_cursor = &place;
1566                 while let Place::Projection(box Projection { base, elem }) = prefix_cursor {
1567                     if let ProjectionElem::Deref = elem {
1568                         // Insert a shallow borrow after a deref. For other
1569                         // projections the borrow of prefix_cursor will
1570                         // conflict with any mutation of base.
1571                         all_fake_borrows.push((base.clone(), BorrowKind::Shallow));
1572                     }
1573                     prefix_cursor = base;
1574                 }
1575             }
1576
1577             all_fake_borrows.push((place, borrow_kind));
1578         }
1579
1580         // Deduplicate and ensure a deterministic order.
1581         all_fake_borrows.sort();
1582         all_fake_borrows.dedup();
1583
1584         debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);
1585
1586         // Add fake borrows to the start of the match and reads of them before
1587         // the start of each arm.
1588         let mut borrowed_input_temps = Vec::with_capacity(all_fake_borrows.len());
1589
1590         for (matched_place, borrow_kind) in all_fake_borrows {
1591             let borrowed_input =
1592                 Rvalue::Ref(tcx.types.re_empty, borrow_kind, matched_place.clone());
1593             let borrowed_input_ty = borrowed_input.ty(&self.local_decls, tcx);
1594             let borrowed_input_temp = self.temp(borrowed_input_ty, source_info.span);
1595             self.cfg.push_assign(
1596                 start_block,
1597                 source_info,
1598                 &borrowed_input_temp,
1599                 borrowed_input
1600             );
1601             borrowed_input_temps.push(borrowed_input_temp);
1602         }
1603
1604         // FIXME: This could be a lot of reads (#fake borrows * #patterns).
1605         // The false edges that we currently generate would allow us to only do
1606         // this on the last Candidate, but it's possible that there might not be
1607         // so many false edges in the future, so we read for all Candidates for
1608         // now.
1609         // Another option would be to make our own block and add our own false
1610         // edges to it.
1611         if tcx.emit_read_for_match() {
1612             for &(pre_binding_block, span) in pre_binding_blocks {
1613                 let pattern_source_info = self.source_info(span);
1614                 for temp in &borrowed_input_temps {
1615                     self.cfg.push(pre_binding_block, Statement {
1616                         source_info: pattern_source_info,
1617                         kind: StatementKind::FakeRead(
1618                             FakeReadCause::ForMatchGuard,
1619                             temp.clone(),
1620                         ),
1621                     });
1622                 }
1623             }
1624         }
1625     }
1626 }