Skip to content

Commit 31f1bc7

Browse files
committed
Auto merge of #52400 - RalfJung:match, r=oli-obk
CTFE: use binary_op to compare integer with match disriminant This is needed to unblock rust-lang/miri#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
2 parents 82e5c9c + f9825c2 commit 31f1bc7

File tree

3 files changed

+61
-4
lines changed

3 files changed

+61
-4
lines changed

src/librustc_mir/interpret/terminator/mod.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use rustc::mir;
22
use rustc::ty::{self, Ty};
3-
use rustc::ty::layout::LayoutOf;
3+
use rustc::ty::layout::{LayoutOf, Size};
44
use syntax::codemap::Span;
55
use rustc_target::spec::abi::Abi;
66

7-
use rustc::mir::interpret::EvalResult;
7+
use rustc::mir::interpret::{EvalResult, Scalar};
88
use super::{EvalContext, Place, Machine, ValTy};
99

1010
use rustc_data_structures::indexed_vec::Idx;
@@ -41,13 +41,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
4141
let discr_prim = self.value_to_scalar(discr_val)?;
4242
let discr_layout = self.layout_of(discr_val.ty).unwrap();
4343
trace!("SwitchInt({:?}, {:#?})", discr_prim, discr_layout);
44-
let discr_prim = discr_prim.to_bits(discr_layout.size)?;
4544

4645
// Branch to the `otherwise` case by default, if no match is found.
4746
let mut target_block = targets[targets.len() - 1];
4847

4948
for (index, &const_int) in values.iter().enumerate() {
50-
if discr_prim == const_int {
49+
// Compare using binary_op
50+
let const_int = Scalar::Bits { bits: const_int, defined: 128 };
51+
let res = self.binary_op(mir::BinOp::Eq,
52+
discr_prim, discr_val.ty,
53+
const_int, discr_val.ty
54+
)?;
55+
if res.0.to_bits(Size::from_bytes(1))? != 0 {
5156
target_block = targets[index];
5257
break;
5358
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
// Make sure match uses the usual pointer comparison code path -- i.e., it should complain
13+
// that pointer comparison is disallowed, not that parts of a pointer are accessed as raw
14+
// bytes.
15+
let _: [u8; 0] = [4; { //~ ERROR could not evaluate repeat length
16+
match &1 as *const i32 as usize { //~ ERROR raw pointers cannot be cast to integers
17+
0 => 42, //~ ERROR constant contains unimplemented expression type
18+
//~^ NOTE "pointer arithmetic or comparison" needs an rfc before being allowed
19+
n => n,
20+
}
21+
}];
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
error[E0018]: raw pointers cannot be cast to integers in constants
2+
--> $DIR/match-test-ptr-null.rs:16:15
3+
|
4+
LL | match &1 as *const i32 as usize { //~ ERROR raw pointers cannot be cast to integers
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error[E0019]: constant contains unimplemented expression type
8+
--> $DIR/match-test-ptr-null.rs:17:13
9+
|
10+
LL | 0 => 42, //~ ERROR constant contains unimplemented expression type
11+
| ^
12+
13+
error[E0080]: could not evaluate repeat length
14+
--> $DIR/match-test-ptr-null.rs:15:26
15+
|
16+
LL | let _: [u8; 0] = [4; { //~ ERROR could not evaluate repeat length
17+
| __________________________^
18+
LL | | match &1 as *const i32 as usize { //~ ERROR raw pointers cannot be cast to integers
19+
LL | | 0 => 42, //~ ERROR constant contains unimplemented expression type
20+
| | - "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
21+
LL | | //~^ NOTE "pointer arithmetic or comparison" needs an rfc before being allowed
22+
LL | | n => n,
23+
LL | | }
24+
LL | | }];
25+
| |_____^
26+
27+
error: aborting due to 3 previous errors
28+
29+
Some errors occurred: E0018, E0019, E0080.
30+
For more information about an error, try `rustc --explain E0018`.

0 commit comments

Comments
 (0)