mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-23 04:14:28 +00:00
Auto merge of #52400 - RalfJung:match, r=oli-obk
CTFE: use binary_op to compare integer with match disriminant This is needed to unblock https://github.com/solson/miri/pull/401: There is code in the Windows initialization functions that uses `match` to test whether a pointer is NULL. I will add a testcase in miri; I was not sure where to add a testcase in Rust itself. r? @oli-obk
This commit is contained in:
commit
31f1bc7b40
@ -1,10 +1,10 @@
|
|||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::layout::LayoutOf;
|
use rustc::ty::layout::{LayoutOf, Size};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use rustc::mir::interpret::EvalResult;
|
use rustc::mir::interpret::{EvalResult, Scalar};
|
||||||
use super::{EvalContext, Place, Machine, ValTy};
|
use super::{EvalContext, Place, Machine, ValTy};
|
||||||
|
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
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_prim = self.value_to_scalar(discr_val)?;
|
||||||
let discr_layout = self.layout_of(discr_val.ty).unwrap();
|
let discr_layout = self.layout_of(discr_val.ty).unwrap();
|
||||||
trace!("SwitchInt({:?}, {:#?})", discr_prim, discr_layout);
|
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.
|
// Branch to the `otherwise` case by default, if no match is found.
|
||||||
let mut target_block = targets[targets.len() - 1];
|
let mut target_block = targets[targets.len() - 1];
|
||||||
|
|
||||||
for (index, &const_int) in values.iter().enumerate() {
|
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];
|
target_block = targets[index];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
22
src/test/ui/const-eval/match-test-ptr-null.rs
Normal file
22
src/test/ui/const-eval/match-test-ptr-null.rs
Normal file
@ -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 <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
|
||||||
|
// 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,
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
30
src/test/ui/const-eval/match-test-ptr-null.stderr
Normal file
30
src/test/ui/const-eval/match-test-ptr-null.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user