From e1e95a83861271e144f65903c652ab9fa9bd64b8 Mon Sep 17 00:00:00 2001
From: Christian Poveda <christianpoveda@protonmail.com>
Date: Wed, 26 Jun 2019 18:50:20 -0500
Subject: [PATCH 1/5] Use force_bits when casting from a pointer

---
 src/librustc_mir/interpret/cast.rs | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index fbacdf6cd93bb..bd012d4c2bf57 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -242,14 +242,31 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
         ty: Ty<'tcx>
     ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
-        match ty.sty {
+
+        let size = match ty.sty {
             // Casting to a reference or fn pointer is not permitted by rustc,
             // no need to support it here.
-            RawPtr(_) |
-            Int(IntTy::Isize) |
-            Uint(UintTy::Usize) => Ok(ptr.into()),
-            Int(_) | Uint(_) => err!(ReadPointerAsBytes),
-            _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
+            RawPtr(_) => return Ok(ptr.into()),
+            Int(IntTy::Isize) | Uint(UintTy::Usize) => {
+                let size = self.memory.pointer_size();
+                if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) {
+                    return Ok(Scalar::from_uint(bits, size));
+                } 
+                return Ok(ptr.into());
+            }
+            // If the target type is a sized integer, we need the its size to perform the pointer cast
+            Int(i) => i.bit_width().unwrap(),
+            Uint(i) => i.bit_width().unwrap(),
+            // Casting to any other type is not implemented
+            _ => return err!(Unimplemented(format!("ptr to {:?} cast", ty))),
+        };
+
+        let size = Size::from_bits(size as u64);
+
+        if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) {
+            Ok(Scalar::from_uint(bits, size))
+        } else {
+            err!(ReadPointerAsBytes)
         }
     }
 

From 7f1e160e02112d4d23a72e52b2ab23860e6a956f Mon Sep 17 00:00:00 2001
From: Christian Poveda <cpovedar@fnal.gov>
Date: Fri, 28 Jun 2019 14:25:33 -0500
Subject: [PATCH 2/5] Reorganize code for readabilty and fixed problem with
 type sizes

---
 src/librustc_mir/interpret/cast.rs | 47 ++++++++++++++++++------------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index bd012d4c2bf57..e8bca0c712399 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -151,7 +151,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
                     "Unexpected cast from type {:?}", src_layout.ty
                 );
                 match val.to_bits_or_ptr(src_layout.size, self) {
-                    Err(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
+                    Err(ptr) => self.cast_from_ptr(ptr, src_layout, dest_layout),
                     Ok(data) => self.cast_from_int(data, src_layout, dest_layout),
                 }
             }
@@ -239,34 +239,43 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
     fn cast_from_ptr(
         &self,
         ptr: Pointer<M::PointerTag>,
-        ty: Ty<'tcx>
+        src_layout: TyLayout<'tcx>,
+        dest_layout: TyLayout<'tcx>,
     ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
 
-        let size = match ty.sty {
+        fn int_size<'tcx>(layout: TyLayout<'tcx>) -> Option<usize> {
+            match layout.ty.sty {
+                Int(i) => i.bit_width(),
+                Uint(i) => i.bit_width(),
+                _ => bug!("Not an integer"),
+            }
+        }
+
+        match dest_layout.ty.sty {
             // Casting to a reference or fn pointer is not permitted by rustc,
             // no need to support it here.
-            RawPtr(_) => return Ok(ptr.into()),
+            RawPtr(_) => Ok(ptr.into()),
             Int(IntTy::Isize) | Uint(UintTy::Usize) => {
                 let size = self.memory.pointer_size();
+                
                 if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) {
-                    return Ok(Scalar::from_uint(bits, size));
-                } 
-                return Ok(ptr.into());
+                    self.cast_from_int(bits, src_layout, dest_layout)
+                } else {
+                    Ok(ptr.into())
+                }
             }
-            // If the target type is a sized integer, we need the its size to perform the pointer cast
-            Int(i) => i.bit_width().unwrap(),
-            Uint(i) => i.bit_width().unwrap(),
+            Int(_) | Uint(_) => {
+                let size = Size::from_bits(int_size(dest_layout).unwrap() as u64);
+                
+                if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) {
+                    self.cast_from_int(bits, src_layout, dest_layout)
+                } else {
+                    err!(ReadPointerAsBytes)
+                }
+            },
             // Casting to any other type is not implemented
-            _ => return err!(Unimplemented(format!("ptr to {:?} cast", ty))),
-        };
-
-        let size = Size::from_bits(size as u64);
-
-        if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) {
-            Ok(Scalar::from_uint(bits, size))
-        } else {
-            err!(ReadPointerAsBytes)
+            _ => return err!(Unimplemented(format!("ptr to {:?} cast", dest_layout.ty))),
         }
     }
 

From 95bc72052c65e22cbf23f80bfa314528abcb981b Mon Sep 17 00:00:00 2001
From: Christian Poveda <cpovedar@fnal.gov>
Date: Sat, 29 Jun 2019 07:59:45 -0500
Subject: [PATCH 3/5] Use pointer size as the source size

---
 src/librustc_mir/interpret/cast.rs | 19 +++----------------
 1 file changed, 3 insertions(+), 16 deletions(-)

diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index e8bca0c712399..73ef0bd6dacb6 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -244,37 +244,24 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
         use rustc::ty::TyKind::*;
 
-        fn int_size<'tcx>(layout: TyLayout<'tcx>) -> Option<usize> {
-            match layout.ty.sty {
-                Int(i) => i.bit_width(),
-                Uint(i) => i.bit_width(),
-                _ => bug!("Not an integer"),
-            }
-        }
-
         match dest_layout.ty.sty {
             // Casting to a reference or fn pointer is not permitted by rustc,
             // no need to support it here.
             RawPtr(_) => Ok(ptr.into()),
             Int(IntTy::Isize) | Uint(UintTy::Usize) => {
-                let size = self.memory.pointer_size();
-                
-                if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) {
+                if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), self.memory.pointer_size()) {
                     self.cast_from_int(bits, src_layout, dest_layout)
                 } else {
                     Ok(ptr.into())
                 }
             }
             Int(_) | Uint(_) => {
-                let size = Size::from_bits(int_size(dest_layout).unwrap() as u64);
-                
-                if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) {
+                if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), self.memory.pointer_size()) {
                     self.cast_from_int(bits, src_layout, dest_layout)
                 } else {
                     err!(ReadPointerAsBytes)
                 }
-            },
-            // Casting to any other type is not implemented
+            }
             _ => return err!(Unimplemented(format!("ptr to {:?} cast", dest_layout.ty))),
         }
     }

From 51793bd318a162752def38a6ae1ec9292861d0cc Mon Sep 17 00:00:00 2001
From: Christian Poveda <christianpoveda@protonmail.com>
Date: Sat, 29 Jun 2019 13:19:37 -0500
Subject: [PATCH 4/5] Simplify control flow

---
 src/librustc_mir/interpret/cast.rs | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 73ef0bd6dacb6..2777ada14f9ad 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -1,7 +1,7 @@
 use rustc::ty::{self, Ty, TypeAndMut};
 use rustc::ty::layout::{self, TyLayout, Size};
 use rustc::ty::adjustment::{PointerCast};
-use syntax::ast::{FloatTy, IntTy, UintTy};
+use syntax::ast::FloatTy;
 use syntax::symbol::sym;
 
 use rustc_apfloat::ieee::{Single, Double};
@@ -248,18 +248,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
             // Casting to a reference or fn pointer is not permitted by rustc,
             // no need to support it here.
             RawPtr(_) => Ok(ptr.into()),
-            Int(IntTy::Isize) | Uint(UintTy::Usize) => {
-                if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), self.memory.pointer_size()) {
-                    self.cast_from_int(bits, src_layout, dest_layout)
-                } else {
-                    Ok(ptr.into())
-                }
-            }
             Int(_) | Uint(_) => {
-                if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), self.memory.pointer_size()) {
-                    self.cast_from_int(bits, src_layout, dest_layout)
-                } else {
-                    err!(ReadPointerAsBytes)
+                let size = self.memory.pointer_size();
+
+                match self.force_bits(Scalar::Ptr(ptr), size) {
+                    Ok(bits) => self.cast_from_int(bits, src_layout, dest_layout),
+                    Err(_) if dest_layout.size == size => Ok(ptr.into()),
+                    Err(e) => Err(e),
                 }
             }
             _ => return err!(Unimplemented(format!("ptr to {:?} cast", dest_layout.ty))),

From 92c28bfabcbbbbf864308cd71750d4b20f306b37 Mon Sep 17 00:00:00 2001
From: Christian Poveda <christianpoveda@protonmail.com>
Date: Sat, 29 Jun 2019 22:50:37 -0500
Subject: [PATCH 5/5] Replace error by bug macro

---
 src/librustc_mir/interpret/cast.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 2777ada14f9ad..e6c9d9f5c79d8 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -257,7 +257,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
                     Err(e) => Err(e),
                 }
             }
-            _ => return err!(Unimplemented(format!("ptr to {:?} cast", dest_layout.ty))),
+            _ => bug!("invalid MIR: ptr to {:?} cast", dest_layout.ty)
         }
     }