@@ -21,7 +21,7 @@ use rustc::mir::*;
21
21
use rustc:: hir;
22
22
use hair:: * ;
23
23
use syntax:: ast:: { Name , NodeId } ;
24
- use syntax_pos:: Span ;
24
+ use syntax_pos:: { DUMMY_SP , Span } ;
25
25
26
26
// helper functions, broken out by category:
27
27
mod simplify;
@@ -398,10 +398,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
398
398
candidates. iter ( ) . take_while ( |c| c. match_pairs . is_empty ( ) ) . count ( ) ;
399
399
debug ! ( "match_candidates: {:?} candidates fully matched" , fully_matched) ;
400
400
let mut unmatched_candidates = candidates. split_off ( fully_matched) ;
401
- for candidate in candidates {
401
+ for ( index , candidate) in candidates. into_iter ( ) . enumerate ( ) {
402
402
// If so, apply any bindings, test the guard (if any), and
403
403
// branch to the arm.
404
- if let Some ( b) = self . bind_and_guard_matched_candidate ( block, arm_blocks, candidate) {
404
+ let is_last = index == fully_matched - 1 ;
405
+ if let Some ( b) = self . bind_and_guard_matched_candidate ( block, arm_blocks,
406
+ candidate, is_last) {
405
407
block = b;
406
408
} else {
407
409
// if None is returned, then any remaining candidates
@@ -664,7 +666,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
664
666
fn bind_and_guard_matched_candidate < ' pat > ( & mut self ,
665
667
mut block : BasicBlock ,
666
668
arm_blocks : & mut ArmBlocks ,
667
- candidate : Candidate < ' pat , ' tcx > )
669
+ candidate : Candidate < ' pat , ' tcx > ,
670
+ is_last_arm : bool )
668
671
-> Option < BasicBlock > {
669
672
debug ! ( "bind_and_guard_matched_candidate(block={:?}, candidate={:?})" ,
670
673
block, candidate) ;
@@ -685,10 +688,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
685
688
self . cfg . terminate ( block, source_info,
686
689
TerminatorKind :: if_ ( self . hir . tcx ( ) , cond, arm_block, otherwise) ) ;
687
690
Some ( otherwise)
691
+ } else if !is_last_arm {
692
+ // Add always true guard in case of more than one arm
693
+ // it creates false edges and allow MIR borrowck detects errors
694
+ // FIXME(#45184) -- permit "false edges"
695
+ let source_info = self . source_info ( candidate. span ) ;
696
+ let true_expr = Expr {
697
+ temp_lifetime : None ,
698
+ ty : self . hir . tcx ( ) . types . bool ,
699
+ span : DUMMY_SP ,
700
+ kind : ExprKind :: Literal { literal : self . hir . true_literal ( ) } ,
701
+ } ;
702
+ let cond = unpack ! ( block = self . as_local_operand( block, true_expr) ) ;
703
+ let otherwise = self . cfg . start_new_block ( ) ;
704
+ self . cfg . terminate ( block, source_info,
705
+ TerminatorKind :: if_ ( self . hir . tcx ( ) , cond, arm_block, otherwise) ) ;
706
+ Some ( otherwise)
688
707
} else {
689
708
let source_info = self . source_info ( candidate. span ) ;
690
709
self . cfg . terminate ( block, source_info,
691
- TerminatorKind :: Goto { target : arm_block } ) ;
710
+ TerminatorKind :: Goto { target : arm_block } ) ;
692
711
None
693
712
}
694
713
}
0 commit comments