Skip to content

Commit 8a28c67

Browse files
author
Your Name
committed
MIR-borrowck: add false edges to match arms
1 parent 264aafe commit 8a28c67

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed

src/librustc_mir/build/matches/mod.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc::mir::*;
2121
use rustc::hir;
2222
use hair::*;
2323
use syntax::ast::{Name, NodeId};
24-
use syntax_pos::Span;
24+
use syntax_pos::{DUMMY_SP, Span};
2525

2626
// helper functions, broken out by category:
2727
mod simplify;
@@ -398,10 +398,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
398398
candidates.iter().take_while(|c| c.match_pairs.is_empty()).count();
399399
debug!("match_candidates: {:?} candidates fully matched", fully_matched);
400400
let mut unmatched_candidates = candidates.split_off(fully_matched);
401-
for candidate in candidates {
401+
for (index, candidate) in candidates.into_iter().enumerate() {
402402
// If so, apply any bindings, test the guard (if any), and
403403
// 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) {
405407
block = b;
406408
} else {
407409
// if None is returned, then any remaining candidates
@@ -664,7 +666,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
664666
fn bind_and_guard_matched_candidate<'pat>(&mut self,
665667
mut block: BasicBlock,
666668
arm_blocks: &mut ArmBlocks,
667-
candidate: Candidate<'pat, 'tcx>)
669+
candidate: Candidate<'pat, 'tcx>,
670+
is_last_arm: bool)
668671
-> Option<BasicBlock> {
669672
debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
670673
block, candidate);
@@ -685,10 +688,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
685688
self.cfg.terminate(block, source_info,
686689
TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
687690
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)
688707
} else {
689708
let source_info = self.source_info(candidate.span);
690709
self.cfg.terminate(block, source_info,
691-
TerminatorKind::Goto { target: arm_block });
710+
TerminatorKind::Goto { target: arm_block });
692711
None
693712
}
694713
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
// revisions: ast mir
12+
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
13+
14+
fn main() {
15+
let mut x = 1;
16+
let _x = &mut x;
17+
let _ = match x {
18+
x => x + 1, //[ast]~ ERROR E0503
19+
//[mir]~^ ERROR (Mir) [E0503]
20+
//[mir]~| ERROR (Ast) [E0503]
21+
y => y + 2, //[ast]~ ERROR [E0503]
22+
//[mir]~^ ERROR (Mir) [E0503]
23+
//[mir]~| ERROR (Ast) [E0503]
24+
};
25+
}

0 commit comments

Comments
 (0)