MIR-borrowck: add false edges to match arms
This commit is contained in:
parent
264aafe056
commit
8a28c676c8
2 changed files with 49 additions and 5 deletions
|
@ -21,7 +21,7 @@ use rustc::mir::*;
|
|||
use rustc::hir;
|
||||
use hair::*;
|
||||
use syntax::ast::{Name, NodeId};
|
||||
use syntax_pos::Span;
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
|
||||
// helper functions, broken out by category:
|
||||
mod simplify;
|
||||
|
@ -398,10 +398,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
candidates.iter().take_while(|c| c.match_pairs.is_empty()).count();
|
||||
debug!("match_candidates: {:?} candidates fully matched", fully_matched);
|
||||
let mut unmatched_candidates = candidates.split_off(fully_matched);
|
||||
for candidate in candidates {
|
||||
for (index, candidate) in candidates.into_iter().enumerate() {
|
||||
// If so, apply any bindings, test the guard (if any), and
|
||||
// branch to the arm.
|
||||
if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, candidate) {
|
||||
let is_last = index == fully_matched - 1;
|
||||
if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks,
|
||||
candidate, is_last) {
|
||||
block = b;
|
||||
} else {
|
||||
// if None is returned, then any remaining candidates
|
||||
|
@ -664,7 +666,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
fn bind_and_guard_matched_candidate<'pat>(&mut self,
|
||||
mut block: BasicBlock,
|
||||
arm_blocks: &mut ArmBlocks,
|
||||
candidate: Candidate<'pat, 'tcx>)
|
||||
candidate: Candidate<'pat, 'tcx>,
|
||||
is_last_arm: bool)
|
||||
-> Option<BasicBlock> {
|
||||
debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
|
||||
block, candidate);
|
||||
|
@ -685,10 +688,26 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
self.cfg.terminate(block, source_info,
|
||||
TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
|
||||
Some(otherwise)
|
||||
} else if !is_last_arm {
|
||||
// Add always true guard in case of more than one arm
|
||||
// it creates false edges and allow MIR borrowck detects errors
|
||||
// FIXME(#45184) -- permit "false edges"
|
||||
let source_info = self.source_info(candidate.span);
|
||||
let true_expr = Expr {
|
||||
temp_lifetime: None,
|
||||
ty: self.hir.tcx().types.bool,
|
||||
span: DUMMY_SP,
|
||||
kind: ExprKind::Literal{literal: self.hir.true_literal()},
|
||||
};
|
||||
let cond = unpack!(block = self.as_local_operand(block, true_expr));
|
||||
let otherwise = self.cfg.start_new_block();
|
||||
self.cfg.terminate(block, source_info,
|
||||
TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
|
||||
Some(otherwise)
|
||||
} else {
|
||||
let source_info = self.source_info(candidate.span);
|
||||
self.cfg.terminate(block, source_info,
|
||||
TerminatorKind::Goto { target: arm_block });
|
||||
TerminatorKind::Goto { target: arm_block });
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// revisions: ast mir
|
||||
//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
|
||||
|
||||
fn main() {
|
||||
let mut x = 1;
|
||||
let _x = &mut x;
|
||||
let _ = match x {
|
||||
x => x + 1, //[ast]~ ERROR E0503
|
||||
//[mir]~^ ERROR (Mir) [E0503]
|
||||
//[mir]~| ERROR (Ast) [E0503]
|
||||
y => y + 2, //[ast]~ ERROR [E0503]
|
||||
//[mir]~^ ERROR (Mir) [E0503]
|
||||
//[mir]~| ERROR (Ast) [E0503]
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue