From 457741d6d2eb6c869fb95ba76dae55daa44b5a3f Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Fri, 8 Feb 2019 14:01:40 +0100
Subject: [PATCH 1/6] update for new bin_op APIs

---
 src/intrinsic.rs | 16 ++++++++--------
 src/lib.rs       |  8 +++-----
 src/operator.rs  | 21 +++++++++++----------
 3 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/src/intrinsic.rs b/src/intrinsic.rs
index 09df91b3ab..5a9939db2e 100644
--- a/src/intrinsic.rs
+++ b/src/intrinsic.rs
@@ -5,7 +5,7 @@ use rustc::ty;
 use rustc::mir::interpret::{EvalResult, PointerArithmetic};
 
 use crate::{
-    PlaceTy, OpTy, Immediate, Scalar, ScalarMaybeUndef, Borrow,
+    PlaceTy, OpTy, ImmTy, Immediate, Scalar, ScalarMaybeUndef, Borrow,
     OperatorEvalContextExt
 };
 
@@ -80,11 +80,11 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
 
             _ if intrinsic_name.starts_with("atomic_cxchg") => {
                 let ptr = this.deref_operand(args[0])?;
-                let expect_old = this.read_immediate(args[1])?; // read as immediate for the sake of `binary_op_imm()`
+                let expect_old = this.read_immediate(args[1])?; // read as immediate for the sake of `binary_op()`
                 let new = this.read_scalar(args[2])?;
-                let old = this.read_immediate(ptr.into())?; // read as immediate for the sake of `binary_op_imm()`
-                // binary_op_imm will bail if either of them is not a scalar
-                let (eq, _) = this.binary_op_imm(mir::BinOp::Eq, old, expect_old)?;
+                let old = this.read_immediate(ptr.into())?; // read as immediate for the sake of `binary_op()`
+                // binary_op will bail if either of them is not a scalar
+                let (eq, _) = this.binary_op(mir::BinOp::Eq, old, expect_old)?;
                 let res = Immediate::ScalarPair(old.to_scalar_or_undef(), eq.into());
                 this.write_immediate(res, dest)?; // old value is returned
                 // update ptr depending on comparison
@@ -140,9 +140,9 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
                     _ => bug!(),
                 };
                 // Atomics wrap around on overflow.
-                let (val, _overflowed) = this.binary_op_imm(op, old, rhs)?;
+                let (val, _overflowed) = this.binary_op(op, old, rhs)?;
                 let val = if neg {
-                    this.unary_op(mir::UnOp::Not, val, old.layout)?
+                    this.unary_op(mir::UnOp::Not, ImmTy::from_scalar(val, old.layout))?
                 } else {
                     val
                 };
@@ -239,7 +239,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
                 let a = this.read_immediate(args[0])?;
                 let b = this.read_immediate(args[1])?;
                 // check x % y != 0
-                if this.binary_op_imm(mir::BinOp::Rem, a, b)?.0.to_bits(dest.layout.size)? != 0 {
+                if this.binary_op(mir::BinOp::Rem, a, b)?.0.to_bits(dest.layout.size)? != 0 {
                     return err!(ValidationFailure(format!("exact_div: {:?} cannot be divided by {:?}", a, b)));
                 }
                 this.binop_ignore_overflow(mir::BinOp::Div, a, b, dest)?;
diff --git a/src/lib.rs b/src/lib.rs
index f59a476ed9..67bd54872f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -406,12 +406,10 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
     fn ptr_op(
         ecx: &rustc_mir::interpret::EvalContext<'a, 'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
-        left: Scalar<Borrow>,
-        left_layout: TyLayout<'tcx>,
-        right: Scalar<Borrow>,
-        right_layout: TyLayout<'tcx>,
+        left: ImmTy<'tcx, Borrow>,
+        right: ImmTy<'tcx, Borrow>,
     ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
-        ecx.ptr_op(bin_op, left, left_layout, right, right_layout)
+        ecx.ptr_op(bin_op, left, right)
     }
 
     fn box_alloc(
diff --git a/src/operator.rs b/src/operator.rs
index 4b110224a0..0bdec03497 100644
--- a/src/operator.rs
+++ b/src/operator.rs
@@ -7,10 +7,8 @@ pub trait EvalContextExt<'tcx> {
     fn ptr_op(
         &self,
         bin_op: mir::BinOp,
-        left: Scalar<Borrow>,
-        left_layout: TyLayout<'tcx>,
-        right: Scalar<Borrow>,
-        right_layout: TyLayout<'tcx>,
+        left: ImmTy<'tcx, Borrow>,
+        right: ImmTy<'tcx, Borrow>,
     ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)>;
 
     fn ptr_int_arithmetic(
@@ -40,13 +38,16 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
     fn ptr_op(
         &self,
         bin_op: mir::BinOp,
-        left: Scalar<Borrow>,
-        left_layout: TyLayout<'tcx>,
-        right: Scalar<Borrow>,
-        right_layout: TyLayout<'tcx>,
+        left: ImmTy<'tcx, Borrow>,
+        right: ImmTy<'tcx, Borrow>,
     ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
         use rustc::mir::BinOp::*;
 
+        let left_layout = left.layout;
+        let left = left.to_scalar()?;
+        let right_layout = right.layout;
+        let right = right.to_scalar()?;
+
         trace!("ptr_op: {:?} {:?} {:?}", left, bin_op, right);
         debug_assert!(left.is_ptr() || right.is_ptr() || bin_op == Offset);
 
@@ -85,8 +86,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
                             let layout = self.layout_of(self.tcx.types.usize)?;
                             return self.binary_op(
                                 Sub,
-                                left_offset, layout,
-                                right_offset, layout,
+                                ImmTy::from_scalar(left_offset, layout),
+                                ImmTy::from_scalar(right_offset, layout),
                             )
                         }
                         _ => bug!("We already established it has to be one of these operators."),

From 2c3ee678b127629396908199d298f66edb0b0b2d Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Fri, 8 Feb 2019 16:27:00 +0100
Subject: [PATCH 2/6] Fix comparing fat pointers

---
 src/lib.rs           |  2 +-
 src/operator.rs      | 31 +++++++++++++++++++++----------
 tests/run-pass/rc.rs | 10 ++++++++++
 3 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index 67bd54872f..1608bc1f30 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -17,7 +17,7 @@ use std::collections::HashMap;
 use std::borrow::Cow;
 
 use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
-use rustc::ty::layout::{TyLayout, LayoutOf, Size, Align};
+use rustc::ty::layout::{LayoutOf, Size, Align};
 use rustc::hir::{self, def_id::DefId};
 use rustc::mir;
 
diff --git a/src/operator.rs b/src/operator.rs
index 0bdec03497..b64ccf5462 100644
--- a/src/operator.rs
+++ b/src/operator.rs
@@ -1,4 +1,4 @@
-use rustc::ty::{Ty, layout::TyLayout};
+use rustc::ty::Ty;
 use rustc::mir;
 
 use crate::*;
@@ -23,7 +23,6 @@ pub trait EvalContextExt<'tcx> {
         &self,
         left: Scalar<Borrow>,
         right: Scalar<Borrow>,
-        size: Size,
     ) -> EvalResult<'tcx, bool>;
 
     fn pointer_offset_inbounds(
@@ -43,12 +42,29 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
     ) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
         use rustc::mir::BinOp::*;
 
+        trace!("ptr_op: {:?} {:?} {:?}", *left, bin_op, *right);
+
+        // Operations that support fat pointers
+        match bin_op {
+            Eq | Ne => {
+                let eq = match (*left, *right) {
+                    (Immediate::Scalar(left), Immediate::Scalar(right)) =>
+                        self.ptr_eq(left.not_undef()?, right.not_undef()?)?,
+                    (Immediate::ScalarPair(left1, left2), Immediate::ScalarPair(right1, right2)) =>
+                        self.ptr_eq(left1.not_undef()?, right1.not_undef()?)? &&
+                        self.ptr_eq(left2.not_undef()?, right2.not_undef()?)?,
+                    _ => bug!("Type system should not allow comparing Scalar with ScalarPair"),
+                };
+                return Ok((Scalar::from_bool(if bin_op == Eq { eq } else { !eq }), false));
+            }
+            _ => {},
+        }
+
+        // Now we expect no more fat pointers
         let left_layout = left.layout;
         let left = left.to_scalar()?;
         let right_layout = right.layout;
         let right = right.to_scalar()?;
-
-        trace!("ptr_op: {:?} {:?} {:?}", left, bin_op, right);
         debug_assert!(left.is_ptr() || right.is_ptr() || bin_op == Offset);
 
         match bin_op {
@@ -64,11 +80,6 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
                 )?;
                 Ok((ptr, false))
             }
-            // These work on anything
-            Eq =>
-                Ok((Scalar::from_bool(self.ptr_eq(left, right, left_layout.size)?), false)),
-            Ne =>
-                Ok((Scalar::from_bool(!self.ptr_eq(left, right, left_layout.size)?), false)),
             // These need both to be pointer, and fail if they are not in the same location
             Lt | Le | Gt | Ge | Sub if left.is_ptr() && right.is_ptr() => {
                 let left = left.to_ptr().expect("we checked is_ptr");
@@ -127,8 +138,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
         &self,
         left: Scalar<Borrow>,
         right: Scalar<Borrow>,
-        size: Size,
     ) -> EvalResult<'tcx, bool> {
+        let size = self.pointer_size();
         Ok(match (left, right) {
             (Scalar::Bits { .. }, Scalar::Bits { .. }) =>
                 left.to_bits(size)? == right.to_bits(size)?,
diff --git a/tests/run-pass/rc.rs b/tests/run-pass/rc.rs
index bc89d752e0..af68e5cfd1 100644
--- a/tests/run-pass/rc.rs
+++ b/tests/run-pass/rc.rs
@@ -1,6 +1,7 @@
 use std::cell::{Cell, RefCell};
 use std::rc::Rc;
 use std::sync::Arc;
+use std::fmt::Debug;
 
 fn rc_refcell() {
     let r = Rc::new(RefCell::new(42));
@@ -60,7 +61,16 @@ fn rc_from() {
     check_unique_rc::<str>(Rc::from("Hello, World!"));
 }
 
+fn rc_fat_ptr_eq() {
+    let p = Rc::new(1) as Rc<Debug>;
+    let a: *const Debug = &*p;
+    let r = Rc::into_raw(p);
+    let _b = a == r;
+    drop(unsafe { Rc::from_raw(r) });
+}
+
 fn main() {
+    rc_fat_ptr_eq();
     rc_refcell();
     rc_refcell2();
     rc_cell();

From 1921fa5766292a8b4ddd6c44deaedccfb2f85b7e Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Fri, 8 Feb 2019 23:48:37 +0100
Subject: [PATCH 3/6] actually they should be equal

---
 tests/run-pass/rc.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/run-pass/rc.rs b/tests/run-pass/rc.rs
index af68e5cfd1..164842ab4d 100644
--- a/tests/run-pass/rc.rs
+++ b/tests/run-pass/rc.rs
@@ -65,7 +65,7 @@ fn rc_fat_ptr_eq() {
     let p = Rc::new(1) as Rc<Debug>;
     let a: *const Debug = &*p;
     let r = Rc::into_raw(p);
-    let _b = a == r;
+    assert!(a == r);
     drop(unsafe { Rc::from_raw(r) });
 }
 

From 9397b36ab813376d5af354c25f8d875b281802c9 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Wed, 13 Feb 2019 17:21:46 +0100
Subject: [PATCH 4/6] typo and comments

---
 src/bin/cargo-miri.rs     | 2 +-
 tests/run-pass/hashmap.rs | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs
index bca2b6df1b..0de835f45d 100644
--- a/src/bin/cargo-miri.rs
+++ b/src/bin/cargo-miri.rs
@@ -266,7 +266,7 @@ path = "lib.rs"
     let sysroot = if is_host { dir.join("HOST") } else { PathBuf::from(dir) };
     std::env::set_var("MIRI_SYSROOT", &sysroot);
     if !ask_user {
-        println!("A libstd for miri is now available in `{}`", sysroot.display());
+        println!("A libstd for Miri is now available in `{}`", sysroot.display());
     }
 }
 
diff --git a/tests/run-pass/hashmap.rs b/tests/run-pass/hashmap.rs
index f4a358174f..d89a5ab535 100644
--- a/tests/run-pass/hashmap.rs
+++ b/tests/run-pass/hashmap.rs
@@ -21,5 +21,5 @@ fn main() {
     }
     assert_eq!(map.values().fold(0, |x, y| x+y), num*(num-1)/2);
 
-    // TODO: Test Entry API
+    // TODO: Test Entry API, Iterators, ...
 }

From 15722fab51fadd484694dd01498f35ebba2b1999 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Fri, 15 Feb 2019 08:28:02 +0100
Subject: [PATCH 5/6] update Rust

---
 rust-version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rust-version b/rust-version
index edd1c533d9..cb6d9f177d 100644
--- a/rust-version
+++ b/rust-version
@@ -1 +1 @@
-nightly-2019-02-14
+nightly-2019-02-15

From e630175867b00a81e4125ece04e5f14cc88d9970 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Fri, 15 Feb 2019 09:32:54 +0100
Subject: [PATCH 6/6] fix async-fn test

---
 tests/run-pass/async-fn.rs | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/tests/run-pass/async-fn.rs b/tests/run-pass/async-fn.rs
index 9094a9fd3a..48f8fc1223 100644
--- a/tests/run-pass/async-fn.rs
+++ b/tests/run-pass/async-fn.rs
@@ -4,7 +4,8 @@
     futures_api,
 )]
 
-use std::{future::Future, pin::Pin, task::Poll};
+use std::{future::Future, pin::Pin, task::Poll, ptr};
+use std::task::{Waker, RawWaker, RawWakerVTable};
 
 // See if we can run a basic `async fn`
 pub async fn foo(x: &u32, y: u32) -> u32 {
@@ -17,18 +18,23 @@ pub async fn foo(x: &u32, y: u32) -> u32 {
     *x + y + *a
 }
 
-fn main() {
-    use std::{sync::Arc, task::{Wake, local_waker}};
+fn raw_waker_clone(_this: *const ()) -> RawWaker {
+    panic!("unimplemented");
+}
+fn raw_waker_wake(_this: *const ()) {
+    panic!("unimplemented");
+}
+fn raw_waker_drop(_this: *const ()) {}
 
-    struct NoWake;
-    impl Wake for NoWake {
-        fn wake(_arc_self: &Arc<Self>) {
-            panic!();
-        }
-    }
+static RAW_WAKER: RawWakerVTable = RawWakerVTable {
+    clone: raw_waker_clone,
+    wake: raw_waker_wake,
+    drop: raw_waker_drop,
+};
 
-    let lw = unsafe { local_waker(Arc::new(NoWake)) };
+fn main() {
     let x = 5;
     let mut fut = foo(&x, 7);
-    assert_eq!(unsafe { Pin::new_unchecked(&mut fut) }.poll(&lw), Poll::Ready(31));
+    let waker = unsafe { Waker::new_unchecked(RawWaker::new(ptr::null(), &RAW_WAKER)) };
+    assert_eq!(unsafe { Pin::new_unchecked(&mut fut) }.poll(&waker), Poll::Ready(31));
 }