diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs
index 8949e4cc387..53d0d7cebaa 100644
--- a/clippy_lints/src/array_indexing.rs
+++ b/clippy_lints/src/array_indexing.rs
@@ -1,13 +1,9 @@
use rustc::lint::*;
-use rustc::middle::const_val::ConstVal;
use rustc::ty;
-use rustc::ty::subst::Substs;
-use rustc_const_eval::ConstContext;
-use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
use rustc::hir;
use syntax::ast::RangeLimits;
use utils::{self, higher};
-use utils::const_to_u64;
+use consts::{constant, Constant};
/// **What it does:** Checks for out of bounds array indexing with a constant
/// index.
@@ -63,29 +59,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
// Array with known size can be checked statically
let ty = cx.tables.expr_ty(array);
if let ty::TyArray(_, size) = ty.sty {
- let size = ConstInt::Usize(
- ConstUsize::new(const_to_u64(size), cx.sess().target.usize_ty).expect("array size is invalid"),
- );
- let parent_item = cx.tcx.hir.get_parent(e.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables);
+ let size = size.val.to_raw_bits().unwrap();
// Index is a constant uint
- if let Ok(const_index) = constcx.eval(index) {
- if let ConstVal::Integral(const_index) = const_index.val {
- if size <= const_index {
- utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds");
- }
-
- return;
+ if let Some((Constant::Int(const_index), _)) = constant(cx, index) {
+ if size <= const_index {
+ utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds");
}
+
+ return;
}
// Index is a constant range
if let Some(range) = higher::range(index) {
- let start = range.start.map(|start| constcx.eval(start)).map(|v| v.ok());
- let end = range.end.map(|end| constcx.eval(end)).map(|v| v.ok());
+ let start = range.start.map(|start| constant(cx, start).map(|(c, _)| c));
+ let end = range.end.map(|end| constant(cx, end).map(|(c, _)| c));
if let Some((start, end)) = to_const_range(&start, &end, range.limits, size) {
if start > size || end > size {
@@ -114,43 +102,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
/// Returns an option containing a tuple with the start and end (exclusive) of
/// the range.
fn to_const_range(
- start: &Option>,
- end: &Option >,
+ start: &Option >,
+ end: &Option >,
limits: RangeLimits,
- array_size: ConstInt,
-) -> Option<(ConstInt, ConstInt)> {
+ array_size: u128,
+) -> Option<(u128, u128)> {
let start = match *start {
- Some(Some(&ty::Const {
- val: ConstVal::Integral(x),
- ..
- })) => x,
+ Some(Some(Constant::Int(x))) => x,
Some(_) => return None,
- None => ConstInt::U8(0),
+ None => 0,
};
let end = match *end {
- Some(Some(&ty::Const {
- val: ConstVal::Integral(x),
- ..
- })) => if limits == RangeLimits::Closed {
- match x {
- ConstInt::U8(_) => (x + ConstInt::U8(1)),
- ConstInt::U16(_) => (x + ConstInt::U16(1)),
- ConstInt::U32(_) => (x + ConstInt::U32(1)),
- ConstInt::U64(_) => (x + ConstInt::U64(1)),
- ConstInt::U128(_) => (x + ConstInt::U128(1)),
- ConstInt::Usize(ConstUsize::Us16(_)) => (x + ConstInt::Usize(ConstUsize::Us16(1))),
- ConstInt::Usize(ConstUsize::Us32(_)) => (x + ConstInt::Usize(ConstUsize::Us32(1))),
- ConstInt::Usize(ConstUsize::Us64(_)) => (x + ConstInt::Usize(ConstUsize::Us64(1))),
- ConstInt::I8(_) => (x + ConstInt::I8(1)),
- ConstInt::I16(_) => (x + ConstInt::I16(1)),
- ConstInt::I32(_) => (x + ConstInt::I32(1)),
- ConstInt::I64(_) => (x + ConstInt::I64(1)),
- ConstInt::I128(_) => (x + ConstInt::I128(1)),
- ConstInt::Isize(ConstIsize::Is16(_)) => (x + ConstInt::Isize(ConstIsize::Is16(1))),
- ConstInt::Isize(ConstIsize::Is32(_)) => (x + ConstInt::Isize(ConstIsize::Is32(1))),
- ConstInt::Isize(ConstIsize::Is64(_)) => (x + ConstInt::Isize(ConstIsize::Is64(1))),
- }.expect("such a big array is not realistic")
+ Some(Some(Constant::Int(x))) => if limits == RangeLimits::Closed {
+ x + 1
} else {
x
},
diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs
index f0ff27d4d63..7eb6477b269 100644
--- a/clippy_lints/src/bit_mask.rs
+++ b/clippy_lints/src/bit_mask.rs
@@ -1,11 +1,10 @@
use rustc::hir::*;
-use rustc::hir::def::Def;
use rustc::lint::*;
-use rustc_const_eval::lookup_const_by_id;
use syntax::ast::LitKind;
use syntax::codemap::Span;
use utils::{span_lint, span_lint_and_then};
use utils::sugg::Sugg;
+use consts::{constant, Constant};
/// **What it does:** Checks for incompatible bit masks in comparisons.
///
@@ -302,31 +301,8 @@ fn check_ineffective_gt(cx: &LateContext, span: Span, m: u128, c: u128, op: &str
}
fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option {
- use rustc::ty::subst::Substs;
- match lit.node {
- ExprLit(ref lit_ptr) => {
- if let LitKind::Int(value, _) = lit_ptr.node {
- Some(value) // TODO: Handle sign
- } else {
- None
- }
- },
- ExprPath(ref qpath) => {
- let def = cx.tables.qpath_def(qpath, lit.hir_id);
- if let Def::Const(def_id) = def {
- lookup_const_by_id(cx.tcx, cx.param_env.and((def_id, Substs::empty()))).and_then(|(l, _ty)| {
- let body = if let Some(id) = cx.tcx.hir.as_local_node_id(l) {
- cx.tcx.mir_const_qualif(def_id);
- cx.tcx.hir.body(cx.tcx.hir.body_owned_by(id))
- } else {
- cx.tcx.extern_const_body(def_id).body
- };
- fetch_int_literal(cx, &body.value)
- })
- } else {
- None
- }
- },
+ match constant(cx, lit)?.0 {
+ Constant::Int(n) => Some(n),
_ => None,
}
}
diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs
index a99a56bc554..7c43cb668b3 100644
--- a/clippy_lints/src/consts.rs
+++ b/clippy_lints/src/consts.rs
@@ -2,19 +2,18 @@
use rustc::lint::LateContext;
use rustc::hir::def::Def;
-use rustc_const_eval::lookup_const_by_id;
-use rustc_const_math::ConstInt;
use rustc::hir::*;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, Instance};
use rustc::ty::subst::{Subst, Substs};
use std::cmp::Ordering::{self, Equal};
use std::cmp::PartialOrd;
use std::hash::{Hash, Hasher};
use std::mem;
use std::rc::Rc;
-use syntax::ast::{FloatTy, LitKind, StrStyle};
+use syntax::ast::{FloatTy, LitKind};
use syntax::ptr::P;
-use utils::const_to_u64;
+use rustc::middle::const_val::ConstVal;
+use utils::{sext, unsext, clip};
#[derive(Debug, Copy, Clone)]
pub enum FloatWidth {
@@ -36,15 +35,17 @@ impl From for FloatWidth {
#[derive(Debug, Clone)]
pub enum Constant {
/// a String "abc"
- Str(String, StrStyle),
+ Str(String),
/// a Binary String b"abc"
Binary(Rc>),
/// a single char 'a'
Char(char),
- /// an integer, third argument is whether the value is negated
- Int(ConstInt),
- /// a float with given type
- Float(String, FloatWidth),
+ /// an integer's bit representation
+ Int(u128),
+ /// an f32
+ F32(f32),
+ /// an f64
+ F64(f64),
/// true or false
Bool(bool),
/// an array of constants
@@ -58,20 +59,21 @@ pub enum Constant {
impl PartialEq for Constant {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
- (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => ls == rs && l_sty == r_sty,
+ (&Constant::Str(ref ls), &Constant::Str(ref rs)) => ls == rs,
(&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r,
(&Constant::Char(l), &Constant::Char(r)) => l == r,
- (&Constant::Int(l), &Constant::Int(r)) => {
- l.is_negative() == r.is_negative() && l.to_u128_unchecked() == r.to_u128_unchecked()
- },
- (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => {
+ (&Constant::Int(l), &Constant::Int(r)) => l == r,
+ (&Constant::F64(l), &Constant::F64(r)) => {
// we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have
// `Fw32 == Fw64` so don’t compare them
- match (ls.parse::(), rs.parse::()) {
- // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs
- (Ok(l), Ok(r)) => unsafe { mem::transmute::(l) == mem::transmute::(r) },
- _ => false,
- }
+ // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs
+ unsafe { mem::transmute::(l) == mem::transmute::(r) }
+ },
+ (&Constant::F32(l), &Constant::F32(r)) => {
+ // we want `Fw32 == FwAny` and `FwAny == Fw64`, by transitivity we must have
+ // `Fw32 == Fw64` so don’t compare them
+ // mem::transmute is required to catch non-matching 0.0, -0.0, and NaNs
+ unsafe { mem::transmute::(l as f64) == mem::transmute::(r as f64) }
},
(&Constant::Bool(l), &Constant::Bool(r)) => l == r,
(&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => l == r,
@@ -87,9 +89,8 @@ impl Hash for Constant {
H: Hasher,
{
match *self {
- Constant::Str(ref s, ref k) => {
+ Constant::Str(ref s) => {
s.hash(state);
- k.hash(state);
},
Constant::Binary(ref b) => {
b.hash(state);
@@ -98,14 +99,13 @@ impl Hash for Constant {
c.hash(state);
},
Constant::Int(i) => {
- i.to_u128_unchecked().hash(state);
- i.is_negative().hash(state);
+ i.hash(state);
},
- Constant::Float(ref f, _) => {
- // don’t use the width here because of PartialEq implementation
- if let Ok(f) = f.parse::() {
- unsafe { mem::transmute::(f) }.hash(state);
- }
+ Constant::F32(f) => {
+ unsafe { mem::transmute::(f as f64) }.hash(state);
+ },
+ Constant::F64(f) => {
+ unsafe { mem::transmute::(f) }.hash(state);
},
Constant::Bool(b) => {
b.hash(state);
@@ -124,25 +124,11 @@ impl Hash for Constant {
impl PartialOrd for Constant {
fn partial_cmp(&self, other: &Self) -> Option {
match (self, other) {
- (&Constant::Str(ref ls, ref l_sty), &Constant::Str(ref rs, ref r_sty)) => if l_sty == r_sty {
- Some(ls.cmp(rs))
- } else {
- None
- },
+ (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)),
(&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)),
(&Constant::Int(l), &Constant::Int(r)) => Some(l.cmp(&r)),
- (&Constant::Float(ref ls, _), &Constant::Float(ref rs, _)) => {
- match (ls.parse::(), rs.parse::()) {
- (Ok(ref l), Ok(ref r)) => {
- match (l.partial_cmp(r), l.is_sign_positive() == r.is_sign_positive()) {
- // Check for comparison of -0.0 and 0.0
- (Some(Ordering::Equal), false) => None,
- (x, _) => x,
- }
- },
- _ => None,
- }
- },
+ (&Constant::F64(l), &Constant::F64(r)) => l.partial_cmp(&r),
+ (&Constant::F32(l), &Constant::F32(r)) => l.partial_cmp(&r),
(&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)),
(&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => {
l.partial_cmp(r)
@@ -157,63 +143,25 @@ impl PartialOrd for Constant {
}
/// parse a `LitKind` to a `Constant`
-#[allow(cast_possible_wrap)]
-pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut ty: Ty<'tcx>) -> Constant {
+pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant {
use syntax::ast::*;
- use syntax::ast::LitIntType::*;
- use rustc::ty::util::IntTypeExt;
- if let ty::TyAdt(adt, _) = ty.sty {
- if adt.is_enum() {
- ty = adt.repr.discr_type().to_ty(tcx)
- }
- }
match *lit {
- LitKind::Str(ref is, style) => Constant::Str(is.to_string(), style),
- LitKind::Byte(b) => Constant::Int(ConstInt::U8(b)),
+ LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
+ LitKind::Byte(b) => Constant::Int(b as u128),
LitKind::ByteStr(ref s) => Constant::Binary(Rc::clone(s)),
LitKind::Char(c) => Constant::Char(c),
- LitKind::Int(n, hint) => match (&ty.sty, hint) {
- (&ty::TyInt(ity), _) | (_, Signed(ity)) => {
- Constant::Int(ConstInt::new_signed_truncating(n as i128, ity, tcx.sess.target.isize_ty))
- },
- (&ty::TyUint(uty), _) | (_, Unsigned(uty)) => {
- Constant::Int(ConstInt::new_unsigned_truncating(n as u128, uty, tcx.sess.target.usize_ty))
- },
+ LitKind::Int(n, _) => Constant::Int(n),
+ LitKind::Float(ref is, _) |
+ LitKind::FloatUnsuffixed(ref is) => match ty.sty {
+ ty::TyFloat(FloatTy::F32) => Constant::F32(is.as_str().parse().unwrap()),
+ ty::TyFloat(FloatTy::F64) => Constant::F64(is.as_str().parse().unwrap()),
_ => bug!(),
},
- LitKind::Float(ref is, ty) => Constant::Float(is.to_string(), ty.into()),
- LitKind::FloatUnsuffixed(ref is) => Constant::Float(is.to_string(), FloatWidth::Any),
LitKind::Bool(b) => Constant::Bool(b),
}
}
-fn constant_not(o: &Constant) -> Option {
- use self::Constant::*;
- match *o {
- Bool(b) => Some(Bool(!b)),
- Int(value) => (!value).ok().map(Int),
- _ => None,
- }
-}
-
-fn constant_negate(o: Constant) -> Option {
- use self::Constant::*;
- match o {
- Int(value) => (-value).ok().map(Int),
- Float(is, ty) => Some(Float(neg_float_str(&is), ty)),
- _ => None,
- }
-}
-
-fn neg_float_str(s: &str) -> String {
- if s.starts_with('-') {
- s[1..].to_owned()
- } else {
- format!("-{}", s)
- }
-}
-
pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> {
let mut cx = ConstEvalLateContext {
tcx: lcx.tcx,
@@ -255,19 +203,19 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
ExprPath(ref qpath) => self.fetch_path(qpath, e.hir_id),
ExprBlock(ref block) => self.block(block),
ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise),
- ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tcx, self.tables.expr_ty(e))),
+ ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tables.expr_ty(e))),
ExprArray(ref vec) => self.multi(vec).map(Constant::Vec),
ExprTup(ref tup) => self.multi(tup).map(Constant::Tuple),
ExprRepeat(ref value, _) => {
let n = match self.tables.expr_ty(e).sty {
- ty::TyArray(_, n) => const_to_u64(n),
+ ty::TyArray(_, n) => n.val.to_raw_bits().expect("array length"),
_ => span_bug!(e.span, "typeck error"),
};
- self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))
+ self.expr(value).map(|v| Constant::Repeat(Box::new(v), n as u64))
},
ExprUnary(op, ref operand) => self.expr(operand).and_then(|o| match op {
- UnNot => constant_not(&o),
- UnNeg => constant_negate(o),
+ UnNot => self.constant_not(&o, self.tables.expr_ty(e)),
+ UnNeg => self.constant_negate(o, self.tables.expr_ty(e)),
UnDeref => Some(o),
}),
ExprBinary(op, ref left, ref right) => self.binop(op, left, right),
@@ -276,6 +224,42 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
}
}
+ fn constant_not(&self, o: &Constant, ty: ty::Ty) -> Option {
+ use self::Constant::*;
+ match *o {
+ Bool(b) => Some(Bool(!b)),
+ Int(value) => {
+ let mut value = !value;
+ match ty.sty {
+ ty::TyInt(ity) => Some(Int(unsext(self.tcx, value as i128, ity))),
+ ty::TyUint(ity) => Some(Int(clip(self.tcx, value, ity))),
+ _ => None,
+ }
+ },
+ _ => None,
+ }
+ }
+
+ fn constant_negate(&self, o: Constant, ty: ty::Ty) -> Option {
+ use self::Constant::*;
+ match o {
+ Int(value) => {
+ let ity = match ty.sty {
+ ty::TyInt(ity) => ity,
+ _ => return None,
+ };
+ // sign extend
+ let value = sext(self.tcx, value, ity);
+ let value = value.checked_neg()?;
+ // clear unused bits
+ Some(Int(unsext(self.tcx, value, ity)))
+ },
+ F32(f) => Some(F32(-f)),
+ F64(f) => Some(F64(-f)),
+ _ => None,
+ }
+ }
+
/// create `Some(Vec![..])` of all constants, unless there is any
/// non-constant part
fn multi(&mut self, vec: &[Expr]) -> Option> {
@@ -295,27 +279,18 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
} else {
substs.subst(self.tcx, self.substs)
};
- let param_env = self.param_env.and((def_id, substs));
- if let Some((def_id, substs)) = lookup_const_by_id(self.tcx, param_env) {
- let mut cx = Self {
- tcx: self.tcx,
- tables: self.tcx.typeck_tables_of(def_id),
- needed_resolution: false,
- substs: substs,
- param_env: param_env.param_env,
- };
- let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
- self.tcx.mir_const_qualif(def_id);
- self.tcx.hir.body(self.tcx.hir.body_owned_by(id))
- } else {
- self.tcx.extern_const_body(def_id).body
- };
- let ret = cx.expr(&body.value);
- if ret.is_some() {
- self.needed_resolution = true;
- }
- return ret;
+ let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs)?;
+ let gid = GlobalId {
+ instance,
+ promoted: None,
+ };
+ use rustc::mir::interpret::GlobalId;
+ let result = self.tcx.const_eval(self.param_env.and(gid)).ok()?;
+ let ret = miri_to_const(self.tcx, result);
+ if ret.is_some() {
+ self.needed_resolution = true;
}
+ return ret;
},
_ => {},
}
@@ -344,36 +319,127 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
}
fn binop(&mut self, op: BinOp, left: &Expr, right: &Expr) -> Option {
- let l = if let Some(l) = self.expr(left) {
- l
- } else {
- return None;
- };
+ let l = self.expr(left)?;
let r = self.expr(right);
- match (op.node, l, r) {
- (BiAdd, Constant::Int(l), Some(Constant::Int(r))) => (l + r).ok().map(Constant::Int),
- (BiSub, Constant::Int(l), Some(Constant::Int(r))) => (l - r).ok().map(Constant::Int),
- (BiMul, Constant::Int(l), Some(Constant::Int(r))) => (l * r).ok().map(Constant::Int),
- (BiDiv, Constant::Int(l), Some(Constant::Int(r))) => (l / r).ok().map(Constant::Int),
- (BiRem, Constant::Int(l), Some(Constant::Int(r))) => (l % r).ok().map(Constant::Int),
- (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)),
- (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)),
- (BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r),
- (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)),
- (BiBitXor, Constant::Int(l), Some(Constant::Int(r))) => (l ^ r).ok().map(Constant::Int),
- (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)),
- (BiBitAnd, Constant::Int(l), Some(Constant::Int(r))) => (l & r).ok().map(Constant::Int),
- (BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)),
- (BiBitOr, Constant::Int(l), Some(Constant::Int(r))) => (l | r).ok().map(Constant::Int),
- (BiShl, Constant::Int(l), Some(Constant::Int(r))) => (l << r).ok().map(Constant::Int),
- (BiShr, Constant::Int(l), Some(Constant::Int(r))) => (l >> r).ok().map(Constant::Int),
- (BiEq, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l == r)),
- (BiNe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l != r)),
- (BiLt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l < r)),
- (BiLe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l <= r)),
- (BiGe, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l >= r)),
- (BiGt, Constant::Int(l), Some(Constant::Int(r))) => Some(Constant::Bool(l > r)),
- _ => None,
+ match (l, r) {
+ (Constant::Int(l), Some(Constant::Int(r))) => {
+ match self.tables.expr_ty(left).sty {
+ ty::TyInt(ity) => {
+ let l = sext(self.tcx, l, ity);
+ let r = sext(self.tcx, r, ity);
+ let zext = |n: i128| Constant::Int(unsext(self.tcx, n, ity));
+ match op.node {
+ BiAdd => l.checked_add(r).map(zext),
+ BiSub => l.checked_sub(r).map(zext),
+ BiMul => l.checked_mul(r).map(zext),
+ BiDiv if r != 0 => l.checked_div(r).map(zext),
+ BiRem if r != 0 => l.checked_rem(r).map(zext),
+ BiShr => l.checked_shr(r as u128 as u32).map(zext),
+ BiShl => l.checked_shl(r as u128 as u32).map(zext),
+ BiBitXor => Some(zext(l ^ r)),
+ BiBitOr => Some(zext(l | r)),
+ BiBitAnd => Some(zext(l & r)),
+ BiEq => Some(Constant::Bool(l == r)),
+ BiNe => Some(Constant::Bool(l != r)),
+ BiLt => Some(Constant::Bool(l < r)),
+ BiLe => Some(Constant::Bool(l <= r)),
+ BiGe => Some(Constant::Bool(l >= r)),
+ BiGt => Some(Constant::Bool(l > r)),
+ _ => None,
+ }
+ }
+ ty::TyUint(_) => {
+ match op.node {
+ BiAdd => l.checked_add(r).map(Constant::Int),
+ BiSub => l.checked_sub(r).map(Constant::Int),
+ BiMul => l.checked_mul(r).map(Constant::Int),
+ BiDiv => l.checked_div(r).map(Constant::Int),
+ BiRem => l.checked_rem(r).map(Constant::Int),
+ BiShr => l.checked_shr(r as u32).map(Constant::Int),
+ BiShl => l.checked_shl(r as u32).map(Constant::Int),
+ BiBitXor => Some(Constant::Int(l ^ r)),
+ BiBitOr => Some(Constant::Int(l | r)),
+ BiBitAnd => Some(Constant::Int(l & r)),
+ BiEq => Some(Constant::Bool(l == r)),
+ BiNe => Some(Constant::Bool(l != r)),
+ BiLt => Some(Constant::Bool(l < r)),
+ BiLe => Some(Constant::Bool(l <= r)),
+ BiGe => Some(Constant::Bool(l >= r)),
+ BiGt => Some(Constant::Bool(l > r)),
+ _ => None,
+ }
+ },
+ _ => None,
+ }
+ },
+ (Constant::F32(l), Some(Constant::F32(r))) => match op.node {
+ BiAdd => Some(Constant::F32(l + r)),
+ BiSub => Some(Constant::F32(l - r)),
+ BiMul => Some(Constant::F32(l * r)),
+ BiDiv => Some(Constant::F32(l / r)),
+ BiRem => Some(Constant::F32(l * r)),
+ BiEq => Some(Constant::Bool(l == r)),
+ BiNe => Some(Constant::Bool(l != r)),
+ BiLt => Some(Constant::Bool(l < r)),
+ BiLe => Some(Constant::Bool(l <= r)),
+ BiGe => Some(Constant::Bool(l >= r)),
+ BiGt => Some(Constant::Bool(l > r)),
+ _ => None,
+ },
+ (Constant::F64(l), Some(Constant::F64(r))) => match op.node {
+ BiAdd => Some(Constant::F64(l + r)),
+ BiSub => Some(Constant::F64(l - r)),
+ BiMul => Some(Constant::F64(l * r)),
+ BiDiv => Some(Constant::F64(l / r)),
+ BiRem => Some(Constant::F64(l * r)),
+ BiEq => Some(Constant::Bool(l == r)),
+ BiNe => Some(Constant::Bool(l != r)),
+ BiLt => Some(Constant::Bool(l < r)),
+ BiLe => Some(Constant::Bool(l <= r)),
+ BiGe => Some(Constant::Bool(l >= r)),
+ BiGt => Some(Constant::Bool(l > r)),
+ _ => None,
+ },
+ (l, r) => match (op.node, l, r) {
+ (BiAnd, Constant::Bool(false), _) => Some(Constant::Bool(false)),
+ (BiOr, Constant::Bool(true), _) => Some(Constant::Bool(true)),
+ (BiAnd, Constant::Bool(true), Some(r)) | (BiOr, Constant::Bool(false), Some(r)) => Some(r),
+ (BiBitXor, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l ^ r)),
+ (BiBitAnd, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l & r)),
+ (BiBitOr, Constant::Bool(l), Some(Constant::Bool(r))) => Some(Constant::Bool(l | r)),
+ _ => None,
+ },
}
}
}
+
+pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<'tcx>) -> Option {
+ use rustc::mir::interpret::{Value, PrimVal};
+ match result.val {
+ ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => match result.ty.sty {
+ ty::TyBool => Some(Constant::Bool(b == 1)),
+ ty::TyUint(_) | ty::TyInt(_) => Some(Constant::Int(b)),
+ ty::TyFloat(FloatTy::F32) => Some(Constant::F32(f32::from_bits(b as u32))),
+ ty::TyFloat(FloatTy::F64) => Some(Constant::F64(f64::from_bits(b as u64))),
+ // FIXME: implement other conversion
+ _ => None,
+ },
+ ConstVal::Value(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(n))) => match result.ty.sty {
+ ty::TyRef(_, tam) => match tam.ty.sty {
+ ty::TyStr => {
+ let alloc = tcx
+ .interpret_interner
+ .get_alloc(ptr.alloc_id)
+ .unwrap();
+ let offset = ptr.offset as usize;
+ let n = n as usize;
+ String::from_utf8(alloc.bytes[offset..(offset + n)].to_owned()).ok().map(Constant::Str)
+ },
+ _ => None,
+ },
+ _ => None,
+ }
+ // FIXME: implement other conversions
+ _ => None,
+ }
+}
diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs
index c65cf92590a..3abd42d37c9 100644
--- a/clippy_lints/src/enum_clike.rs
+++ b/clippy_lints/src/enum_clike.rs
@@ -2,13 +2,14 @@
//! don't fit into an `i32`
use rustc::lint::*;
-use rustc::middle::const_val::ConstVal;
-use rustc_const_math::*;
use rustc::hir::*;
use rustc::ty;
-use rustc::traits::Reveal;
use rustc::ty::subst::Substs;
+use syntax::ast::{IntTy, UintTy};
use utils::span_lint;
+use consts::{Constant, miri_to_const};
+use rustc::ty::util::IntTypeExt;
+use rustc::mir::interpret::GlobalId;
/// **What it does:** Checks for C-like enumerations that are
/// `repr(isize/usize)` and have values that don't fit into an `i32`.
@@ -43,36 +44,46 @@ impl LintPass for UnportableVariant {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant {
#[allow(cast_possible_truncation, cast_sign_loss)]
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
+ if cx.tcx.data_layout.pointer_size.bits() != 64 {
+ return;
+ }
if let ItemEnum(ref def, _) = item.node {
for var in &def.variants {
let variant = &var.node;
if let Some(body_id) = variant.disr_expr {
- let expr = &cx.tcx.hir.body(body_id).value;
+ let param_env = ty::ParamEnv::empty();
let did = cx.tcx.hir.body_owner_def_id(body_id);
- let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
let substs = Substs::identity_for_item(cx.tcx.global_tcx(), did);
- let bad = match cx.tcx
- .at(expr.span)
- .const_eval(param_env.and((did, substs)))
- {
- Ok(&ty::Const {
- val: ConstVal::Integral(Usize(Us64(i))),
- ..
- }) => u64::from(i as u32) != i,
- Ok(&ty::Const {
- val: ConstVal::Integral(Isize(Is64(i))),
- ..
- }) => i64::from(i as i32) != i,
- _ => false,
+ let instance = ty::Instance::new(did, substs);
+ let cid = GlobalId {
+ instance,
+ promoted: None
};
- if bad {
+ let constant = cx.tcx.const_eval(param_env.and(cid)).ok();
+ if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
+ let mut ty = cx.tcx.type_of(did);
+ if let ty::TyAdt(adt, _) = ty.sty {
+ if adt.is_enum() {
+ ty = adt.repr.discr_type().to_ty(cx.tcx);
+ }
+ }
+ match ty.sty {
+ ty::TyInt(IntTy::Isize) => {
+ let val = ((val as i128) << 64) >> 64;
+ if val <= i32::max_value() as i128 && val >= i32::min_value() as i128 {
+ continue;
+ }
+ }
+ ty::TyUint(UintTy::Usize) if val > u32::max_value() as u128 => {},
+ _ => continue,
+ }
span_lint(
cx,
ENUM_CLIKE_UNPORTABLE_VARIANT,
var.span,
"Clike enum variant discriminant is not portable to 32-bit targets",
);
- }
+ };
}
}
}
diff --git a/clippy_lints/src/erasing_op.rs b/clippy_lints/src/erasing_op.rs
index dd8f029501f..a601d91a185 100644
--- a/clippy_lints/src/erasing_op.rs
+++ b/clippy_lints/src/erasing_op.rs
@@ -51,7 +51,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ErasingOp {
fn check(cx: &LateContext, e: &Expr, span: Span) {
if let Some(Constant::Int(v)) = constant_simple(cx, e) {
- if v.to_u128_unchecked() == 0 {
+ if v == 0 {
span_lint(
cx,
ERASING_OP,
diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs
index e1d84a07439..717245ec0f5 100644
--- a/clippy_lints/src/identity_op.rs
+++ b/clippy_lints/src/identity_op.rs
@@ -1,9 +1,9 @@
use consts::{constant_simple, Constant};
use rustc::hir::*;
use rustc::lint::*;
-use rustc_const_math::ConstInt;
use syntax::codemap::Span;
-use utils::{in_macro, snippet, span_lint};
+use utils::{in_macro, snippet, span_lint, unsext, clip};
+use rustc::ty;
/// **What it does:** Checks for identity operations, e.g. `x + 0`.
///
@@ -58,29 +58,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
}
}
-fn all_ones(v: &ConstInt) -> bool {
- match *v {
- ConstInt::I8(i) => i == !0,
- ConstInt::I16(i) => i == !0,
- ConstInt::I32(i) => i == !0,
- ConstInt::I64(i) => i == !0,
- ConstInt::I128(i) => i == !0,
- ConstInt::U8(i) => i == !0,
- ConstInt::U16(i) => i == !0,
- ConstInt::U32(i) => i == !0,
- ConstInt::U64(i) => i == !0,
- ConstInt::U128(i) => i == !0,
- _ => false,
- }
-}
-
#[allow(cast_possible_wrap)]
fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) {
if let Some(Constant::Int(v)) = constant_simple(cx, e) {
+ let check = match cx.tables.expr_ty(e).sty {
+ ty::TyInt(ity) => unsext(cx.tcx, -1i128, ity),
+ ty::TyUint(uty) => clip(cx.tcx, !0, uty),
+ _ => return,
+ };
if match m {
- 0 => v.to_u128_unchecked() == 0,
- -1 => all_ones(&v),
- 1 => v.to_u128_unchecked() == 1,
+ 0 => v == 0,
+ -1 => v == check,
+ 1 => v == 1,
_ => unreachable!(),
} {
span_lint(
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index e1b8ff2dc05..0034e28fac2 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -10,6 +10,7 @@
#![feature(conservative_impl_trait)]
#![feature(inclusive_range_syntax, range_contains)]
#![feature(macro_vis_matcher)]
+#![feature(dotdoteq_in_patterns)]
#![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)]
#![recursion_limit = "256"]
@@ -37,7 +38,6 @@ extern crate regex_syntax;
extern crate quine_mc_cluskey;
-extern crate rustc_const_eval;
extern crate rustc_const_math;
extern crate rustc_errors;
extern crate rustc_plugin;
diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs
index f476b960d88..a0f3db7b784 100644
--- a/clippy_lints/src/loops.rs
+++ b/clippy_lints/src/loops.rs
@@ -6,23 +6,19 @@ use rustc::hir::def_id;
use rustc::hir::intravisit::{walk_block, walk_decl, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
use rustc::hir::map::Node::{NodeBlock, NodeExpr, NodeStmt};
use rustc::lint::*;
-use rustc::middle::const_val::ConstVal;
use rustc::middle::region;
// use rustc::middle::region::CodeExtent;
use rustc::middle::expr_use_visitor::*;
use rustc::middle::mem_categorization::Categorization;
use rustc::middle::mem_categorization::cmt;
use rustc::ty::{self, Ty};
-use rustc::ty::subst::{Subst, Substs};
-use rustc_const_eval::ConstContext;
+use rustc::ty::subst::Subst;
use std::collections::{HashMap, HashSet};
use std::iter::{once, Iterator};
use syntax::ast;
use syntax::codemap::Span;
-use utils::sugg;
-use utils::const_to_u64;
-
-use consts::constant;
+use utils::{sugg, sext};
+use consts::{constant, Constant};
use utils::{get_enclosing_block, get_parent_expr, higher, in_external_macro, is_integer_literal, is_refutable,
last_path_segment, match_trait_method, match_type, match_var, multispan_sugg, snippet, snippet_opt,
@@ -1113,27 +1109,22 @@ fn check_for_loop_reverse_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arg: &'tcx
}) = higher::range(arg)
{
// ...and both sides are compile-time constant integers...
- let parent_item = cx.tcx.hir.get_parent(arg.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables);
- if let Ok(start_idx) = constcx.eval(start) {
- if let Ok(end_idx) = constcx.eval(end) {
+ if let Some((start_idx, _)) = constant(cx, start) {
+ if let Some((end_idx, _)) = constant(cx, end) {
// ...and the start index is greater than the end index,
// this loop will never run. This is often confusing for developers
// who think that this will iterate from the larger value to the
// smaller value.
+ let ty = cx.tables.expr_ty(start);
let (sup, eq) = match (start_idx, end_idx) {
(
- &ty::Const {
- val: ConstVal::Integral(start_idx),
- ..
- },
- &ty::Const {
- val: ConstVal::Integral(end_idx),
- ..
- },
- ) => (start_idx > end_idx, start_idx == end_idx),
+ Constant::Int(start_idx),
+ Constant::Int(end_idx),
+ ) => (match ty.sty {
+ ty::TyInt(ity) => sext(cx.tcx, start_idx, ity) > sext(cx.tcx, end_idx, ity),
+ ty::TyUint(_) => start_idx > end_idx,
+ _ => false,
+ }, start_idx == end_idx),
_ => (false, false),
};
@@ -1220,7 +1211,7 @@ fn check_for_loop_arg(cx: &LateContext, pat: &Pat, arg: &Expr, expr: &Expr) {
match cx.tables.expr_ty(&args[0]).sty {
// If the length is greater than 32 no traits are implemented for array and
// therefore we cannot use `&`.
- ty::TypeVariants::TyArray(_, size) if const_to_u64(size) > 32 => (),
+ ty::TypeVariants::TyArray(_, size) if size.val.to_raw_bits().expect("array size") > 32 => (),
_ => lint_iter_method(cx, args, arg, method_name),
};
} else {
@@ -1795,7 +1786,7 @@ fn is_ref_iterable_type(cx: &LateContext, e: &Expr) -> bool {
fn is_iterable_array(ty: Ty) -> bool {
// IntoIterator is currently only implemented for array sizes <= 32 in rustc
match ty.sty {
- ty::TyArray(_, n) => (0..=32).contains(const_to_u64(n)),
+ ty::TyArray(_, n) => (0..=32).contains(n.val.to_raw_bits().expect("array length")),
_ => false,
}
}
@@ -2249,4 +2240,4 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
}
fn decl_without_init(&mut self, _: NodeId, _: Span) {}
-}
\ No newline at end of file
+}
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index 979f0806e52..b617f098e3e 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -1,19 +1,15 @@
use rustc::hir::*;
use rustc::lint::*;
-use rustc::middle::const_val::ConstVal;
use rustc::ty::{self, Ty};
-use rustc::ty::subst::Substs;
-use rustc_const_eval::ConstContext;
-use rustc_const_math::ConstInt;
use std::cmp::Ordering;
use std::collections::Bound;
use syntax::ast::LitKind;
-use syntax::ast::NodeId;
use syntax::codemap::Span;
use utils::paths;
use utils::{expr_block, in_external_macro, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg,
remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty};
use utils::sugg::Sugg;
+use consts::{constant, Constant};
/// **What it does:** Checks for matches with a single arm where an `if let`
/// will usually suffice.
@@ -343,7 +339,7 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr, arms: &'tcx [Arm]) {
if arms.len() >= 2 && cx.tables.expr_ty(ex).is_integral() {
- let ranges = all_ranges(cx, arms, ex.id);
+ let ranges = all_ranges(cx, arms);
let type_ranges = type_ranges(&ranges);
if !type_ranges.is_empty() {
if let Some((start, end)) = overlapping(&type_ranges) {
@@ -460,12 +456,7 @@ fn check_match_as_ref(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
fn all_ranges<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
arms: &'tcx [Arm],
- id: NodeId,
-) -> Vec>> {
- let parent_item = cx.tcx.hir.get_parent(id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- let constcx = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables);
+) -> Vec> {
arms.iter()
.flat_map(|arm| {
if let Arm {
@@ -478,25 +469,19 @@ fn all_ranges<'a, 'tcx>(
} else {
[].iter()
}.filter_map(|pat| {
- if_chain! {
- if let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node;
- if let Ok(lhs) = constcx.eval(lhs);
- if let Ok(rhs) = constcx.eval(rhs);
- then {
- let rhs = match *range_end {
- RangeEnd::Included => Bound::Included(rhs),
- RangeEnd::Excluded => Bound::Excluded(rhs),
- };
- return Some(SpannedRange { span: pat.span, node: (lhs, rhs) });
- }
+ if let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node {
+ let lhs = constant(cx, lhs)?.0;
+ let rhs = constant(cx, rhs)?.0;
+ let rhs = match *range_end {
+ RangeEnd::Included => Bound::Included(rhs),
+ RangeEnd::Excluded => Bound::Excluded(rhs),
+ };
+ return Some(SpannedRange { span: pat.span, node: (lhs, rhs) });
}
- if_chain! {
- if let PatKind::Lit(ref value) = pat.node;
- if let Ok(value) = constcx.eval(value);
- then {
- return Some(SpannedRange { span: pat.span, node: (value, Bound::Included(value)) });
- }
+ if let PatKind::Lit(ref value) = pat.node {
+ let value = constant(cx, value)?.0;
+ return Some(SpannedRange { span: pat.span, node: (value.clone(), Bound::Included(value)) });
}
None
@@ -511,46 +496,31 @@ pub struct SpannedRange {
pub node: (T, Bound),
}
-type TypedRanges = Vec>;
+type TypedRanges = Vec>;
/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway
/// and other types than
/// `Uint` and `Int` probably don't make sense.
-fn type_ranges(ranges: &[SpannedRange<&ty::Const>]) -> TypedRanges {
+fn type_ranges(ranges: &[SpannedRange]) -> TypedRanges {
ranges
.iter()
.filter_map(|range| match range.node {
(
- &ty::Const {
- val: ConstVal::Integral(start),
- ..
- },
- Bound::Included(&ty::Const {
- val: ConstVal::Integral(end),
- ..
- }),
+ Constant::Int(start),
+ Bound::Included(Constant::Int(end)),
) => Some(SpannedRange {
span: range.span,
node: (start, Bound::Included(end)),
}),
(
- &ty::Const {
- val: ConstVal::Integral(start),
- ..
- },
- Bound::Excluded(&ty::Const {
- val: ConstVal::Integral(end),
- ..
- }),
+ Constant::Int(start),
+ Bound::Excluded(Constant::Int(end)),
) => Some(SpannedRange {
span: range.span,
node: (start, Bound::Excluded(end)),
}),
(
- &ty::Const {
- val: ConstVal::Integral(start),
- ..
- },
+ Constant::Int(start),
Bound::Unbounded,
) => Some(SpannedRange {
span: range.span,
diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs
index 57d93b44328..0e55d0f8a3a 100644
--- a/clippy_lints/src/methods.rs
+++ b/clippy_lints/src/methods.rs
@@ -1,10 +1,7 @@
use rustc::hir;
use rustc::lint::*;
-use rustc::middle::const_val::ConstVal;
use rustc::ty::{self, Ty};
use rustc::hir::def::Def;
-use rustc::ty::subst::Substs;
-use rustc_const_eval::ConstContext;
use std::borrow::Cow;
use std::fmt;
use std::iter;
@@ -16,7 +13,7 @@ use utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro,
span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
use utils::paths;
use utils::sugg;
-use utils::const_to_u64;
+use consts::{constant, Constant};
#[derive(Clone)]
pub struct Pass;
@@ -1302,7 +1299,7 @@ fn derefs_to_slice(cx: &LateContext, expr: &hir::Expr, ty: Ty) -> Option true,
ty::TyAdt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
ty::TyAdt(..) => match_type(cx, ty, &paths::VEC),
- ty::TyArray(_, size) => const_to_u64(size) < 32,
+ ty::TyArray(_, size) => size.val.to_raw_bits().expect("array length") < 32,
ty::TyRef(_, ty::TypeAndMut { ty: inner, .. }) => may_slice(cx, inner),
_ => false,
}
@@ -1754,14 +1751,7 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: &
/// lint for length-1 `str`s for methods in `PATTERN_METHODS`
fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) {
- let parent_item = cx.tcx.hir.get_parent(arg.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- if let Ok(&ty::Const {
- val: ConstVal::Str(r),
- ..
- }) = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(arg)
- {
+ if let Some((Constant::Str(r), _)) = constant(cx, arg) {
if r.len() == 1 {
let c = r.chars().next().unwrap();
let snip = snippet(cx, expr.span, "..");
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index 04cc488d562..172de7a15a5 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -2,18 +2,14 @@ use reexport::*;
use rustc::hir::*;
use rustc::hir::intravisit::FnKind;
use rustc::lint::*;
-use rustc::middle::const_val::ConstVal;
use rustc::ty;
-use rustc::ty::subst::Substs;
-use rustc_const_eval::ConstContext;
-use rustc_const_math::ConstFloat;
use syntax::codemap::{ExpnFormat, Span};
use utils::{get_item_name, get_parent_expr, implements_trait, in_constant, in_macro, is_integer_literal,
iter_input_pats, last_path_segment, match_qpath, match_trait_method, paths, snippet, span_lint,
span_lint_and_then, walk_ptrs_ty};
use utils::sugg::Sugg;
-use syntax::ast::{FloatTy, LitKind, CRATE_NODE_ID};
-use consts::constant;
+use syntax::ast::{LitKind, CRATE_NODE_ID};
+use consts::{constant, Constant};
/// **What it does:** Checks for function arguments and let bindings denoted as
/// `ref`.
@@ -457,58 +453,10 @@ fn is_named_constant<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) ->
}
fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool {
- let parent_item = cx.tcx.hir.get_parent(expr.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- let res = ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr);
- if let Ok(&ty::Const {
- val: ConstVal::Float(val),
- ..
- }) = res
- {
- use std::cmp::Ordering;
- match val.ty {
- FloatTy::F32 => {
- let zero = ConstFloat {
- ty: FloatTy::F32,
- bits: u128::from(0.0_f32.to_bits()),
- };
-
- let infinity = ConstFloat {
- ty: FloatTy::F32,
- bits: u128::from(::std::f32::INFINITY.to_bits()),
- };
-
- let neg_infinity = ConstFloat {
- ty: FloatTy::F32,
- bits: u128::from(::std::f32::NEG_INFINITY.to_bits()),
- };
-
- val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal)
- || val.try_cmp(neg_infinity) == Ok(Ordering::Equal)
- },
- FloatTy::F64 => {
- let zero = ConstFloat {
- ty: FloatTy::F64,
- bits: u128::from(0.0_f64.to_bits()),
- };
-
- let infinity = ConstFloat {
- ty: FloatTy::F64,
- bits: u128::from(::std::f64::INFINITY.to_bits()),
- };
-
- let neg_infinity = ConstFloat {
- ty: FloatTy::F64,
- bits: u128::from(::std::f64::NEG_INFINITY.to_bits()),
- };
-
- val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal)
- || val.try_cmp(neg_infinity) == Ok(Ordering::Equal)
- },
- }
- } else {
- false
+ match constant(cx, expr) {
+ Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(),
+ Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(),
+ _ => false,
}
}
diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs
index 21a7542e6c7..ca9044c6e8b 100644
--- a/clippy_lints/src/needless_pass_by_value.rs
+++ b/clippy_lints/src/needless_pass_by_value.rs
@@ -205,7 +205,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
let sugg = |db: &mut DiagnosticBuilder| {
if let ty::TypeVariants::TyAdt(ref def, ..) = ty.sty {
if let Some(span) = cx.tcx.hir.span_if_local(def.did) {
- let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing);
+ let param_env = ty::ParamEnv::empty();
if param_env.can_type_implement_copy(cx.tcx, ty, span).is_ok() {
db.span_help(span, "consider marking this type as Copy");
}
diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs
index e34136face9..2ac195f555b 100644
--- a/clippy_lints/src/neg_multiply.rs
+++ b/clippy_lints/src/neg_multiply.rs
@@ -47,8 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply {
fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) {
if_chain! {
if let ExprLit(ref l) = lit.node;
- if let Constant::Int(ref ci) = consts::lit_to_constant(&l.node, cx.tcx, cx.tables.expr_ty(lit));
- if let Some(val) = ci.to_u64();
+ if let Constant::Int(val) = consts::lit_to_constant(&l.node, cx.tables.expr_ty(lit));
if val == 1;
if cx.tables.expr_ty(exp).is_integral();
then {
diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs
index 39252ceed1c..c98df6464d4 100644
--- a/clippy_lints/src/ranges.rs
+++ b/clippy_lints/src/ranges.rs
@@ -94,16 +94,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
// Range with step_by(0).
if name == "step_by" && args.len() == 2 && has_step_by(cx, &args[0]) {
use consts::{constant, Constant};
- use rustc_const_math::ConstInt::Usize;
- if let Some((Constant::Int(Usize(us)), _)) = constant(cx, &args[1]) {
- if us.as_u64() == 0 {
- span_lint(
- cx,
- ITERATOR_STEP_BY_ZERO,
- expr.span,
- "Iterator::step_by(0) will panic at runtime",
- );
- }
+ if let Some((Constant::Int(0), _)) = constant(cx, &args[1]) {
+ span_lint(
+ cx,
+ ITERATOR_STEP_BY_ZERO,
+ expr.span,
+ "Iterator::step_by(0) will panic at runtime",
+ );
}
} else if name == "zip" && args.len() == 2 {
let iter = &args[0].node;
diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs
index f2c08944f50..93ba3f0e8e7 100644
--- a/clippy_lints/src/regex.rs
+++ b/clippy_lints/src/regex.rs
@@ -1,15 +1,11 @@
use regex_syntax;
use rustc::hir::*;
use rustc::lint::*;
-use rustc::ty;
-use rustc::middle::const_val::ConstVal;
-use rustc_const_eval::ConstContext;
-use rustc::ty::subst::Substs;
use std::collections::HashSet;
use syntax::ast::{LitKind, NodeId, StrStyle};
use syntax::codemap::{BytePos, Span};
-use syntax::symbol::InternedString;
use utils::{is_expn_of, match_def_path, match_type, opt_def_id, paths, span_help_and_lint, span_lint};
+use consts::{constant, Constant};
/// **What it does:** Checks [regex](https://crates.io/crates/regex) creation
/// (with `Regex::new`,`RegexBuilder::new` or `RegexSet::new`) for correct
@@ -141,17 +137,11 @@ fn str_span(base: Span, c: regex_syntax::ast::Span, offset: usize) -> Span {
Span::new(start, end, base.ctxt())
}
-fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option {
- let parent_item = cx.tcx.hir.get_parent(e.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(e) {
- Ok(&ty::Const {
- val: ConstVal::Str(r),
- ..
- }) => Some(r),
+fn const_str<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) -> Option {
+ constant(cx, e).and_then(|(c, _)| match c {
+ Constant::Str(s) => Some(s),
_ => None,
- }
+ })
}
fn is_trivial_regex(s: ®ex_syntax::hir::Hir) -> Option<&'static str> {
diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs
index ba79bf4407b..0e9d8bdfefd 100644
--- a/clippy_lints/src/types.rs
+++ b/clippy_lints/src/types.rs
@@ -5,19 +5,18 @@ use rustc::hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisito
use rustc::lint::*;
use rustc::ty::{self, Ty, TyCtxt, TypeckTables};
use rustc::ty::layout::LayoutOf;
-use rustc::ty::subst::Substs;
use rustc_typeck::hir_ty_to_ty;
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::borrow::Cow;
use syntax::ast::{FloatTy, IntTy, UintTy};
-use syntax::attr::IntType;
use syntax::codemap::Span;
use syntax::errors::DiagnosticBuilder;
use utils::{comparisons, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path,
multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint,
- span_lint_and_sugg, span_lint_and_then};
+ span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits};
use utils::paths;
+use consts::{constant, Constant};
/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
@@ -1298,58 +1297,20 @@ fn detect_absurd_comparison<'a, 'tcx>(
}
fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option> {
- use rustc::middle::const_val::ConstVal::*;
- use rustc_const_math::*;
- use rustc_const_eval::*;
use types::ExtremeType::*;
let ty = cx.tables.expr_ty(expr);
- match ty.sty {
- ty::TyBool | ty::TyInt(_) | ty::TyUint(_) => (),
- _ => return None,
- };
+ let cv = constant(cx, expr)?.0;
- let parent_item = cx.tcx.hir.get_parent(expr.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- let cv = match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) {
- Ok(val) => val,
- Err(_) => return None,
- };
+ let which = match (&ty.sty, cv) {
+ (&ty::TyBool, Constant::Bool(false)) |
+ (&ty::TyUint(_), Constant::Int(0)) => Minimum,
+ (&ty::TyInt(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Minimum,
- let which = match (&ty.sty, cv.val) {
- (&ty::TyBool, Bool(false)) |
- (&ty::TyInt(IntTy::Isize), Integral(Isize(Is32(::std::i32::MIN)))) |
- (&ty::TyInt(IntTy::Isize), Integral(Isize(Is64(::std::i64::MIN)))) |
- (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) |
- (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) |
- (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MIN))) |
- (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MIN))) |
- (&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MIN))) |
- (&ty::TyUint(UintTy::Usize), Integral(Usize(Us32(::std::u32::MIN)))) |
- (&ty::TyUint(UintTy::Usize), Integral(Usize(Us64(::std::u64::MIN)))) |
- (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) |
- (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) |
- (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MIN))) |
- (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MIN))) |
- (&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MIN))) => Minimum,
-
- (&ty::TyBool, Bool(true)) |
- (&ty::TyInt(IntTy::Isize), Integral(Isize(Is32(::std::i32::MAX)))) |
- (&ty::TyInt(IntTy::Isize), Integral(Isize(Is64(::std::i64::MAX)))) |
- (&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) |
- (&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) |
- (&ty::TyInt(IntTy::I32), Integral(I32(::std::i32::MAX))) |
- (&ty::TyInt(IntTy::I64), Integral(I64(::std::i64::MAX))) |
- (&ty::TyInt(IntTy::I128), Integral(I128(::std::i128::MAX))) |
- (&ty::TyUint(UintTy::Usize), Integral(Usize(Us32(::std::u32::MAX)))) |
- (&ty::TyUint(UintTy::Usize), Integral(Usize(Us64(::std::u64::MAX)))) |
- (&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) |
- (&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) |
- (&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) |
- (&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) |
- (&ty::TyUint(UintTy::U128), Integral(U128(::std::u128::MAX))) => Maximum,
+ (&ty::TyBool, Constant::Bool(true)) => Maximum,
+ (&ty::TyInt(ity), Constant::Int(i)) if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) => Maximum,
+ (&ty::TyUint(uty), Constant::Int(i)) if clip(cx.tcx, u128::max_value(), uty) == i => Maximum,
_ => return None,
};
@@ -1524,24 +1485,16 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(
}
}
-#[allow(cast_possible_wrap)]
fn node_as_const_fullint<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> Option {
- use rustc::middle::const_val::ConstVal::*;
- use rustc_const_eval::ConstContext;
-
- let parent_item = cx.tcx.hir.get_parent(expr.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- match ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables).eval(expr) {
- Ok(val) => if let Integral(const_int) = val.val {
- match const_int.int_type() {
- IntType::SignedInt(_) => Some(FullInt::S(const_int.to_u128_unchecked() as i128)),
- IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())),
- }
- } else {
- None
- },
- Err(_) => None,
+ let val = constant(cx, expr)?.0;
+ if let Constant::Int(const_int) = val {
+ match cx.tables.expr_ty(expr).sty {
+ ty::TyInt(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
+ ty::TyUint(_) => Some(FullInt::U(const_int)),
+ _ => None,
+ }
+ } else {
+ None
}
}
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 2f2f0c04054..b171bdf4030 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -8,7 +8,7 @@ use rustc::hir::map::Node;
use rustc::lint::{LateContext, Level, Lint, LintContext};
use rustc::session::Session;
use rustc::traits;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, layout};
use rustc_errors;
use std::borrow::Cow;
use std::env;
@@ -276,14 +276,6 @@ pub fn path_to_def(cx: &LateContext, path: &[&str]) -> Option {
}
}
-pub fn const_to_u64(c: &ty::Const) -> u64 {
- c.val
- .to_const_int()
- .expect("eddyb says this works")
- .to_u64()
- .expect("see previous expect")
-}
-
/// Convenience function to get the `DefId` of a trait by path.
pub fn get_trait_def_id(cx: &LateContext, path: &[&str]) -> Option {
let def = match path_to_def(cx, path) {
@@ -1071,3 +1063,26 @@ pub fn get_arg_name(pat: &Pat) -> Option {
_ => None,
}
}
+
+pub fn int_bits(tcx: TyCtxt, ity: ast::IntTy) -> u64 {
+ layout::Integer::from_attr(tcx, attr::IntType::SignedInt(ity)).size().bits()
+}
+
+/// Turn a constant int byte representation into an i128
+pub fn sext(tcx: TyCtxt, u: u128, ity: ast::IntTy) -> i128 {
+ let amt = 128 - int_bits(tcx, ity);
+ ((u as i128) << amt) >> amt
+}
+
+/// clip unused bytes
+pub fn unsext(tcx: TyCtxt, u: i128, ity: ast::IntTy) -> u128 {
+ let amt = 128 - int_bits(tcx, ity);
+ ((u as u128) << amt) >> amt
+}
+
+/// clip unused bytes
+pub fn clip(tcx: TyCtxt, u: u128, ity: ast::UintTy) -> u128 {
+ let bits = layout::Integer::from_attr(tcx, attr::IntType::UnsignedInt(ity)).size().bits();
+ let amt = 128 - bits;
+ (u << amt) >> amt
+}
diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs
index e1c226466f9..4762c730683 100644
--- a/clippy_lints/src/vec.rs
+++ b/clippy_lints/src/vec.rs
@@ -1,10 +1,9 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::ty::{self, Ty};
-use rustc::ty::subst::Substs;
-use rustc_const_eval::ConstContext;
use syntax::codemap::Span;
use utils::{higher, is_copy, snippet, span_lint_and_sugg};
+use consts::constant;
/// **What it does:** Checks for usage of `&vec![..]` when using `&[..]` would
/// be possible.
@@ -67,13 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_vec_macro<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, vec_args: &higher::VecArgs<'tcx>, span: Span) {
let snippet = match *vec_args {
higher::VecArgs::Repeat(elem, len) => {
- let parent_item = cx.tcx.hir.get_parent(len.id);
- let parent_def_id = cx.tcx.hir.local_def_id(parent_item);
- let substs = Substs::identity_for_item(cx.tcx, parent_def_id);
- if ConstContext::new(cx.tcx, cx.param_env.and(substs), cx.tables)
- .eval(len)
- .is_ok()
- {
+ if constant(cx, len).is_some() {
format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len"))
} else {
return;
diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs
index efe23bcdc47..416ee155174 100644
--- a/clippy_lints/src/zero_div_zero.rs
+++ b/clippy_lints/src/zero_div_zero.rs
@@ -1,4 +1,4 @@
-use consts::{constant_simple, Constant, FloatWidth};
+use consts::{constant_simple, Constant};
use rustc::lint::*;
use rustc::hir::*;
use utils::span_help_and_lint;
@@ -37,16 +37,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
// TODO - constant_simple does not fold many operations involving floats.
// That's probably fine for this lint - it's pretty unlikely that someone would
// do something like 0.0/(2.0 - 2.0), but it would be nice to warn on that case too.
- if let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(cx, left);
- if let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(cx, right);
- if Ok(0.0) == lhs_value.parse();
- if Ok(0.0) == rhs_value.parse();
+ if let Some(lhs_value) = constant_simple(cx, left);
+ if let Some(rhs_value) = constant_simple(cx, right);
+ if Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value;
+ if Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value;
then {
// since we're about to suggest a use of std::f32::NaN or std::f64::NaN,
// match the precision of the literals that are given.
- let float_type = match (lhs_width, rhs_width) {
- (FloatWidth::F64, _)
- | (_, FloatWidth::F64) => "f64",
+ let float_type = match (lhs_value, rhs_value) {
+ (Constant::F64(_), _)
+ | (_, Constant::F64(_)) => "f64",
_ => "f32"
};
span_help_and_lint(
diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr
index 85595fb0233..5757a6ef390 100644
--- a/tests/ui/builtin-type-shadow.stderr
+++ b/tests/ui/builtin-type-shadow.stderr
@@ -19,4 +19,4 @@ error[E0308]: mismatched types
error: aborting due to 2 previous errors
-If you want more information on this error, try using "rustc --explain E0308"
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/conf_bad_arg.stderr b/tests/ui/conf_bad_arg.stderr
index 30a87e23275..094b7d49cb5 100644
--- a/tests/ui/conf_bad_arg.stderr
+++ b/tests/ui/conf_bad_arg.stderr
@@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2
error: aborting due to previous error
-If you want more information on this error, try using "rustc --explain E0658"
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/conf_bad_toml.stderr b/tests/ui/conf_bad_toml.stderr
index f01b5605a51..640b1c5e610 100644
--- a/tests/ui/conf_bad_toml.stderr
+++ b/tests/ui/conf_bad_toml.stderr
@@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2
error: aborting due to previous error
-If you want more information on this error, try using "rustc --explain E0658"
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/conf_bad_type.stderr b/tests/ui/conf_bad_type.stderr
index ea9cf0acdd8..f92b52ec032 100644
--- a/tests/ui/conf_bad_type.stderr
+++ b/tests/ui/conf_bad_type.stderr
@@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2
error: aborting due to previous error
-If you want more information on this error, try using "rustc --explain E0658"
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/conf_french_blacklisted_name.stderr b/tests/ui/conf_french_blacklisted_name.stderr
index d09ae43301c..214226ac2f9 100644
--- a/tests/ui/conf_french_blacklisted_name.stderr
+++ b/tests/ui/conf_french_blacklisted_name.stderr
@@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2
error: aborting due to previous error
-If you want more information on this error, try using "rustc --explain E0658"
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/conf_path_non_string.stderr b/tests/ui/conf_path_non_string.stderr
index 6af3b595921..10b007b0de0 100644
--- a/tests/ui/conf_path_non_string.stderr
+++ b/tests/ui/conf_path_non_string.stderr
@@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2
error: aborting due to previous error
-If you want more information on this error, try using "rustc --explain E0658"
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/conf_unknown_key.stderr b/tests/ui/conf_unknown_key.stderr
index 80a60bd8f2e..d7ac055c517 100644
--- a/tests/ui/conf_unknown_key.stderr
+++ b/tests/ui/conf_unknown_key.stderr
@@ -8,4 +8,4 @@ error[E0658]: compiler plugins are experimental and possibly buggy (see issue #2
error: aborting due to previous error
-If you want more information on this error, try using "rustc --explain E0658"
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr
index a764403d039..df404a1eec3 100644
--- a/tests/ui/float_cmp.stderr
+++ b/tests/ui/float_cmp.stderr
@@ -1,70 +1,10 @@
-error: strict comparison of f32 or f64
- --> $DIR/float_cmp.rs:43:5
- |
-43 | ONE == 1f32;
- | ^^^^^^^^^^^ help: consider comparing them within some error: `(ONE - 1f32).abs() < error`
- |
- = note: `-D float-cmp` implied by `-D warnings`
-note: std::f32::EPSILON and std::f64::EPSILON are available.
- --> $DIR/float_cmp.rs:43:5
- |
-43 | ONE == 1f32;
- | ^^^^^^^^^^^
-
-error: strict comparison of f32 or f64
- --> $DIR/float_cmp.rs:44:5
- |
-44 | ONE == 1.0 + 0.0;
- | ^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE - (1.0 + 0.0)).abs() < error`
- |
-note: std::f32::EPSILON and std::f64::EPSILON are available.
- --> $DIR/float_cmp.rs:44:5
- |
-44 | ONE == 1.0 + 0.0;
- | ^^^^^^^^^^^^^^^^
-
-error: strict comparison of f32 or f64
- --> $DIR/float_cmp.rs:45:5
- |
-45 | ONE + ONE == ZERO + ONE + ONE;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE + ONE - (ZERO + ONE + ONE)).abs() < error`
- |
-note: std::f32::EPSILON and std::f64::EPSILON are available.
- --> $DIR/float_cmp.rs:45:5
- |
-45 | ONE + ONE == ZERO + ONE + ONE;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: strict comparison of f32 or f64
- --> $DIR/float_cmp.rs:46:5
- |
-46 | ONE != 2.0;
- | ^^^^^^^^^^ help: consider comparing them within some error: `(ONE - 2.0).abs() < error`
- |
-note: std::f32::EPSILON and std::f64::EPSILON are available.
- --> $DIR/float_cmp.rs:46:5
- |
-46 | ONE != 2.0;
- | ^^^^^^^^^^
-
-error: strict comparison of f32 or f64
- --> $DIR/float_cmp.rs:48:5
- |
-48 | twice(ONE) != ONE;
- | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(twice(ONE) - ONE).abs() < error`
- |
-note: std::f32::EPSILON and std::f64::EPSILON are available.
- --> $DIR/float_cmp.rs:48:5
- |
-48 | twice(ONE) != ONE;
- | ^^^^^^^^^^^^^^^^^
-
error: strict comparison of f32 or f64
--> $DIR/float_cmp.rs:49:5
|
49 | ONE as f64 != 2.0;
| ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE as f64 - 2.0).abs() < error`
|
+ = note: `-D float-cmp` implied by `-D warnings`
note: std::f32::EPSILON and std::f64::EPSILON are available.
--> $DIR/float_cmp.rs:49:5
|
@@ -95,5 +35,5 @@ note: std::f32::EPSILON and std::f64::EPSILON are available.
57 | twice(x) != twice(ONE as f64);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 8 previous errors
+error: aborting due to 3 previous errors
diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr
index a4f7b3c6761..28223563db1 100644
--- a/tests/ui/op_ref.stderr
+++ b/tests/ui/op_ref.stderr
@@ -10,5 +10,13 @@ help: use the values directly
13 | let foo = 5 - 6;
|
-error: aborting due to previous error
+error: taken reference of right operand
+ --> $DIR/op_ref.rs:21:8
+ |
+21 | if b < &a {
+ | ^^^^--
+ | |
+ | help: use the right value directly: `a`
+
+error: aborting due to 2 previous errors
diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr
index b81e59c07f1..bc2a70beffd 100644
--- a/tests/ui/zero_div_zero.stderr
+++ b/tests/ui/zero_div_zero.stderr
@@ -13,7 +13,7 @@ error: constant division of 0.0 with 0.0 will always result in NaN
| ^^^^^^^^^
|
= note: `-D zero-divided-by-zero` implied by `-D warnings`
- = help: Consider using `std::f32::NAN` if you would like a constant representing NaN
+ = help: Consider using `std::f64::NAN` if you would like a constant representing NaN
error: equal expressions as operands to `/`
--> $DIR/zero_div_zero.rs:8:19