use rustc_hir::def::{DefKind, Res};
use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp};
use rustc_lint::LateContext;
+use rustc_middle::mir::interpret::Scalar;
use rustc_middle::ty::subst::{Subst, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Symbol;
use std::cmp::Ordering::{self, Equal};
Tuple(Vec<Constant>),
/// A raw pointer.
RawPtr(u128),
+ /// A reference
+ Ref(Box<Constant>),
/// A literal with syntax error.
Err(Symbol),
}
(&Self::Bool(l), &Self::Bool(r)) => l == r,
(&Self::Vec(ref l), &Self::Vec(ref r)) | (&Self::Tuple(ref l), &Self::Tuple(ref r)) => l == r,
(&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => ls == rs && lv == rv,
+ (&Self::Ref(ref lb), &Self::Ref(ref rb)) => *lb == *rb,
// TODO: are there inter-type equalities?
_ => false,
}
Self::RawPtr(u) => {
u.hash(state);
},
+ Self::Ref(ref r) => {
+ r.hash(state);
+ },
Self::Err(ref s) => {
s.hash(state);
},
x => x,
}
},
+ (&Self::Ref(ref lb), &Self::Ref(ref rb)) => Self::partial_cmp(tcx, cmp_type, lb, rb),
// TODO: are there any useful inter-type orderings?
_ => None,
}
ExprKind::Unary(op, ref operand) => self.expr(operand).and_then(|o| match op {
UnOp::UnNot => self.constant_not(&o, self.typeck_results.expr_ty(e)),
UnOp::UnNeg => self.constant_negate(&o, self.typeck_results.expr_ty(e)),
- UnOp::UnDeref => Some(o),
+ UnOp::UnDeref => Some(if let Constant::Ref(r) = o { *r } else { o }),
}),
ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right),
ExprKind::Call(ref callee, ref args) => {
}
},
ExprKind::Index(ref arr, ref index) => self.index(arr, index),
+ ExprKind::AddrOf(_, _, ref inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))),
// TODO: add other expressions.
_ => None,
}
}
pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
- use rustc_middle::mir::interpret::{ConstValue, Scalar};
+ use rustc_middle::mir::interpret::ConstValue;
match result.val {
- ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: d, .. })) => {
+ ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(int))) => {
match result.ty.kind() {
- ty::Bool => Some(Constant::Bool(d == 1)),
- ty::Uint(_) | ty::Int(_) => Some(Constant::Int(d)),
+ ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
+ ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
- d.try_into().expect("invalid f32 bit representation"),
+ int.try_into().expect("invalid f32 bit representation"),
))),
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
- d.try_into().expect("invalid f64 bit representation"),
+ int.try_into().expect("invalid f64 bit representation"),
))),
ty::RawPtr(type_and_mut) => {
if let ty::Uint(_) = type_and_mut.ty.kind() {
- return Some(Constant::RawPtr(d));
+ return Some(Constant::RawPtr(int.assert_bits(int.size())));
}
None
},