Fix comparing fat pointers
This commit is contained in:
parent
457741d6d2
commit
2c3ee678b1
@ -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;
|
||||
|
||||
|
@ -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)?,
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user