]> git.lizzy.rs Git - rust.git/commitdiff
forbid moves out of slices
authorAriel Ben-Yehuda <ariel.byd@gmail.com>
Sun, 24 Jul 2016 10:56:27 +0000 (13:56 +0300)
committerAriel Ben-Yehuda <arielb1@mail.tau.ac.il>
Fri, 16 Sep 2016 12:08:32 +0000 (15:08 +0300)
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.

src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
src/librustc_borrowck/borrowck/gather_loans/move_error.rs
src/test/compile-fail/move-out-of-slice-1.rs [new file with mode: 0644]

index 3e335dacc8ed9f7a6698159cbc6ec4ef7ea9ebca..9bdc6887f6d03e74680a3a74fbb9a31d480f1926 100644 (file)
@@ -185,6 +185,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                         check_and_get_illegal_move_origin(bccx, b)
                     }
                 }
+                ty::TySlice(..) => Some(cmt.clone()),
                 _ => {
                     check_and_get_illegal_move_origin(bccx, b)
                 }
index 3fa7c252b842ce886701397c0301316eb0eda71f..9fbf1492f5d2884b869390e0192a68b5407c5956 100644 (file)
@@ -16,7 +16,6 @@
 use syntax::ast;
 use syntax_pos;
 use errors::DiagnosticBuilder;
-use rustc::hir;
 
 pub struct MoveErrorCollector<'tcx> {
     errors: Vec<MoveError<'tcx>>
@@ -131,17 +130,20 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
             err
         }
 
-        Categorization::Interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
-            let expr = bccx.tcx.map.expect_expr(move_from.id);
-            if let hir::ExprIndex(..) = expr.node {
-                let mut err = struct_span_err!(bccx, move_from.span, E0508,
-                                               "cannot move out of type `{}`, \
-                                               a non-copy fixed-size array",
-                                               b.ty);
-                err.span_label(move_from.span, &format!("cannot move out of here"));
-                err
-            } else {
-                span_bug!(move_from.span, "this path should not cause illegal move");
+        Categorization::Interior(ref b, mc::InteriorElement(ik, _)) => {
+            match (&b.ty.sty, ik) {
+                (&ty::TySlice(..), _) |
+                (_, Kind::Index) => {
+                    let mut err = struct_span_err!(bccx, move_from.span, E0508,
+                                                   "cannot move out of type `{}`, \
+                                                    a non-copy array",
+                                                   b.ty);
+                    err.span_label(move_from.span, &format!("cannot move out of here"));
+                    err
+                }
+                (_, Kind::Pattern) => {
+                    span_bug!(move_from.span, "this path should not cause illegal move");
+                }
             }
         }
 
diff --git a/src/test/compile-fail/move-out-of-slice-1.rs b/src/test/compile-fail/move-out-of-slice-1.rs
new file mode 100644 (file)
index 0000000..f3efc68
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2016 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.
+
+#![feature(slice_patterns, box_patterns)]
+
+struct A;
+
+fn main() {
+    let a: Box<[A]> = Box::new([A]);
+    match a {
+        box [a] => {}, //~ ERROR cannot move out of type `[A]`
+        _ => {}
+    }
+}