Skip to content

Commit b71aa4e

Browse files
committed
Fix comparing fat pointers
1 parent 1d8ccd4 commit b71aa4e

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::collections::HashMap;
1717
use std::borrow::Cow;
1818

1919
use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
20-
use rustc::ty::layout::{TyLayout, LayoutOf, Size, Align};
20+
use rustc::ty::layout::{LayoutOf, Size, Align};
2121
use rustc::hir::{self, def_id::DefId};
2222
use rustc::mir;
2323

src/operator.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc::ty::{Ty, layout::TyLayout};
1+
use rustc::ty::Ty;
22
use rustc::mir;
33

44
use crate::*;
@@ -23,7 +23,6 @@ pub trait EvalContextExt<'tcx> {
2323
&self,
2424
left: Scalar<Borrow>,
2525
right: Scalar<Borrow>,
26-
size: Size,
2726
) -> EvalResult<'tcx, bool>;
2827

2928
fn pointer_offset_inbounds(
@@ -43,12 +42,29 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
4342
) -> EvalResult<'tcx, (Scalar<Borrow>, bool)> {
4443
use rustc::mir::BinOp::*;
4544

45+
trace!("ptr_op: {:?} {:?} {:?}", *left, bin_op, *right);
46+
47+
// Operations that support fat pointers
48+
match bin_op {
49+
Eq | Ne => {
50+
let eq = match (*left, *right) {
51+
(Immediate::Scalar(left), Immediate::Scalar(right)) =>
52+
self.ptr_eq(left.not_undef()?, right.not_undef()?)?,
53+
(Immediate::ScalarPair(left1, left2), Immediate::ScalarPair(right1, right2)) =>
54+
self.ptr_eq(left1.not_undef()?, right1.not_undef()?)? &&
55+
self.ptr_eq(left2.not_undef()?, right2.not_undef()?)?,
56+
_ => bug!("Type system should not allow comparing Scalar with ScalarPair"),
57+
};
58+
return Ok((Scalar::from_bool(if bin_op == Eq { eq } else { !eq }), false));
59+
}
60+
_ => {},
61+
}
62+
63+
// Now we expect no more fat pointers
4664
let left_layout = left.layout;
4765
let left = left.to_scalar()?;
4866
let right_layout = right.layout;
4967
let right = right.to_scalar()?;
50-
51-
trace!("ptr_op: {:?} {:?} {:?}", left, bin_op, right);
5268
debug_assert!(left.is_ptr() || right.is_ptr() || bin_op == Offset);
5369

5470
match bin_op {
@@ -64,11 +80,6 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
6480
)?;
6581
Ok((ptr, false))
6682
}
67-
// These work on anything
68-
Eq =>
69-
Ok((Scalar::from_bool(self.ptr_eq(left, right, left_layout.size)?), false)),
70-
Ne =>
71-
Ok((Scalar::from_bool(!self.ptr_eq(left, right, left_layout.size)?), false)),
7283
// These need both to be pointer, and fail if they are not in the same location
7384
Lt | Le | Gt | Ge | Sub if left.is_ptr() && right.is_ptr() => {
7485
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, '
127138
&self,
128139
left: Scalar<Borrow>,
129140
right: Scalar<Borrow>,
130-
size: Size,
131141
) -> EvalResult<'tcx, bool> {
142+
let size = self.pointer_size();
132143
Ok(match (left, right) {
133144
(Scalar::Bits { .. }, Scalar::Bits { .. }) =>
134145
left.to_bits(size)? == right.to_bits(size)?,

tests/run-pass/rc.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::cell::{Cell, RefCell};
22
use std::rc::Rc;
33
use std::sync::Arc;
4+
use std::fmt::Debug;
45

56
fn rc_refcell() {
67
let r = Rc::new(RefCell::new(42));
@@ -60,7 +61,16 @@ fn rc_from() {
6061
check_unique_rc::<str>(Rc::from("Hello, World!"));
6162
}
6263

64+
fn rc_fat_ptr_eq() {
65+
let p = Rc::new(1) as Rc<Debug>;
66+
let a: *const Debug = &*p;
67+
let r = Rc::into_raw(p);
68+
let _b = a == r;
69+
drop(unsafe { Rc::from_raw(r) });
70+
}
71+
6372
fn main() {
73+
rc_fat_ptr_eq();
6474
rc_refcell();
6575
rc_refcell2();
6676
rc_cell();

0 commit comments

Comments
 (0)