Skip to content

Commit

Permalink
Turn off const propagation of ref taking
Browse files Browse the repository at this point in the history
Fixes #67529
Fixes #67640
Fixes #67641
Fixes #67862
  • Loading branch information
wesleywiser committed Jan 13, 2020
1 parent f363745 commit 7f65475
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 22 deletions.
23 changes: 3 additions & 20 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,28 +595,11 @@ 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;
}
}
return None;
}

_ => {}
Expand Down
4 changes: 2 additions & 2 deletions src/test/mir-opt/const_prop/ref_deref_project.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
fn main() {
*(&(4, 5).1);
*(&(4, 5).1); // This does not currently propagate (#67862)
}

// END RUST SOURCE
Expand Down Expand Up @@ -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
11 changes: 11 additions & 0 deletions src/test/ui/consts/issue-67529.rs
Original file line number Diff line number Diff line change
@@ -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);
}
24 changes: 24 additions & 0 deletions src/test/ui/consts/issue-67640.rs
Original file line number Diff line number Diff line change
@@ -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);
}
24 changes: 24 additions & 0 deletions src/test/ui/consts/issue-67641.rs
Original file line number Diff line number Diff line change
@@ -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();
}
18 changes: 18 additions & 0 deletions src/test/ui/consts/issue-67862.rs
Original file line number Diff line number Diff line change
@@ -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));
}

0 comments on commit 7f65475

Please sign in to comment.