Skip to content

Commit 7b25e88

Browse files
arielb1Ariel Ben-Yehuda
authored and
Ariel Ben-Yehuda
committed
forbid moves out of slices
The wording of RFC #495 enables moves out of slices. Unfortuantely, non-zeroing moves out of slices introduce a very annoying complication: as slices can vary in their length, indexes from the start and end may or may not overlap depending on the slice's exact length, which prevents assigning a particular drop flag for each individual element. For example, in the code ```Rust fn foo<T>(a: Box<[Box<[T]>]>, c: bool) -> T { match (a, c) { (box [box [t, ..], ..], true) => t, (box [.., box [.., t]], false) => t, _ => panic!() } } ``` If the condition is false, we have to drop the first element of `a`, unless `a` has size 1 in which case we drop all the elements of it but the last. If someone comes with a nice way of handling it, we can always re-allow moves out of slices. This is a [breaking-change], but it is behind the `slice_patterns` feature gate and was not allowed until recently.
1 parent eb19cd6 commit 7b25e88

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
185185
check_and_get_illegal_move_origin(bccx, b)
186186
}
187187
}
188+
ty::TySlice(..) => Some(cmt.clone()),
188189
_ => {
189190
check_and_get_illegal_move_origin(bccx, b)
190191
}

src/librustc_borrowck/borrowck/gather_loans/move_error.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc::ty;
1616
use syntax::ast;
1717
use syntax_pos;
1818
use errors::DiagnosticBuilder;
19-
use rustc::hir;
2019

2120
pub struct MoveErrorCollector<'tcx> {
2221
errors: Vec<MoveError<'tcx>>
@@ -131,17 +130,20 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
131130
err
132131
}
133132

134-
Categorization::Interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
135-
let expr = bccx.tcx.map.expect_expr(move_from.id);
136-
if let hir::ExprIndex(..) = expr.node {
137-
let mut err = struct_span_err!(bccx, move_from.span, E0508,
138-
"cannot move out of type `{}`, \
139-
a non-copy fixed-size array",
140-
b.ty);
141-
err.span_label(move_from.span, &format!("cannot move out of here"));
142-
err
143-
} else {
144-
span_bug!(move_from.span, "this path should not cause illegal move");
133+
Categorization::Interior(ref b, mc::InteriorElement(ik, _)) => {
134+
match (&b.ty.sty, ik) {
135+
(&ty::TySlice(..), _) |
136+
(_, Kind::Index) => {
137+
let mut err = struct_span_err!(bccx, move_from.span, E0508,
138+
"cannot move out of type `{}`, \
139+
a non-copy array",
140+
b.ty);
141+
err.span_label(move_from.span, &format!("cannot move out of here"));
142+
err
143+
}
144+
(_, Kind::Pattern) => {
145+
span_bug!(move_from.span, "this path should not cause illegal move");
146+
}
145147
}
146148
}
147149

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2016 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+
#![feature(slice_patterns, box_patterns)]
12+
13+
struct A;
14+
15+
fn main() {
16+
let a: Box<[A]> = Box::new([A]);
17+
match a {
18+
box [a] => {}, //~ ERROR cannot move out of type `[A]`
19+
_ => {}
20+
}
21+
}

0 commit comments

Comments
 (0)