Skip to content

disable multiple-match slice patterns #32161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,17 +663,6 @@ pub enum Rvalue<'tcx> {
/// away after type-checking and before lowering.
Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),

/// Generates a slice of the form `&input[from_start..L-from_end]`
/// where `L` is the length of the slice. This is only created by
/// slice pattern matching, so e.g. a pattern of the form `[x, y,
/// .., z]` might create a slice with `from_start=2` and
/// `from_end=1`.
Slice {
input: Lvalue<'tcx>,
from_start: usize,
from_end: usize,
},

InlineAsm(InlineAsm),
}

Expand Down Expand Up @@ -760,9 +749,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
Box(ref t) => write!(fmt, "Box({:?})", t),
InlineAsm(ref asm) => write!(fmt, "InlineAsm({:?})", asm),
Slice { ref input, from_start, from_end } =>
write!(fmt, "{:?}[{:?}..-{:?}]", input, from_start, from_end),

Ref(_, borrow_kind, ref lv) => {
let kind_str = match borrow_kind {
BorrowKind::Shared => "",
Expand Down
1 change: 0 additions & 1 deletion src/librustc/mir/tcx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ impl<'tcx> Mir<'tcx> {
}
}
}
Rvalue::Slice { .. } => None,
Rvalue::InlineAsm(..) => None
}
}
Expand Down
9 changes: 0 additions & 9 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,15 +252,6 @@ macro_rules! make_mir_visitor {
}
}

Rvalue::Slice { ref $($mutability)* input,
from_start,
from_end } => {
self.visit_lvalue(input, LvalueContext::Slice {
from_start: from_start,
from_end: from_end,
});
}

Rvalue::InlineAsm(_) => {
}
}
Expand Down
18 changes: 11 additions & 7 deletions src/librustc_mir/build/matches/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
/// possible, Err is returned and no changes are made to
/// candidate.
fn simplify_match_pair<'pat>(&mut self,
mut block: BasicBlock,
block: BasicBlock,
match_pair: MatchPair<'pat, 'tcx>,
candidate: &mut Candidate<'pat, 'tcx>)
-> Result<BasicBlock, MatchPair<'pat, 'tcx>> {
Expand Down Expand Up @@ -96,12 +96,16 @@ impl<'a,'tcx> Builder<'a,'tcx> {
}

PatternKind::Array { ref prefix, ref slice, ref suffix } => {
unpack!(block = self.prefix_suffix_slice(&mut candidate.match_pairs,
block,
match_pair.lvalue.clone(),
prefix,
slice.as_ref(),
suffix));
if let Some(ref slice) = *slice {
match *slice.kind {
PatternKind::Wild => {},
_ => panic!("bad slice pattern {:?}", slice)
}
}
self.prefix_suffix(&mut candidate.match_pairs,
match_pair.lvalue.clone(),
prefix,
suffix);
Ok(block)
}

Expand Down
54 changes: 6 additions & 48 deletions src/librustc_mir/build/matches/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use build::{BlockAnd, BlockAndExtension, Builder};
use build::Builder;
use build::matches::MatchPair;
use hair::*;
use rustc::mir::repr::*;
Expand All @@ -28,54 +28,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
.collect()
}

/// When processing an array/slice pattern like `lv @ [x, y, ..s, z]`,
/// this function converts the prefix (`x`, `y`) and suffix (`z`) into
/// distinct match pairs:
///
/// lv[0 of 3] @ x // see ProjectionElem::ConstantIndex (and its Debug impl)
/// lv[1 of 3] @ y // to explain the `[x of y]` notation
/// lv[-1 of 3] @ z
///
/// If a slice like `s` is present, then the function also creates
/// a temporary like:
///
/// tmp0 = lv[2..-1] // using the special Rvalue::Slice
///
/// and creates a match pair `tmp0 @ s`
pub fn prefix_suffix_slice<'pat>(&mut self,
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
block: BasicBlock,
lvalue: Lvalue<'tcx>,
prefix: &'pat [Pattern<'tcx>],
opt_slice: Option<&'pat Pattern<'tcx>>,
suffix: &'pat [Pattern<'tcx>])
-> BlockAnd<()> {
// If there is a `..P` pattern, create a temporary `t0` for
// the slice and then a match pair `t0 @ P`:
if let Some(slice) = opt_slice {
let prefix_len = prefix.len();
let suffix_len = suffix.len();
let rvalue = Rvalue::Slice {
input: lvalue.clone(),
from_start: prefix_len,
from_end: suffix_len,
};
let temp = self.temp(slice.ty.clone()); // no need to schedule drop, temp is always copy
self.cfg.push_assign(block, slice.span, &temp, rvalue);
match_pairs.push(MatchPair::new(temp, slice));
}

self.prefix_suffix(match_pairs, lvalue, prefix, suffix);

block.unit()
}

/// Helper for `prefix_suffix_slice` which just processes the prefix and suffix.
fn prefix_suffix<'pat>(&mut self,
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
lvalue: Lvalue<'tcx>,
prefix: &'pat [Pattern<'tcx>],
suffix: &'pat [Pattern<'tcx>]) {
pub fn prefix_suffix<'pat>(&mut self,
match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
lvalue: Lvalue<'tcx>,
prefix: &'pat [Pattern<'tcx>],
suffix: &'pat [Pattern<'tcx>]) {
let min_length = prefix.len() + suffix.len();
assert!(min_length < u32::MAX as usize);
let min_length = min_length as u32;
Expand Down
1 change: 0 additions & 1 deletion src/librustc_mir/transform/erase_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
Rvalue::Len(_) |
Rvalue::BinaryOp(_, _, _) |
Rvalue::UnaryOp(_, _) |
Rvalue::Slice { input: _, from_start: _, from_end: _ } |
Rvalue::InlineAsm(_) => {},

Rvalue::Repeat(_, ref mut value) => value.ty = self.tcx.erase_regions(&value.ty),
Expand Down
21 changes: 0 additions & 21 deletions src/librustc_trans/trans/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,25 +145,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
bcx
}

mir::Rvalue::Slice { ref input, from_start, from_end } => {
let ccx = bcx.ccx();
let input = self.trans_lvalue(&bcx, input);
let (llbase, lllen) = bcx.with_block(|bcx| {
tvec::get_base_and_len(bcx,
input.llval,
input.ty.to_ty(bcx.tcx()))
});
let llbase1 = bcx.gepi(llbase, &[from_start]);
let adj = common::C_uint(ccx, from_start + from_end);
let lllen1 = bcx.sub(lllen, adj);
let (lladdrdest, llmetadest) = bcx.with_block(|bcx| {
(expr::get_dataptr(bcx, dest.llval), expr::get_meta(bcx, dest.llval))
});
bcx.store(llbase1, lladdrdest);
bcx.store(lllen1, llmetadest);
bcx
}

mir::Rvalue::InlineAsm(ref inline_asm) => {
bcx.map_block(|bcx| {
asm::trans_inline_asm(bcx, inline_asm)
Expand Down Expand Up @@ -432,7 +413,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
mir::Rvalue::Use(..) |
mir::Rvalue::Repeat(..) |
mir::Rvalue::Aggregate(..) |
mir::Rvalue::Slice { .. } |
mir::Rvalue::InlineAsm(..) => {
bcx.tcx().sess.bug(&format!("cannot generate operand from rvalue {:?}", rvalue));
}
Expand Down Expand Up @@ -557,7 +537,6 @@ pub fn rvalue_creates_operand<'tcx>(rvalue: &mir::Rvalue<'tcx>) -> bool {
mir::Rvalue::Use(..) | // (**)
mir::Rvalue::Repeat(..) |
mir::Rvalue::Aggregate(..) |
mir::Rvalue::Slice { .. } |
mir::Rvalue::InlineAsm(..) =>
false,
}
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,11 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
check_pat(pcx, &elt, inner_ty);
}
if let Some(ref slice) = *slice {
if slice.node != PatKind::Wild {
tcx.sess.span_err(slice.span,
"multi-element slice patterns are badly broken");
}

let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
let mutbl = expected_ty.builtin_deref(true, ty::NoPreference)
.map_or(hir::MutImmutable, |mt| mt.mutbl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ pub fn main() {
);
let x: &[Foo] = &x;
match x {
[_, tail..] => {
[_, tail..] => { //~ ERROR slice patterns are badly broken
match tail {
[Foo { string: a }, //~ ERROR cannot move out of borrowed content
[Foo { string: a }, //# ERROR cannot move out of borrowed content
Foo { string: b }] => {
//~^^ NOTE attempting to move value to here
//~^^ NOTE and here
//#^^ NOTE attempting to move value to here
//#^^ NOTE and here
}
_ => {
unreachable!();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,29 @@

fn a<'a>() -> &'a [isize] {
let vec = vec!(1, 2, 3, 4);
let vec: &[isize] = &vec; //~ ERROR does not live long enough
let vec: &[isize] = &vec; //# ERROR does not live long enough
let tail = match vec {
[_, tail..] => tail,
[_, tail..] => tail, //~ ERROR slice patterns are badly broken
_ => panic!("a")
};
tail
}

fn b<'a>() -> &'a [isize] {
let vec = vec!(1, 2, 3, 4);
let vec: &[isize] = &vec; //~ ERROR does not live long enough
let vec: &[isize] = &vec; //# ERROR does not live long enough
let init = match vec {
[init.., _] => init,
[init.., _] => init, //~ ERROR slice patterns are badly broken
_ => panic!("b")
};
init
}

fn c<'a>() -> &'a [isize] {
let vec = vec!(1, 2, 3, 4);
let vec: &[isize] = &vec; //~ ERROR does not live long enough
let vec: &[isize] = &vec; //# ERROR does not live long enough
let slice = match vec {
[_, slice.., _] => slice,
[_, slice.., _] => slice, //~ ERROR slice patterns are badly broken
_ => panic!("c")
};
slice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ fn a() {
let mut v = vec!(1, 2, 3);
let vb: &mut [isize] = &mut v;
match vb {
[_a, tail..] => {
v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
[_a, tail..] => { //~ ERROR slice patterns are badly broken
v.push(tail[0] + tail[1]); //# ERROR cannot borrow
}
_ => {}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ fn main() {
let mut a = [1, 2, 3, 4];
let t = match a {
[1, 2, tail..] => tail,
//~^ ERROR slice patterns are badly broken
_ => unreachable!()
};
println!("t[0]: {}", t[0]);
a[2] = 0; //~ ERROR cannot assign to `a[..]` because it is borrowed
a[2] = 0; //# ERROR cannot assign to `a[..]` because it is borrowed
println!("t[0]: {}", t[0]);
t[0];
}
32 changes: 17 additions & 15 deletions src/test/compile-fail/borrowck/borrowck-vec-pattern-nesting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fn a() {
let mut vec = [box 1, box 2, box 3];
match vec {
[box ref _a, _, _] => {
vec[0] = box 4; //~ ERROR cannot assign
vec[0] = box 4; //# ERROR cannot assign
}
}
}
Expand All @@ -26,8 +26,8 @@ fn b() {
let mut vec = vec!(box 1, box 2, box 3);
let vec: &mut [Box<isize>] = &mut vec;
match vec {
[_b..] => {
vec[0] = box 4; //~ ERROR cannot assign
[_b..] => { //~ ERROR slice patterns are badly broken
vec[0] = box 4; //# ERROR cannot assign
}
}
}
Expand All @@ -36,8 +36,9 @@ fn c() {
let mut vec = vec!(box 1, box 2, box 3);
let vec: &mut [Box<isize>] = &mut vec;
match vec {
[_a, //~ ERROR cannot move out
_b..] => { //~^ NOTE attempting to move value to here
[_a, //# ERROR cannot move out
_b..] => { //#^ NOTE attempting to move value to here
//~^ ERROR slice patterns are badly broken

// Note: `_a` is *moved* here, but `b` is borrowing,
// hence illegal.
Expand All @@ -47,32 +48,33 @@ fn c() {
}
_ => {}
}
let a = vec[0]; //~ ERROR cannot move out
let a = vec[0]; //# ERROR cannot move out
}

fn d() {
let mut vec = vec!(box 1, box 2, box 3);
let vec: &mut [Box<isize>] = &mut vec;
match vec {
[_a.., //~ ERROR cannot move out
_b] => {} //~ NOTE attempting to move value to here
[_a.., //# ERROR cannot move out
_b] => {} //# NOTE attempting to move value to here
//~^^ ERROR slice patterns are badly broken
_ => {}
}
let a = vec[0]; //~ ERROR cannot move out
let a = vec[0]; //# ERROR cannot move out
}

fn e() {
let mut vec = vec!(box 1, box 2, box 3);
let vec: &mut [Box<isize>] = &mut vec;
match vec {
[_a, _b, _c] => {} //~ ERROR cannot move out
//~^ NOTE attempting to move value to here
//~^^ NOTE and here
//~^^^ NOTE and here
[_a, _b, _c] => {} //# ERROR cannot move out
//#^ NOTE attempting to move value to here
//#^^ NOTE and here
//#^^^ NOTE and here
_ => {}
}
let a = vec[0]; //~ ERROR cannot move out
//~^ NOTE attempting to move value to here
let a = vec[0]; //# ERROR cannot move out
//#^ NOTE attempting to move value to here
}

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@

fn a<'a>() -> &'a isize {
let vec = vec!(1, 2, 3, 4);
let vec: &[isize] = &vec; //~ ERROR `vec` does not live long enough
let vec: &[isize] = &vec; //# ERROR `vec` does not live long enough
let tail = match vec {
[_a, tail..] => &tail[0],
//~^ ERROR slice patterns are badly broken
_ => panic!("foo")
};
tail
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/feature-gate-slice-patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
fn main() {
let x = [1, 2, 3, 4, 5];
match x {
[1, 2, xs..] => {} //~ ERROR slice pattern syntax is experimental
[1, 2, 3, 4, xs] => {} //~ ERROR slice pattern syntax is experimental
}
}
4 changes: 3 additions & 1 deletion src/test/compile-fail/issue-12369.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ fn main() {
[] => 0,
[a,b,c] => 3,
[a, rest..] => a,
[10,a, rest..] => 10 //~ ERROR: unreachable pattern
//~^ ERROR slice patterns are badly broken
[10,a, rest..] => 10 //# ERROR: unreachable pattern
//~^ ERROR slice patterns are badly broken
};
}
Loading