diff options
| author | bors <bors@rust-lang.org> | 2017-10-15 02:20:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-10-15 02:20:13 +0000 |
| commit | f5eb33f4e5ea2b78cfcc34cc42dda8701b2a0f85 (patch) | |
| tree | eb19a929d88e0a63be9c1a4057c0329faacbfbcc /src | |
| parent | a457e298115fd1811f3b5c4ec889067279b218f7 (diff) | |
| parent | 8a28c676c89173a88c2568deb8964e0960f2afb6 (diff) | |
| download | rust-f5eb33f4e5ea2b78cfcc34cc42dda8701b2a0f85.tar.gz rust-f5eb33f4e5ea2b78cfcc34cc42dda8701b2a0f85.zip | |
Auto merge of #45200 - mikhail-m1:match-with-false-edges, r=nikomatsakis
MIR-borrowck: add false edges to match arms basic fix for https://github.com/rust-lang/rust/issues/45043, should be modified with #45184
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/build/matches/mod.rs | 29 | ||||
| -rw-r--r-- | src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs | 25 |
2 files changed, 49 insertions, 5 deletions
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index f04dede6e40..56c926eaa61 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -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 } } diff --git a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs new file mode 100644 index 00000000000..1d21f40fcca --- /dev/null +++ b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs @@ -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] + }; +} |
