From 8a17b36fc5cdd33fdd8a705b82118980b48681f7 Mon Sep 17 00:00:00 2001 From: Ralf Jung 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 2994b1b387f..e281ba79639 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 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 00000000000..3e8a5930a1d --- /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 00000000000..ffc911a2ae2 --- /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 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 3e8a5930a1d..19b3dcc3181 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 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 From f9825c215b9b76dd42504e72887f82eca0469c96 Mon Sep 17 00:00:00 2001 From: Ralf Jung 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 ffc911a2ae2..726ada9b428 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 | __________________________^