diff --git a/clippy_lints/src/array_indexing.rs b/clippy_lints/src/array_indexing.rs index 2ab70da8c..1cd57e632 100644 --- a/clippy_lints/src/array_indexing.rs +++ b/clippy_lints/src/array_indexing.rs @@ -1,9 +1,8 @@ use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::ConstContext; -use rustc_const_math::ConstInt; +use rustc_const_math::{ConstUsize,ConstIsize,ConstInt}; use rustc::hir; use syntax::ast::RangeLimits; use utils::{self, higher}; @@ -61,11 +60,11 @@ 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::Infer(size as u128); + let size = ConstInt::Usize(ConstUsize::new(size as u64, cx.sess().target.uint_type).expect("array size is invalid")); let constcx = ConstContext::with_tables(cx.tcx, cx.tables); // Index is a constant uint - let const_index = constcx.eval(index, ExprTypeChecked); + let const_index = constcx.eval(index); if let Ok(ConstVal::Integral(const_index)) = const_index { if size <= const_index { utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds"); @@ -77,10 +76,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing { // Index is a constant range if let Some(range) = higher::range(index) { let start = range.start - .map(|start| constcx.eval(start, ExprTypeChecked)) + .map(|start| constcx.eval(start)) .map(|v| v.ok()); let end = range.end - .map(|end| constcx.eval(end, ExprTypeChecked)) + .map(|end| constcx.eval(end)) .map(|v| v.ok()); if let Some((start, end)) = to_const_range(&start, &end, range.limits, size) { @@ -117,13 +116,30 @@ fn to_const_range( let start = match *start { Some(Some(ConstVal::Integral(x))) => x, Some(_) => return None, - None => ConstInt::Infer(0), + None => ConstInt::U8(0), }; let end = match *end { Some(Some(ConstVal::Integral(x))) => { if limits == RangeLimits::Closed { - (x + ConstInt::Infer(1)).expect("such a big array is not realistic") + 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") } else { x } diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 06e8e9182..789de240d 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -237,6 +237,7 @@ 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 { @@ -248,7 +249,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { ExprPath(ref qpath) => { let def = cx.tables.qpath_def(qpath, lit.id); if let Def::Const(def_id) = def { - lookup_const_by_id(cx.tcx, def_id, None).and_then(|(l, _tab, _ty)| fetch_int_literal(cx, l)) + lookup_const_by_id(cx.tcx, def_id, Substs::empty()).and_then(|(l, _ty)| fetch_int_literal(cx, l)) } else { None } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 46371b938..b38b906b4 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -3,14 +3,15 @@ use rustc::lint::LateContext; use rustc::hir::def::Def; use rustc_const_eval::lookup_const_by_id; -use rustc_const_math::{ConstInt, ConstUsize, ConstIsize}; +use rustc_const_math::ConstInt; use rustc::hir::*; +use rustc::ty::{TyCtxt, self}; 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, LitIntType, LitKind, StrStyle, UintTy, IntTy, NodeId}; +use syntax::ast::{FloatTy, LitKind, StrStyle, NodeId}; use syntax::ptr::P; #[derive(Debug, Copy, Clone)] @@ -174,29 +175,36 @@ impl PartialOrd for Constant { /// parse a `LitKind` to a `Constant` #[allow(cast_possible_wrap)] -pub fn lit_to_constant(lit: &LitKind) -> Constant { +pub fn lit_to_constant<'a, 'tcx>(lit: &LitKind, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut ty: 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::ByteStr(ref s) => Constant::Binary(s.clone()), LitKind::Char(c) => Constant::Char(c), - LitKind::Int(value, LitIntType::Unsuffixed) => Constant::Int(ConstInt::Infer(value)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U8)) => Constant::Int(ConstInt::U8(value as u8)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U16)) => Constant::Int(ConstInt::U16(value as u16)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U32)) => Constant::Int(ConstInt::U32(value as u32)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U64)) => Constant::Int(ConstInt::U64(value as u64)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::U128)) => Constant::Int(ConstInt::U128(value as u128)), - LitKind::Int(value, LitIntType::Unsigned(UintTy::Us)) => { - Constant::Int(ConstInt::Usize(ConstUsize::Us32(value as u32))) - }, - LitKind::Int(value, LitIntType::Signed(IntTy::I8)) => Constant::Int(ConstInt::I8(value as i8)), - LitKind::Int(value, LitIntType::Signed(IntTy::I16)) => Constant::Int(ConstInt::I16(value as i16)), - LitKind::Int(value, LitIntType::Signed(IntTy::I32)) => Constant::Int(ConstInt::I32(value as i32)), - LitKind::Int(value, LitIntType::Signed(IntTy::I64)) => Constant::Int(ConstInt::I64(value as i64)), - LitKind::Int(value, LitIntType::Signed(IntTy::I128)) => Constant::Int(ConstInt::I128(value as i128)), - LitKind::Int(value, LitIntType::Signed(IntTy::Is)) => { - Constant::Int(ConstInt::Isize(ConstIsize::Is32(value as i32))) - }, + 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.int_type)) + } + (&ty::TyUint(uty), _) | + (_, Unsigned(uty)) => { + Constant::Int(ConstInt::new_unsigned_truncating(n as u128, + uty, tcx.sess.target.uint_type)) + } + _ => 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), @@ -231,22 +239,20 @@ fn neg_float_str(s: &str) -> String { pub fn constant(lcx: &LateContext, e: &Expr) -> Option<(Constant, bool)> { let mut cx = ConstEvalLateContext { - lcx: Some(lcx), + tcx: lcx.tcx, + tables: lcx.tables, needed_resolution: false, }; cx.expr(e).map(|cst| (cst, cx.needed_resolution)) } -pub fn constant_simple(e: &Expr) -> Option { - let mut cx = ConstEvalLateContext { - lcx: None, - needed_resolution: false, - }; - cx.expr(e) +pub fn constant_simple(lcx: &LateContext, e: &Expr) -> Option { + constant(lcx, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) } -struct ConstEvalLateContext<'c, 'cc: 'c> { - lcx: Option<&'c LateContext<'c, 'cc>>, +struct ConstEvalLateContext<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::TypeckTables<'tcx>, needed_resolution: bool, } @@ -257,17 +263,14 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprPath(ref qpath) => self.fetch_path(qpath, e.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)), + ExprLit(ref lit) => Some(lit_to_constant(&lit.node, self.tcx, 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, number_id) => { - if let Some(lcx) = self.lcx { - self.binop_apply(value, - &lcx.tcx.hir.body(number_id).value, - |v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize))) - } else { - None - } + let val = &self.tcx.hir.body(number_id).value; + self.binop_apply(value, + val, + |v, n| Some(Constant::Repeat(Box::new(v), n.as_u64() as usize))) }, ExprUnary(op, ref operand) => { self.expr(operand).and_then(|o| match op { @@ -292,24 +295,27 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { /// lookup a possibly constant expression from a ExprPath fn fetch_path(&mut self, qpath: &QPath, id: NodeId) -> Option { - if let Some(lcx) = self.lcx { - let def = lcx.tables.qpath_def(qpath, id); - match def { - Def::Const(def_id) | - Def::AssociatedConst(def_id) => { - let substs = Some(lcx.tables - .node_id_item_substs(id) - .unwrap_or_else(|| lcx.tcx.intern_substs(&[]))); - if let Some((const_expr, _tab, _ty)) = lookup_const_by_id(lcx.tcx, def_id, substs) { - let ret = self.expr(const_expr); - if ret.is_some() { - self.needed_resolution = true; - } - return ret; + let def = self.tables.qpath_def(qpath, id); + match def { + Def::Const(def_id) | + Def::AssociatedConst(def_id) => { + let substs = self.tables + .node_id_item_substs(id) + .unwrap_or_else(|| self.tcx.intern_substs(&[])); + if let Some((const_expr, tables)) = lookup_const_by_id(self.tcx, def_id, substs) { + let mut cx = ConstEvalLateContext { + tcx: self.tcx, + tables, + needed_resolution: false, + }; + let ret = cx.expr(const_expr); + if ret.is_some() { + self.needed_resolution = true; } - }, - _ => {}, - } + return ret; + } + }, + _ => {}, } None } diff --git a/clippy_lints/src/cyclomatic_complexity.rs b/clippy_lints/src/cyclomatic_complexity.rs index 9d6056de3..33c27b53b 100644 --- a/clippy_lints/src/cyclomatic_complexity.rs +++ b/clippy_lints/src/cyclomatic_complexity.rs @@ -136,7 +136,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> { let ty = self.cx.tables.node_id_to_type(callee.id); match ty.sty { ty::TyFnDef(_, _, ty) | - ty::TyFnPtr(ty) if ty.sig.skip_binder().output().sty == ty::TyNever => { + ty::TyFnPtr(ty) if ty.skip_binder().output().sty == ty::TyNever => { self.divergence += 1; }, _ => (), diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index e924ae79d..4032234ac 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -45,7 +45,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { if let Some(body_id) = variant.disr_expr { use rustc_const_eval::*; let constcx = ConstContext::new(cx.tcx, body_id); - let bad = match constcx.eval(&cx.tcx.hir.body(body_id).value, EvalHint::ExprTypeChecked) { + let bad = match constcx.eval(&cx.tcx.hir.body(body_id).value) { Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i, Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != i, _ => false, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 40678e324..8230fe731 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -66,7 +66,7 @@ fn check_closure(cx: &LateContext, expr: &Expr) { // Is it an unsafe function? They don't implement the closure traits ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty) => { - if fn_ty.unsafety == Unsafety::Unsafe || fn_ty.sig.skip_binder().output().sty == ty::TyNever { + if fn_ty.skip_binder().unsafety == Unsafety::Unsafe || fn_ty.skip_binder().output().sty == ty::TyNever { return; } }, diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 798bd6cf1..f07ec7de5 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -129,7 +129,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> { match self.cx.tables.expr_ty(func).sty { ty::TyFnDef(_, _, fn_ty) | ty::TyFnPtr(fn_ty) => { - if let ty::TyNever = self.cx.tcx.erase_late_bound_regions(&fn_ty.sig).output().sty { + if let ty::TyNever = self.cx.tcx.erase_late_bound_regions(&fn_ty).output().sty { self.report_diverging_sub_expr(e); } }, diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index a10a9523a..82db13b10 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -3,7 +3,7 @@ use rustc::lint::*; use rustc::hir::*; use syntax::codemap::Span; use utils::{span_lint, snippet, in_macro}; -use rustc_const_math::ConstInt; +use syntax::attr::IntType::{SignedInt, UnsignedInt}; /// **What it does:** Checks for identity operations, e.g. `x + 0`. /// @@ -60,11 +60,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp { fn check(cx: &LateContext, e: &Expr, m: i8, span: Span, arg: Span) { - if let Some(v @ Constant::Int(_)) = constant_simple(e) { + if let Some(Constant::Int(v)) = constant_simple(cx, e) { if match m { - 0 => v == Constant::Int(ConstInt::Infer(0)), - -1 => v == Constant::Int(ConstInt::InferSigned(-1)), - 1 => v == Constant::Int(ConstInt::Infer(1)), + 0 => v.to_u128_unchecked() == 0, + -1 => match v.int_type() { + SignedInt(_) => #[allow(cast_possible_wrap)] (v.to_u128_unchecked() as i128 == -1), + UnsignedInt(_) => false + }, + 1 => v.to_u128_unchecked() == 1, _ => unreachable!(), } { span_lint(cx, diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index f656d513b..bfd17d995 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -2,10 +2,8 @@ use rustc::lint::*; use rustc::hir::*; -use utils::{span_lint_and_then, snippet_opt}; -use rustc::ty::layout::TargetDataLayout; +use utils::{span_lint_and_then, snippet_opt, type_size}; use rustc::ty::TypeFoldable; -use rustc::traits::Reveal; /// **What it does:** Checks for large size differences between variants on `enum`s. /// @@ -55,28 +53,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { let mut largest_variant: Option<(_, _)> = None; for (i, variant) in adt.variants.iter().enumerate() { - let data_layout = TargetDataLayout::parse(cx.sess()); - cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| { - let size: u64 = variant.fields - .iter() - .map(|f| { - let ty = cx.tcx.item_type(f.did); - if ty.needs_subst() { - 0 // we can't reason about generics, so we treat them as zero sized - } else { - ty.layout(&infcx) - .expect("layout should be computable for concrete type") - .size(&data_layout) - .bytes() - } - }) - .sum(); + let size: u64 = variant.fields + .iter() + .map(|f| { + let ty = cx.tcx.item_type(f.did); + if ty.needs_subst() { + 0 // we can't reason about generics, so we treat them as zero sized + } else { + type_size(cx, ty).expect("size should be computable for concrete type") + } + }) + .sum(); - let grouped = (size, (i, variant)); + let grouped = (size, (i, variant)); - update_if(&mut smallest_variant, grouped, |a, b| b.0 <= a.0); - update_if(&mut largest_variant, grouped, |a, b| b.0 >= a.0); - }); + update_if(&mut smallest_variant, grouped, |a, b| b.0 <= a.0); + update_if(&mut largest_variant, grouped, |a, b| b.0 >= a.0); } if let (Some(smallest), Some(largest)) = (smallest_variant, largest_variant) { diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index cc4df4581..03522cc02 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -186,7 +186,8 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { fn is_is_empty(cx: &LateContext, item: &ty::AssociatedItem) -> bool { if let ty::AssociatedKind::Method = item.kind { if &*item.name.as_str() == "is_empty" { - let ty = cx.tcx.item_type(item.def_id).fn_sig().skip_binder(); + let sig = cx.tcx.item_type(item.def_id).fn_sig(); + let ty = sig.skip_binder(); ty.inputs().len() == 1 } else { false @@ -198,7 +199,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool { /// Check the inherent impl's items for an `is_empty(self)` method. fn has_is_empty_impl(cx: &LateContext, id: DefId) -> bool { - cx.tcx.inherent_impls.borrow().get(&id).map_or(false, |impls| { + cx.tcx.maps.inherent_impls.borrow().get(&id).map_or(false, |impls| { impls.iter().any(|imp| cx.tcx.associated_items(*imp).any(|item| is_is_empty(cx, &item))) }) } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 2051c8836..1571372ce 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -257,7 +257,7 @@ impl<'v, 't> RefVisitor<'v, 't> { } }, Def::Trait(def_id) => { - let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id]; + let trait_def = self.cx.tcx.maps.trait_def.borrow()[&def_id]; for _ in &self.cx.tcx.item_generics(trait_def.def_id).regions { self.record(&None); } diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index dd9ec1f6e..8c1f47a21 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -8,7 +8,6 @@ use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::middle::region::CodeExtent; use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::ConstContext; use std::collections::HashMap; use syntax::ast; @@ -596,8 +595,8 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::range(arg) { // ...and both sides are compile-time constant integers... let constcx = ConstContext::with_tables(cx.tcx, cx.tables); - if let Ok(start_idx) = constcx.eval(start, ExprTypeChecked) { - if let Ok(end_idx) = constcx.eval(end, ExprTypeChecked) { + if let Ok(start_idx) = constcx.eval(start) { + if let Ok(end_idx) = constcx.eval(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 diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 5a8ff4422..4df2052cd 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -2,7 +2,6 @@ use rustc::hir::*; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::ConstContext; use rustc_const_math::ConstInt; use std::cmp::Ordering; @@ -415,7 +414,7 @@ fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: Match } /// Get all arms that are unbounded `PatRange`s. -fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec> { +fn all_ranges<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, arms: &[Arm]) -> Vec>> { let constcx = ConstContext::with_tables(cx.tcx, cx.tables); arms.iter() .flat_map(|arm| { @@ -427,8 +426,8 @@ fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec> { .filter_map(|pat| { if_let_chain! {[ let PatKind::Range(ref lhs, ref rhs, ref range_end) = pat.node, - let Ok(lhs) = constcx.eval(lhs, ExprTypeChecked), - let Ok(rhs) = constcx.eval(rhs, ExprTypeChecked) + let Ok(lhs) = constcx.eval(lhs), + let Ok(rhs) = constcx.eval(rhs) ], { let rhs = match *range_end { RangeEnd::Included => Bound::Included(rhs), @@ -439,7 +438,7 @@ fn all_ranges(cx: &LateContext, arms: &[Arm]) -> Vec> { if_let_chain! {[ let PatKind::Lit(ref value) = pat.node, - let Ok(value) = constcx.eval(value, ExprTypeChecked) + let Ok(value) = constcx.eval(value) ], { return Some(SpannedRange { span: pat.span, node: (value.clone(), Bound::Included(value)) }); }} diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index fbb5f32b3..b43a2473f 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget { let forgot_ty = cx.tables.expr_ty(&args[0]); if match forgot_ty.ty_adt_def() { - Some(def) => def.has_dtor(), + Some(def) => def.has_dtor(cx.tcx), _ => false, } { span_lint(cx, MEM_FORGET, e.span, "usage of mem::forget on Drop type"); diff --git a/clippy_lints/src/methods.rs b/clippy_lints/src/methods.rs index 9acf4c7e9..b74166309 100644 --- a/clippy_lints/src/methods.rs +++ b/clippy_lints/src/methods.rs @@ -3,7 +3,6 @@ use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::ty; use rustc::hir::def::Def; -use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::ConstContext; use std::borrow::Cow; use std::fmt; @@ -1240,7 +1239,7 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other: /// lint for length-1 `str`s for methods in `PATTERN_METHODS` fn lint_single_char_pattern(cx: &LateContext, expr: &hir::Expr, arg: &hir::Expr) { - if let Ok(ConstVal::Str(r)) = ConstContext::with_tables(cx.tcx, cx.tables).eval(arg, ExprTypeChecked) { + if let Ok(ConstVal::Str(r)) = ConstContext::with_tables(cx.tcx, cx.tables).eval(arg) { if r.len() == 1 { let hint = snippet(cx, expr.span, "..").replace(&format!("\"{}\"", r), &format!("'{}'", r)); span_lint_and_then(cx, diff --git a/clippy_lints/src/minmax.rs b/clippy_lints/src/minmax.rs index 7cf260c7d..2c6553e90 100644 --- a/clippy_lints/src/minmax.rs +++ b/clippy_lints/src/minmax.rs @@ -65,9 +65,9 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &' let def_id = cx.tables.qpath_def(qpath, path.id).def_id(); if match_def_path(cx.tcx, def_id, &paths::CMP_MIN) { - fetch_const(args, MinMax::Min) + fetch_const(cx, args, MinMax::Min) } else if match_def_path(cx.tcx, def_id, &paths::CMP_MAX) { - fetch_const(args, MinMax::Max) + fetch_const(cx, args, MinMax::Max) } else { None } @@ -79,18 +79,18 @@ fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &' } } -fn fetch_const(args: &[Expr], m: MinMax) -> Option<(MinMax, Constant, &Expr)> { +fn fetch_const<'a>(cx: &LateContext, args: &'a [Expr], m: MinMax) -> Option<(MinMax, Constant, &'a Expr)> { if args.len() != 2 { return None; } - if let Some(c) = constant_simple(&args[0]) { - if constant_simple(&args[1]).is_none() { + if let Some(c) = constant_simple(cx, &args[0]) { + if constant_simple(cx, &args[1]).is_none() { // otherwise ignore Some((m, c, &args[1])) } else { None } - } else if let Some(c) = constant_simple(&args[1]) { + } else if let Some(c) = constant_simple(cx, &args[1]) { Some((m, c, &args[0])) } else { None diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index d2f794def..3fb910107 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -4,7 +4,6 @@ use rustc::hir::intravisit::FnKind; use rustc::lint::*; use rustc::middle::const_val::ConstVal; use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::ConstContext; use rustc_const_math::ConstFloat; use syntax::codemap::{Span, Spanned, ExpnFormat}; @@ -360,27 +359,31 @@ fn check_nan(cx: &LateContext, path: &Path, span: Span) { } fn is_allowed(cx: &LateContext, expr: &Expr) -> bool { - let res = ConstContext::with_tables(cx.tcx, cx.tables).eval(expr, ExprTypeChecked); + let res = ConstContext::with_tables(cx.tcx, cx.tables).eval(expr); if let Ok(ConstVal::Float(val)) = res { use std::cmp::Ordering; + match val { + val @ ConstFloat::F32(_) => { + let zero = ConstFloat::F32(0.0); - let zero = ConstFloat::FInfer { - f32: 0.0, - f64: 0.0, - }; + let infinity = ConstFloat::F32(::std::f32::INFINITY); - let infinity = ConstFloat::FInfer { - f32: ::std::f32::INFINITY, - f64: ::std::f64::INFINITY, - }; + let neg_infinity = ConstFloat::F32(::std::f32::NEG_INFINITY); - let neg_infinity = ConstFloat::FInfer { - f32: ::std::f32::NEG_INFINITY, - f64: ::std::f64::NEG_INFINITY, - }; + val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || + val.try_cmp(neg_infinity) == Ok(Ordering::Equal) + }, + val @ ConstFloat::F64(_) => { + let zero = ConstFloat::F64(0.0); - val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || - val.try_cmp(neg_infinity) == Ok(Ordering::Equal) + let infinity = ConstFloat::F64(::std::f64::INFINITY); + + let neg_infinity = ConstFloat::F64(::std::f64::NEG_INFINITY); + + val.try_cmp(zero) == Ok(Ordering::Equal) || val.try_cmp(infinity) == Ok(Ordering::Equal) || + val.try_cmp(neg_infinity) == Ok(Ordering::Equal) + } + } } else { false } diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index cb1f33133..07c941ece 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -62,7 +62,7 @@ fn check_arguments(cx: &LateContext, arguments: &[Expr], type_definition: &TyS, match type_definition.sty { TypeVariants::TyFnDef(_, _, fn_type) | TypeVariants::TyFnPtr(fn_type) => { - let parameters = fn_type.sig.skip_binder().inputs(); + let parameters = fn_type.skip_binder().inputs(); for (argument, parameter) in arguments.iter().zip(parameters.iter()) { match parameter.sty { TypeVariants::TyRef(_, TypeAndMut { mutbl: MutImmutable, .. }) | diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 72399a9e6..d7e7a0bdb 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let fn_def_id = cx.tcx.hir.local_def_id(node_id); let param_env = ty::ParameterEnvironment::for_item(cx.tcx, node_id); let fn_sig = cx.tcx.item_type(fn_def_id).fn_sig(); - let fn_sig = cx.tcx.liberate_late_bound_regions(param_env.free_id_outlive, fn_sig); + let fn_sig = cx.tcx.liberate_late_bound_regions(param_env.free_id_outlive, &fn_sig); for ((input, ty), arg) in decl.inputs.iter().zip(fn_sig.inputs()).zip(&body.arguments) { diff --git a/clippy_lints/src/neg_multiply.rs b/clippy_lints/src/neg_multiply.rs index b41423b0a..d7437f34c 100644 --- a/clippy_lints/src/neg_multiply.rs +++ b/clippy_lints/src/neg_multiply.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply { fn check_mul(cx: &LateContext, span: Span, lit: &Expr, exp: &Expr) { if_let_chain!([ let ExprLit(ref l) = lit.node, - let Constant::Int(ref ci) = consts::lit_to_constant(&l.node), + let Constant::Int(ref ci) = consts::lit_to_constant(&l.node, cx.tcx, cx.tables.expr_ty(lit)), let Some(val) = ci.to_u64(), val == 1, cx.tables.expr_ty(exp).is_integral() diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index e9176372e..279996bfa 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -113,7 +113,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass { fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) { let fn_def_id = cx.tcx.hir.local_def_id(fn_id); - let fn_ty = cx.tcx.item_type(fn_def_id).fn_sig().skip_binder(); + let sig = cx.tcx.item_type(fn_def_id).fn_sig(); + let fn_ty = sig.skip_binder(); for (arg, ty) in decl.inputs.iter().zip(fn_ty.inputs()) { if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty { diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 991d601cf..6f22c3cfc 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -2,7 +2,6 @@ use regex_syntax; use rustc::hir::*; use rustc::lint::*; use rustc::middle::const_val::ConstVal; -use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::ConstContext; use std::collections::HashSet; use std::error::Error; @@ -151,7 +150,7 @@ fn str_span(base: Span, s: &str, c: usize) -> Span { } fn const_str(cx: &LateContext, e: &Expr) -> Option { - match ConstContext::with_tables(cx.tcx, cx.tables).eval(e, ExprTypeChecked) { + match ConstContext::with_tables(cx.tcx, cx.tables).eval(e) { Ok(ConstVal::Str(r)) => Some(r), _ => None, } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 17d4ebd87..c93ba0021 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -5,9 +5,10 @@ use rustc::lint::*; use rustc::ty; use std::cmp::Ordering; use syntax::ast::{IntTy, UintTy, FloatTy}; +use syntax::attr::IntType; use syntax::codemap::Span; use utils::{comparisons, higher, in_external_macro, in_macro, match_def_path, snippet, span_help_and_lint, span_lint, - opt_def_id, last_path_segment}; + opt_def_id, last_path_segment, type_size}; use utils::paths; /// Handles all the linting of funky types @@ -907,7 +908,6 @@ fn detect_absurd_comparison<'a>( fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option> { use rustc::middle::const_val::ConstVal::*; use rustc_const_math::*; - use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::*; use types::ExtremeType::*; @@ -918,7 +918,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option return None, }; - let cv = match ConstContext::with_tables(cx.tcx, cx.tables).eval(expr, ExprTypeChecked) { + let cv = match ConstContext::with_tables(cx.tcx, cx.tables).eval(expr) { Ok(val) => val, Err(_) => return None, }; @@ -1077,7 +1077,13 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( use std::*; if let ExprCast(ref cast_exp, _) = expr.node { - match cx.tables.expr_ty(cast_exp).sty { + let pre_cast_ty = cx.tables.expr_ty(cast_exp); + let cast_ty = cx.tables.expr_ty(expr); + // if it's a cast from i32 to u32 wrapping will invalidate all these checks + if type_size(cx, pre_cast_ty) == type_size(cx, cast_ty) { + return None; + } + match pre_cast_ty.sty { TyInt(int_ty) => { Some(match int_ty { IntTy::I8 => (FullInt::S(i8::min_value() as i128), FullInt::S(i8::max_value() as i128)), @@ -1107,18 +1113,15 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext, expr: &'a Expr) -> Option<( fn node_as_const_fullint(cx: &LateContext, expr: &Expr) -> Option { use rustc::middle::const_val::ConstVal::*; - use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::ConstContext; - use rustc_const_math::ConstInt; - match ConstContext::with_tables(cx.tcx, cx.tables).eval(expr, ExprTypeChecked) { + match ConstContext::with_tables(cx.tcx, cx.tables).eval(expr) { Ok(val) => { if let Integral(const_int) = val { - Some(match const_int.erase_type() { - ConstInt::InferSigned(x) => FullInt::S(x as i128), - ConstInt::Infer(x) => FullInt::U(x as u128), - _ => unreachable!(), - }) + match const_int.int_type() { + IntType::SignedInt(_) => #[allow(cast_possible_wrap)] Some(FullInt::S(const_int.to_u128_unchecked() as i128)), + IntType::UnsignedInt(_) => Some(FullInt::U(const_int.to_u128_unchecked())), + } } else { None } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2dae1cf17..18864d42d 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -9,6 +9,7 @@ use rustc::traits::Reveal; use rustc::traits; use rustc::ty::subst::Subst; use rustc::ty; +use rustc::ty::layout::TargetDataLayout; use rustc_errors; use std::borrow::Cow; use std::env; @@ -781,7 +782,7 @@ pub fn return_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, fn_item: NodeId) -> ty::T let parameter_env = ty::ParameterEnvironment::for_item(cx.tcx, fn_item); let fn_def_id = cx.tcx.hir.local_def_id(fn_item); let fn_sig = cx.tcx.item_type(fn_def_id).fn_sig(); - let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, fn_sig); + let fn_sig = cx.tcx.liberate_late_bound_regions(parameter_env.free_id_outlive, &fn_sig); fn_sig.output() } @@ -806,7 +807,7 @@ pub fn same_tys<'a, 'tcx>( pub fn type_is_unsafe_function(ty: ty::Ty) -> bool { match ty.sty { ty::TyFnDef(_, _, f) | - ty::TyFnPtr(f) => f.unsafety == Unsafety::Unsafe, + ty::TyFnPtr(f) => f.unsafety() == Unsafety::Unsafe, _ => false, } } @@ -972,3 +973,9 @@ pub fn is_try(expr: &Expr) -> Option<&Expr> { None } + +pub fn type_size<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: ty::Ty<'tcx>) -> Option { + cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| + ty.layout(&infcx).ok().map(|lay| lay.size(&TargetDataLayout::parse(cx.sess())).bytes()) + ) +} diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index a8d2701cc..3b9e38cb6 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,7 +1,6 @@ use rustc::hir::*; use rustc::lint::*; use rustc::ty; -use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_eval::ConstContext; use syntax::codemap::Span; use utils::{higher, is_copy, snippet, span_lint_and_then}; @@ -60,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) { let snippet = match *vec_args { higher::VecArgs::Repeat(elem, len) => { - if ConstContext::with_tables(cx.tcx, cx.tables).eval(len, ExprTypeChecked).is_ok() { + if ConstContext::with_tables(cx.tcx, cx.tables).eval(len).is_ok() { format!("&[{}; {}]", snippet(cx, elem.span, "elem"), snippet(cx, len.span, "len")).into() } else { return; diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index daf0721af..eb298f9bc 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -36,8 +36,8 @@ 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. - let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(left), - let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(right), + let Some(Constant::Float(ref lhs_value, lhs_width)) = constant_simple(cx, left), + let Some(Constant::Float(ref rhs_value, rhs_width)) = constant_simple(cx, right), let Ok(0.0) = lhs_value.parse(), let Ok(0.0) = rhs_value.parse() ], { diff --git a/tests/consts.rs b/tests/consts.rs deleted file mode 100644 index d4a4ef8a3..000000000 --- a/tests/consts.rs +++ /dev/null @@ -1,99 +0,0 @@ -#![feature(rustc_private)] - -extern crate clippy_lints; -extern crate rustc; -extern crate rustc_const_eval; -extern crate rustc_const_math; -extern crate syntax; - -use clippy_lints::consts::{constant_simple, Constant, FloatWidth}; -use rustc_const_math::ConstInt; -use rustc::hir::*; -use syntax::ast::{LitIntType, LitKind, NodeId, StrStyle}; -use syntax::codemap::{Spanned, COMMAND_LINE_SP}; -use syntax::symbol::Symbol; -use syntax::ptr::P; -use syntax::util::ThinVec; - -fn spanned(t: T) -> Spanned { - Spanned { - node: t, - span: COMMAND_LINE_SP, - } -} - -fn expr(n: Expr_) -> Expr { - Expr { - id: NodeId::new(1), - node: n, - span: COMMAND_LINE_SP, - attrs: ThinVec::new(), - } -} - -fn lit(l: LitKind) -> Expr { - expr(ExprLit(P(spanned(l)))) -} - -fn binop(op: BinOp_, l: Expr, r: Expr) -> Expr { - expr(ExprBinary(spanned(op), P(l), P(r))) -} - -fn check(expect: Constant, expr: &Expr) { - assert_eq!(Some(expect), constant_simple(expr)) -} - -const TRUE: Constant = Constant::Bool(true); -const FALSE: Constant = Constant::Bool(false); -const ZERO: Constant = Constant::Int(ConstInt::Infer(0)); -const ONE: Constant = Constant::Int(ConstInt::Infer(1)); -const TWO: Constant = Constant::Int(ConstInt::Infer(2)); - -#[test] -fn test_lit() { - check(TRUE, &lit(LitKind::Bool(true))); - check(FALSE, &lit(LitKind::Bool(false))); - check(ZERO, &lit(LitKind::Int(0, LitIntType::Unsuffixed))); - check(Constant::Str("cool!".into(), StrStyle::Cooked), - &lit(LitKind::Str(Symbol::intern("cool!"), StrStyle::Cooked))); -} - -#[test] -fn test_ops() { - check(TRUE, &binop(BiOr, lit(LitKind::Bool(false)), lit(LitKind::Bool(true)))); - check(FALSE, &binop(BiAnd, lit(LitKind::Bool(false)), lit(LitKind::Bool(true)))); - - let litzero = lit(LitKind::Int(0, LitIntType::Unsuffixed)); - let litone = lit(LitKind::Int(1, LitIntType::Unsuffixed)); - check(TRUE, &binop(BiEq, litzero.clone(), litzero.clone())); - check(TRUE, &binop(BiGe, litzero.clone(), litzero.clone())); - check(TRUE, &binop(BiLe, litzero.clone(), litzero.clone())); - check(FALSE, &binop(BiNe, litzero.clone(), litzero.clone())); - check(FALSE, &binop(BiGt, litzero.clone(), litzero.clone())); - check(FALSE, &binop(BiLt, litzero.clone(), litzero.clone())); - - check(ZERO, &binop(BiAdd, litzero.clone(), litzero.clone())); - check(TWO, &binop(BiAdd, litone.clone(), litone.clone())); - check(ONE, &binop(BiSub, litone.clone(), litzero.clone())); - check(ONE, &binop(BiMul, litone.clone(), litone.clone())); - check(ONE, &binop(BiDiv, litone.clone(), litone.clone())); - - let half_any = Constant::Float("0.5".into(), FloatWidth::Any); - let half32 = Constant::Float("0.5".into(), FloatWidth::F32); - let half64 = Constant::Float("0.5".into(), FloatWidth::F64); - let pos_zero = Constant::Float("0.0".into(), FloatWidth::F64); - let neg_zero = Constant::Float("-0.0".into(), FloatWidth::F64); - - assert_eq!(pos_zero, pos_zero); - assert_eq!(neg_zero, neg_zero); - assert_eq!(None, pos_zero.partial_cmp(&neg_zero)); - - assert_eq!(half_any, half32); - assert_eq!(half_any, half64); - // for transitivity - assert_eq!(half32, half64); - - assert_eq!(Constant::Int(ConstInt::Infer(0)), Constant::Int(ConstInt::U8(0))); - assert_eq!(Constant::Int(ConstInt::Infer(0)), Constant::Int(ConstInt::I8(0))); - assert_eq!(Constant::Int(ConstInt::InferSigned(-1)), Constant::Int(ConstInt::I8(-1))); -} diff --git a/tests/ui/invalid_upcast_comparisons.rs b/tests/ui/invalid_upcast_comparisons.rs index 952cf1e43..c59f04d4f 100644 --- a/tests/ui/invalid_upcast_comparisons.rs +++ b/tests/ui/invalid_upcast_comparisons.rs @@ -3,33 +3,79 @@ #![deny(invalid_upcast_comparisons)] #![allow(unused, eq_op, no_effect, unnecessary_operation)] + +fn mk_value() -> T { unimplemented!() } + fn main() { - let zero: u32 = 0; - let u8_max: u8 = 255; + let u32: u32 = mk_value(); + let u8: u8 = mk_value(); + let i32: i32 = mk_value(); + let i8: i8 = mk_value(); - (u8_max as u32) > 300; - (u8_max as u32) > 20; + // always false, since no u8 can be > 300 + (u8 as u32) > 300; + (u8 as i32) > 300; + (u8 as u32) == 300; + (u8 as i32) == 300; + 300 < (u8 as u32); + 300 < (u8 as i32); + 300 == (u8 as u32); + 300 == (u8 as i32); + // inverted of the above + (u8 as u32) <= 300; + (u8 as i32) <= 300; + (u8 as u32) != 300; + (u8 as i32) != 300; + 300 >= (u8 as u32); + 300 >= (u8 as i32); + 300 != (u8 as u32); + 300 != (u8 as i32); - (zero as i32) < -5; - (zero as i32) < 10; + // always false, since u8 -> i32 doesn't wrap + (u8 as i32) < 0; + -5 != (u8 as i32); + // inverted of the above + (u8 as i32) >= 0; + -5 == (u8 as i32); - -5 < (zero as i32); - 0 <= (zero as i32); - 0 < (zero as i32); + // always false, since no u8 can be 1337 + 1337 == (u8 as i32); + 1337 == (u8 as u32); + // inverted of the above + 1337 != (u8 as i32); + 1337 != (u8 as u32); - -5 > (zero as i32); - -5 >= (u8_max as i32); - 1337 == (u8_max as i32); - - -5 == (zero as i32); - -5 != (u8_max as i32); // Those are Ok: - 42 == (u8_max as i32); - 42 != (u8_max as i32); - 42 > (u8_max as i32); - (u8_max as i32) == 42; - (u8_max as i32) != 42; - (u8_max as i32) > 42; - (u8_max as i32) < 42; + (u8 as u32) > 20; + 42 == (u8 as i32); + 42 != (u8 as i32); + 42 > (u8 as i32); + (u8 as i32) == 42; + (u8 as i32) != 42; + (u8 as i32) > 42; + (u8 as i32) < 42; + + (u8 as i8) == -1; + (u8 as i8) != -1; + (u8 as i32) > -1; + (u8 as i32) < -1; + (u32 as i32) < -5; + (u32 as i32) < 10; + + (i8 as u8) == 1; + (i8 as u8) != 1; + (i8 as u8) < 1; + (i8 as u8) > 1; + (i32 as u32) < 5; + (i32 as u32) < 10; + + -5 < (u32 as i32); + 0 <= (u32 as i32); + 0 < (u32 as i32); + + -5 > (u32 as i32); + -5 >= (u8 as i32); + + -5 == (u32 as i32); } diff --git a/tests/ui/invalid_upcast_comparisons.stderr b/tests/ui/invalid_upcast_comparisons.stderr index e7eda752f..874081c22 100644 --- a/tests/ui/invalid_upcast_comparisons.stderr +++ b/tests/ui/invalid_upcast_comparisons.stderr @@ -1,8 +1,8 @@ -error: because of the numeric bounds on `u8_max` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:10:5 +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:16:5 | -10 | (u8_max as u32) > 300; - | ^^^^^^^^^^^^^^^^^^^^^ +16 | (u8 as u32) > 300; + | ^^^^^^^^^^^^^^^^^ | note: lint level defined here --> $DIR/invalid_upcast_comparisons.rs:4:9 @@ -10,53 +10,161 @@ note: lint level defined here 4 | #![deny(invalid_upcast_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: because of the numeric bounds on `zero` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:13:5 - | -13 | (zero as i32) < -5; - | ^^^^^^^^^^^^^^^^^^ - -error: because of the numeric bounds on `zero` prior to casting, this expression is always true - --> $DIR/invalid_upcast_comparisons.rs:16:5 - | -16 | -5 < (zero as i32); - | ^^^^^^^^^^^^^^^^^^ - -error: because of the numeric bounds on `zero` prior to casting, this expression is always true +error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:17:5 | -17 | 0 <= (zero as i32); +17 | (u8 as i32) > 300; + | ^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:18:5 + | +18 | (u8 as u32) == 300; | ^^^^^^^^^^^^^^^^^^ -error: because of the numeric bounds on `zero` prior to casting, this expression is always false +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:19:5 + | +19 | (u8 as i32) == 300; + | ^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:20:5 | -20 | -5 > (zero as i32); - | ^^^^^^^^^^^^^^^^^^ +20 | 300 < (u8 as u32); + | ^^^^^^^^^^^^^^^^^ -error: because of the numeric bounds on `u8_max` prior to casting, this expression is always false +error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:21:5 | -21 | -5 >= (u8_max as i32); - | ^^^^^^^^^^^^^^^^^^^^^ +21 | 300 < (u8 as i32); + | ^^^^^^^^^^^^^^^^^ -error: because of the numeric bounds on `u8_max` prior to casting, this expression is always false +error: because of the numeric bounds on `u8` prior to casting, this expression is always false --> $DIR/invalid_upcast_comparisons.rs:22:5 | -22 | 1337 == (u8_max as i32); - | ^^^^^^^^^^^^^^^^^^^^^^^ +22 | 300 == (u8 as u32); + | ^^^^^^^^^^^^^^^^^^ -error: because of the numeric bounds on `zero` prior to casting, this expression is always false - --> $DIR/invalid_upcast_comparisons.rs:24:5 +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:23:5 | -24 | -5 == (zero as i32); - | ^^^^^^^^^^^^^^^^^^^ +23 | 300 == (u8 as i32); + | ^^^^^^^^^^^^^^^^^^ -error: because of the numeric bounds on `u8_max` prior to casting, this expression is always true +error: because of the numeric bounds on `u8` prior to casting, this expression is always true --> $DIR/invalid_upcast_comparisons.rs:25:5 | -25 | -5 != (u8_max as i32); - | ^^^^^^^^^^^^^^^^^^^^^ +25 | (u8 as u32) <= 300; + | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:26:5 + | +26 | (u8 as i32) <= 300; + | ^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:27:5 + | +27 | (u8 as u32) != 300; + | ^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:28:5 + | +28 | (u8 as i32) != 300; + | ^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:29:5 + | +29 | 300 >= (u8 as u32); + | ^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:30:5 + | +30 | 300 >= (u8 as i32); + | ^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:31:5 + | +31 | 300 != (u8 as u32); + | ^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:32:5 + | +32 | 300 != (u8 as i32); + | ^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:35:5 + | +35 | (u8 as i32) < 0; + | ^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:36:5 + | +36 | -5 != (u8 as i32); + | ^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:38:5 + | +38 | (u8 as i32) >= 0; + | ^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:39:5 + | +39 | -5 == (u8 as i32); + | ^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:42:5 + | +42 | 1337 == (u8 as i32); + | ^^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:43:5 + | +43 | 1337 == (u8 as u32); + | ^^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:45:5 + | +45 | 1337 != (u8 as i32); + | ^^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:46:5 + | +46 | 1337 != (u8 as u32); + | ^^^^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always true + --> $DIR/invalid_upcast_comparisons.rs:61:5 + | +61 | (u8 as i32) > -1; + | ^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:62:5 + | +62 | (u8 as i32) < -1; + | ^^^^^^^^^^^^^^^^ + +error: because of the numeric bounds on `u8` prior to casting, this expression is always false + --> $DIR/invalid_upcast_comparisons.rs:78:5 + | +78 | -5 >= (u8 as i32); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 27 previous errors