Auto merge of #68170 - wesleywiser:stop_const_prop_ref_taking, r=oli-obk

Turn off const propagation of ref taking

Fixes #67529
Fixes #67640
Fixes #67641
Fixes #67862

r? @oli-obk
This commit is contained in:
bors 2020-01-18 11:36:47 +00:00
commit 35b5157db5
6 changed files with 82 additions and 22 deletions

View File

@ -636,29 +636,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
self.check_binary_op(*op, left, right, source_info, place_layout, overflow_check)?;
}
// Work around: avoid ICE in miri. FIXME(wesleywiser)
// The Miri engine ICEs when taking a reference to an uninitialized unsized
// local. There's nothing it can do here: taking a reference needs an allocation
// which needs to know the size. Normally that's okay as during execution
// (e.g. for CTFE) it can never happen. But here in const_prop
// unknown data is uninitialized, so if e.g. a function argument is unsized
// and has a reference taken, we get an ICE.
// Do not try creating references (#67862)
Rvalue::Ref(_, _, place_ref) => {
trace!("checking Ref({:?})", place_ref);
trace!("skipping Ref({:?})", place_ref);
if let Some(local) = place_ref.as_local() {
let alive = if let LocalValue::Live(_) = self.ecx.frame().locals[local].value {
true
} else {
false
};
if !alive {
trace!("skipping Ref({:?}) to uninitialized local", place);
return None;
}
}
}
_ => {}
}

View File

@ -1,5 +1,5 @@
fn main() {
*(&(4, 5).1);
*(&(4, 5).1); // This does not currently propagate (#67862)
}
// END RUST SOURCE
@ -35,7 +35,7 @@ fn main() {
// ...
// _4 = const main::promoted[0];
// _2 = &((*_4).1: i32);
// _1 = const 5i32;
// _1 = (*_2);
// ...
// }
// END rustc.main.ConstProp.after.mir

View File

@ -0,0 +1,11 @@
// compile-flags: -Z mir-opt-level=2
// run-pass
struct Baz<T: ?Sized> {
a: T
}
fn main() {
let d : Baz<[i32; 4]> = Baz { a: [1,2,3,4] };
assert_eq!([1, 2, 3, 4], d.a);
}

View File

@ -0,0 +1,24 @@
// compile-flags: -Z mir-opt-level=3
// run-pass
struct X {
x: isize
}
fn f1(a: &mut X, b: &mut isize, c: isize) -> isize {
let r = a.x + *b + c;
a.x = 0;
*b = 10;
return r;
}
fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; }
pub fn main() {
let mut a = X {x: 1};
let mut b = 2;
let c = 3;
assert_eq!(f1(&mut a, &mut b, c), 6);
assert_eq!(a.x, 0);
assert_eq!(f2(a.x, |_| a.x = 50), 0);
}

View File

@ -0,0 +1,24 @@
// compile-flags: -Z mir-opt-level=2
// run-pass
use std::cell::Cell;
#[derive(Debug)]
struct B<'a> {
a: [Cell<Option<&'a B<'a>>>; 2]
}
impl<'a> B<'a> {
fn new() -> B<'a> {
B { a: [Cell::new(None), Cell::new(None)] }
}
}
fn f() {
let b2 = B::new();
b2.a[0].set(Some(&b2));
}
fn main() {
f();
}

View File

@ -0,0 +1,18 @@
// compile-flags: -Z mir-opt-level=2
// run-pass
fn e220() -> (i64, i64) {
#[inline(never)]
fn get_displacement() -> [i64; 2] {
[139776, 963904]
}
let res = get_displacement();
match (&res[0], &res[1]) {
(arg0, arg1) => (*arg0, *arg1),
}
}
fn main() {
assert_eq!(e220(), (139776, 963904));
}