]> git.lizzy.rs Git - rust.git/commitdiff
Fix comparing fat pointers
authorRalf Jung <post@ralfj.de>
Fri, 8 Feb 2019 15:27:00 +0000 (16:27 +0100)
committerRalf Jung <post@ralfj.de>
Fri, 15 Feb 2019 08:35:55 +0000 (09:35 +0100)
src/lib.rs
src/operator.rs
tests/run-pass/rc.rs

index 67bd54872f82aaa7d9371117d239726d224666e1..1608bc1f3028b9280970896a78005673d35e82f7 100644 (file)
@@ -17,7 +17,7 @@
 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;
 
index 0bdec0349778d926d6ba9a7f3d0e8616185396f5..b64ccf5462d6a017c09a7547eac8010b3aef50df 100644 (file)
@@ -1,4 +1,4 @@
-use rustc::ty::{Ty, layout::TyLayout};
+use rustc::ty::Ty;
 use rustc::mir;
 
 use crate::*;
@@ -23,7 +23,6 @@ fn ptr_eq(
         &self,
         left: Scalar<Borrow>,
         right: Scalar<Borrow>,
-        size: Size,
     ) -> EvalResult<'tcx, bool>;
 
     fn pointer_offset_inbounds(
@@ -43,12 +42,29 @@ fn ptr_op(
     ) -> 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 @@ fn ptr_op(
                 )?;
                 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 @@ fn ptr_eq(
         &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)?,
index bc89d752e0b62122642a3647d4874bd4ba38ea1e..af68e5cfd1faa76c6ae049eeceae739ebbe847cd 100644 (file)
@@ -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();