about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <bjorn3@users.noreply.github.com>2020-01-11 14:15:24 +0100
committerbjorn3 <bjorn3@users.noreply.github.com>2020-01-11 14:28:18 +0100
commit2a082209a68703915ffe10c913d30f274bf76fa7 (patch)
tree572179f3c9f514deb34a64062cbec17479d0365e
parent0080f55df2fb00a8934f064a3d9f4db3b0cc48db (diff)
downloadrust-2a082209a68703915ffe10c913d30f274bf76fa7.tar.gz
rust-2a082209a68703915ffe10c913d30f274bf76fa7.zip
Fix PlaceElem::Subslice length computation
-rw-r--r--example/subslice-patterns-const-eval.rs99
-rw-r--r--src/base.rs2
-rwxr-xr-xtest.sh4
3 files changed, 104 insertions, 1 deletions
diff --git a/example/subslice-patterns-const-eval.rs b/example/subslice-patterns-const-eval.rs
new file mode 100644
index 00000000000..ec3614bb34a
--- /dev/null
+++ b/example/subslice-patterns-const-eval.rs
@@ -0,0 +1,99 @@
+// Based on https://github.com/rust-lang/rust/blob/c5840f9d252c2f5cc16698dbf385a29c5de3ca07/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
+
+// Test that array subslice patterns are correctly handled in const evaluation.
+
+// run-pass
+
+#![feature(slice_patterns)]
+
+#[derive(PartialEq, Debug, Clone)]
+struct N(u8);
+
+#[derive(PartialEq, Debug, Clone)]
+struct Z;
+
+macro_rules! n {
+    ($($e:expr),* $(,)?) => {
+        [$(N($e)),*]
+    }
+}
+
+// This macro has an unused variable so that it can be repeated base on the
+// number of times a repeated variable (`$e` in `z`) occurs.
+macro_rules! zed {
+    ($e:expr) => { Z }
+}
+
+macro_rules! z {
+    ($($e:expr),* $(,)?) => {
+        [$(zed!($e)),*]
+    }
+}
+
+// Compare constant evaluation and runtime evaluation of a given expression.
+macro_rules! compare_evaluation {
+    ($e:expr, $t:ty $(,)?) => {{
+        const CONST_EVAL: $t = $e;
+        const fn const_eval() -> $t { $e }
+        static CONST_EVAL2: $t = const_eval();
+        let runtime_eval = $e;
+        assert_eq!(CONST_EVAL, runtime_eval);
+        assert_eq!(CONST_EVAL2, runtime_eval);
+    }}
+}
+
+// Repeat `$test`, substituting the given macro variables with the given
+// identifiers.
+//
+// For example:
+//
+// repeat! {
+//     ($name); X; Y:
+//     struct $name;
+// }
+//
+// Expands to:
+//
+// struct X; struct Y;
+//
+// This is used to repeat the tests using both the `N` and `Z`
+// types.
+macro_rules! repeat {
+    (($($dollar:tt $placeholder:ident)*); $($($values:ident),+);*: $($test:tt)*) => {
+        macro_rules! single {
+            ($($dollar $placeholder:ident),*) => { $($test)* }
+        }
+        $(single!($($values),+);)*
+    }
+}
+
+fn main() {
+    repeat! {
+        ($arr $Ty); n, N; z, Z:
+        compare_evaluation!({ let [_, x @ .., _] = $arr!(1, 2, 3, 4); x }, [$Ty; 2]);
+        compare_evaluation!({ let [_, ref x @ .., _] = $arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]);
+        compare_evaluation!({ let [_, x @ .., _] = &$arr!(1, 2, 3, 4); x }, &'static [$Ty; 2]);
+
+        compare_evaluation!({ let [_, _, x @ .., _, _] = $arr!(1, 2, 3, 4); x }, [$Ty; 0]);
+        compare_evaluation!(
+            { let [_, _, ref x @ .., _, _] = $arr!(1, 2, 3, 4); x },
+            &'static [$Ty; 0],
+        );
+        compare_evaluation!(
+            { let [_, _, x @ .., _, _] = &$arr!(1, 2, 3, 4); x },
+            &'static [$Ty; 0],
+        );
+
+        compare_evaluation!({ let [_, .., x] = $arr!(1, 2, 3, 4); x }, $Ty);
+        compare_evaluation!({ let [_, .., ref x] = $arr!(1, 2, 3, 4); x }, &'static $Ty);
+        compare_evaluation!({ let [_, _y @ .., x] = &$arr!(1, 2, 3, 4); x }, &'static $Ty);
+    }
+
+    compare_evaluation!({ let [_, .., N(x)] = n!(1, 2, 3, 4); x }, u8);
+    compare_evaluation!({ let [_, .., N(ref x)] = n!(1, 2, 3, 4); x }, &'static u8);
+    compare_evaluation!({ let [_, .., N(x)] = &n!(1, 2, 3, 4); x }, &'static u8);
+
+    compare_evaluation!({ let [N(x), .., _] = n!(1, 2, 3, 4); x }, u8);
+    compare_evaluation!({ let [N(ref x), .., _] = n!(1, 2, 3, 4); x }, &'static u8);
+    compare_evaluation!({ let [N(x), .., _] = &n!(1, 2, 3, 4); x }, &'static u8);
+}
diff --git a/src/base.rs b/src/base.rs
index 4d1d5df8a89..663e312a424 100644
--- a/src/base.rs
+++ b/src/base.rs
@@ -688,7 +688,7 @@ pub fn trans_place<'tcx>(
                             .eval_usize(fx.tcx, ParamEnv::reveal_all());
                         cplace = CPlace::for_ptr(
                             ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * from as i64),
-                            fx.layout_of(fx.tcx.mk_array(elem_ty, len - from as u64 - to as u64)),
+                            fx.layout_of(fx.tcx.mk_array(elem_ty, to as u64 - from as u64)),
                         );
                     }
                     ty::Slice(elem_ty) => {
diff --git a/test.sh b/test.sh
index 2990a9c03eb..d73badad957 100755
--- a/test.sh
+++ b/test.sh
@@ -60,6 +60,10 @@ echo "[AOT] std_example"
 $RUSTC example/std_example.rs --crate-type bin
 ./target/out/std_example
 
+echo "[AOT] subslice-patterns-const-eval"
+$RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort
+./target/out/subslice-patterns-const-eval
+
 echo "[BUILD] mod_bench"
 $RUSTC example/mod_bench.rs --crate-type bin