From 8a17b36fc5cdd33fdd8a705b82118980b48681f7 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 15 Jul 2018 11:35:18 +0200
Subject: [PATCH 1/4] CTFE: use binary_op to compare integer with match
 disriminant

---
 src/librustc_mir/interpret/terminator/mod.rs | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index 2994b1b387f3f..e281ba7963979 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -1,10 +1,10 @@
 use rustc::mir;
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::LayoutOf;
+use rustc::ty::layout::{LayoutOf, Size};
 use syntax::codemap::Span;
 use rustc_target::spec::abi::Abi;
 
-use rustc::mir::interpret::EvalResult;
+use rustc::mir::interpret::{EvalResult, Scalar};
 use super::{EvalContext, Place, Machine, ValTy};
 
 use rustc_data_structures::indexed_vec::Idx;
@@ -41,13 +41,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                 let discr_prim = self.value_to_scalar(discr_val)?;
                 let discr_layout = self.layout_of(discr_val.ty).unwrap();
                 trace!("SwitchInt({:?}, {:#?})", discr_prim, discr_layout);
-                let discr_prim = discr_prim.to_bits(discr_layout.size)?;
 
                 // Branch to the `otherwise` case by default, if no match is found.
                 let mut target_block = targets[targets.len() - 1];
 
                 for (index, &const_int) in values.iter().enumerate() {
-                    if discr_prim == const_int {
+                    // Compare using binary_op
+                    let const_int = Scalar::Bits { bits: const_int, defined: 128 };
+                    let res = self.binary_op(mir::BinOp::Eq,
+                        discr_prim, discr_val.ty,
+                        const_int, discr_val.ty
+                    )?;
+                    if res.0.to_bits(Size::from_bytes(1))? != 0 {
                         target_block = targets[index];
                         break;
                     }

From 5be74148c23d41e306446d23acb93ed93e095252 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 15 Jul 2018 13:55:17 +0200
Subject: [PATCH 2/4] add test case

---
 src/test/ui/const-eval/match-test-ptr-null.rs | 12 ++++++++
 .../ui/const-eval/match-test-ptr-null.stderr  | 30 +++++++++++++++++++
 2 files changed, 42 insertions(+)
 create mode 100644 src/test/ui/const-eval/match-test-ptr-null.rs
 create mode 100644 src/test/ui/const-eval/match-test-ptr-null.stderr

diff --git a/src/test/ui/const-eval/match-test-ptr-null.rs b/src/test/ui/const-eval/match-test-ptr-null.rs
new file mode 100644
index 0000000000000..3e8a5930a1d20
--- /dev/null
+++ b/src/test/ui/const-eval/match-test-ptr-null.rs
@@ -0,0 +1,12 @@
+fn main() {
+    // Make sure match uses the usual pointer comparison code path -- i.e., it should complain
+    // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw
+    // bytes.
+    let _: [u8; 0] = [4; { //~ ERROR could not evaluate repeat length
+        match &1 as *const i32 as usize { //~ ERROR raw pointers cannot be cast to integers
+            0 => 42, //~ ERROR constant contains unimplemented expression type
+            //~^ NOTE "pointer arithmetic or comparison" needs an rfc before being allowed
+            n => n,
+        }
+    }];
+}
diff --git a/src/test/ui/const-eval/match-test-ptr-null.stderr b/src/test/ui/const-eval/match-test-ptr-null.stderr
new file mode 100644
index 0000000000000..ffc911a2ae2e6
--- /dev/null
+++ b/src/test/ui/const-eval/match-test-ptr-null.stderr
@@ -0,0 +1,30 @@
+error[E0018]: raw pointers cannot be cast to integers in constants
+  --> $DIR/match-test-ptr-null.rs:6:15
+   |
+LL |         match &1 as *const i32 as usize { //~ ERROR raw pointers cannot be cast to integers
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0019]: constant contains unimplemented expression type
+  --> $DIR/match-test-ptr-null.rs:7:13
+   |
+LL |             0 => 42, //~ ERROR constant contains unimplemented expression type
+   |             ^
+
+error[E0080]: could not evaluate repeat length
+  --> $DIR/match-test-ptr-null.rs:5:26
+   |
+LL |       let _: [u8; 0] = [4; { //~ ERROR could not evaluate repeat length
+   |  __________________________^
+LL | |         match &1 as *const i32 as usize { //~ ERROR raw pointers cannot be cast to integers
+LL | |             0 => 42, //~ ERROR constant contains unimplemented expression type
+   | |             - "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+LL | |             //~^ NOTE "pointer arithmetic or comparison" needs an rfc before being allowed
+LL | |             n => n,
+LL | |         }
+LL | |     }];
+   | |_____^
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0018, E0019, E0080.
+For more information about an error, try `rustc --explain E0018`.

From 03b9020155033c2721206c4b4446b888fb5617c9 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 15 Jul 2018 14:26:31 +0200
Subject: [PATCH 3/4] add license text

---
 src/test/ui/const-eval/match-test-ptr-null.rs | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/test/ui/const-eval/match-test-ptr-null.rs b/src/test/ui/const-eval/match-test-ptr-null.rs
index 3e8a5930a1d20..19b3dcc318154 100644
--- a/src/test/ui/const-eval/match-test-ptr-null.rs
+++ b/src/test/ui/const-eval/match-test-ptr-null.rs
@@ -1,3 +1,13 @@
+// Copyright 2018 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.
+
 fn main() {
     // Make sure match uses the usual pointer comparison code path -- i.e., it should complain
     // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw

From f9825c215b9b76dd42504e72887f82eca0469c96 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 15 Jul 2018 20:42:18 +0200
Subject: [PATCH 4/4] fix line numbers

---
 src/test/ui/const-eval/match-test-ptr-null.stderr | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/test/ui/const-eval/match-test-ptr-null.stderr b/src/test/ui/const-eval/match-test-ptr-null.stderr
index ffc911a2ae2e6..726ada9b428aa 100644
--- a/src/test/ui/const-eval/match-test-ptr-null.stderr
+++ b/src/test/ui/const-eval/match-test-ptr-null.stderr
@@ -1,17 +1,17 @@
 error[E0018]: raw pointers cannot be cast to integers in constants
-  --> $DIR/match-test-ptr-null.rs:6:15
+  --> $DIR/match-test-ptr-null.rs:16:15
    |
 LL |         match &1 as *const i32 as usize { //~ ERROR raw pointers cannot be cast to integers
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/match-test-ptr-null.rs:7:13
+  --> $DIR/match-test-ptr-null.rs:17:13
    |
 LL |             0 => 42, //~ ERROR constant contains unimplemented expression type
    |             ^
 
 error[E0080]: could not evaluate repeat length
-  --> $DIR/match-test-ptr-null.rs:5:26
+  --> $DIR/match-test-ptr-null.rs:15:26
    |
 LL |       let _: [u8; 0] = [4; { //~ ERROR could not evaluate repeat length
    |  __________________________^