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; } 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..19b3dcc318154 --- /dev/null +++ b/src/test/ui/const-eval/match-test-ptr-null.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , 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 + // 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..726ada9b428aa --- /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: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:17:13 + | +LL | 0 => 42, //~ ERROR constant contains unimplemented expression type + | ^ + +error[E0080]: could not evaluate repeat length + --> $DIR/match-test-ptr-null.rs:15: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`.