diff --git a/src/array_indexing.rs b/src/array_indexing.rs index 274491b7c..3c6acb932 100644 --- a/src/array_indexing.rs +++ b/src/array_indexing.rs @@ -3,6 +3,7 @@ use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::ty::TyArray; use rustc_front::hir::*; +use rustc_const_eval::ConstInt; use syntax::ast::RangeLimits; use utils; @@ -62,11 +63,11 @@ impl LateLintPass for ArrayIndexing { // Array with known size can be checked statically let ty = cx.tcx.expr_ty(array); if let TyArray(_, size) = ty.sty { - let size = size as u64; + let size = ConstInt::Infer(size as u64); // Index is a constant uint let const_index = eval_const_expr_partial(cx.tcx, &index, ExprTypeChecked, None); - if let Ok(ConstVal::Uint(const_index)) = const_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"); } @@ -115,24 +116,24 @@ impl LateLintPass for ArrayIndexing { fn to_const_range(start: Option>, end: Option>, limits: RangeLimits, - array_size: u64) - -> Option<(u64, u64)> { + array_size: ConstInt) + -> Option<(ConstInt, ConstInt)> { let start = match start { - Some(Some(ConstVal::Uint(x))) => x, + Some(Some(ConstVal::Integral(x))) => x, Some(_) => return None, - None => 0, + None => ConstInt::Infer(0), }; let end = match end { - Some(Some(ConstVal::Uint(x))) => { + Some(Some(ConstVal::Integral(x))) => { if limits == RangeLimits::Closed { x } else { - x - 1 + (x - ConstInt::Infer(1)).expect("x > 0") } } Some(_) => return None, - None => array_size - 1, + None => (array_size - ConstInt::Infer(1)).expect("array_size > 0"), }; Some((start, end)) diff --git a/src/bit_mask.rs b/src/bit_mask.rs index 0e09122bc..02d428e83 100644 --- a/src/bit_mask.rs +++ b/src/bit_mask.rs @@ -271,7 +271,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option { } } .and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None, None)) - .and_then(|l| fetch_int_literal(cx, l)) + .and_then(|(l, _ty)| fetch_int_literal(cx, l)) } _ => None, } diff --git a/src/consts.rs b/src/consts.rs index 6dd5651e7..eae9747d6 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -347,7 +347,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } // separate if lets to avoid double borrowing the def_map if let Some(id) = maybe_id { - if let Some(const_expr) = lookup_const_by_id(lcx.tcx, id, None, None) { + if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None, None) { let ret = self.expr(const_expr); if ret.is_some() { self.needed_resolution = true; diff --git a/src/enum_clike.rs b/src/enum_clike.rs index 7ee71f41f..85fa418f2 100644 --- a/src/enum_clike.rs +++ b/src/enum_clike.rs @@ -1,11 +1,9 @@ //! lint on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32` use rustc::lint::*; -use syntax::ast::{IntTy, UintTy}; use syntax::attr::*; use rustc_front::hir::*; use rustc::middle::const_eval::{ConstVal, EvalHint, eval_const_expr_partial}; -use rustc::middle::ty; use utils::span_lint; /// **What it does:** Lints on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`. @@ -35,12 +33,10 @@ impl LateLintPass for EnumClikeUnportableVariant { for var in &def.variants { let variant = &var.node; if let Some(ref disr) = variant.disr_expr { - let cv = eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None); - let bad = match (cv, &cx.tcx.expr_ty(&**disr).sty) { - (Ok(ConstVal::Int(i)), &ty::TyInt(IntTy::Is)) => i as i32 as i64 != i, - (Ok(ConstVal::Uint(i)), &ty::TyInt(IntTy::Is)) => i as i32 as u64 != i, - (Ok(ConstVal::Int(i)), &ty::TyUint(UintTy::Us)) => (i < 0) || (i as u32 as i64 != i), - (Ok(ConstVal::Uint(i)), &ty::TyUint(UintTy::Us)) => i as u32 as u64 != i, + use rustc_const_eval::*; + let bad = match eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None) { + 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, }; if bad { diff --git a/src/loops.rs b/src/loops.rs index 462ca7c49..7987c70d0 100644 --- a/src/loops.rs +++ b/src/loops.rs @@ -429,10 +429,7 @@ fn check_for_loop_reverse_range(cx: &LateContext, arg: &Expr, expr: &Expr) { // who think that this will iterate from the larger value to the // smaller value. let (sup, eq) = match (start_idx, end_idx) { - (ConstVal::Int(start_idx), ConstVal::Int(end_idx)) => { - (start_idx > end_idx, start_idx == end_idx) - } - (ConstVal::Uint(start_idx), ConstVal::Uint(end_idx)) => { + (ConstVal::Integral(start_idx), ConstVal::Integral(end_idx)) => { (start_idx > end_idx, start_idx == end_idx) } _ => (false, false), diff --git a/src/matches.rs b/src/matches.rs index 4c60ea89b..a456a816f 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -1,9 +1,9 @@ use rustc::lint::*; -use rustc::middle::const_eval::ConstVal::{Int, Uint}; use rustc::middle::const_eval::EvalHint::ExprTypeChecked; use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal}; use rustc::middle::ty; use rustc_front::hir::*; +use rustc_const_eval::ConstInt; use std::cmp::Ordering; use syntax::ast::LitKind; use syntax::codemap::Span; @@ -288,19 +288,16 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) { fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) { if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() { let ranges = all_ranges(cx, arms); - let overlap = match type_ranges(&ranges) { - TypedRanges::IntRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)), - TypedRanges::UintRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)), - TypedRanges::None => None, - }; - - if let Some((start, end)) = overlap { - span_note_and_lint(cx, - MATCH_OVERLAPPING_ARM, - start, - "some ranges overlap", - end, - "overlaps with this"); + let type_ranges = type_ranges(&ranges); + if !type_ranges.is_empty() { + if let Some((start, end)) = overlapping(&type_ranges) { + span_note_and_lint(cx, + MATCH_OVERLAPPING_ARM, + start.span, + "some ranges overlap", + end.span, + "overlaps with this"); + } } } } @@ -370,51 +367,22 @@ pub struct SpannedRange { pub node: (T, T), } -#[derive(Debug)] -enum TypedRanges { - IntRanges(Vec>), - UintRanges(Vec>), - None, -} +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]) -> TypedRanges { - if ranges.is_empty() { - TypedRanges::None - } else { - match ranges[0].node { - (Int(_), Int(_)) => { - TypedRanges::IntRanges(ranges.iter() - .filter_map(|range| { - if let (Int(start), Int(end)) = range.node { - Some(SpannedRange { - span: range.span, - node: (start, end), - }) - } else { - None - } - }) - .collect()) - } - (Uint(_), Uint(_)) => { - TypedRanges::UintRanges(ranges.iter() - .filter_map(|range| { - if let (Uint(start), Uint(end)) = range.node { - Some(SpannedRange { - span: range.span, - node: (start, end), - }) - } else { - None - } - }) - .collect()) - } - _ => TypedRanges::None, + ranges.iter().filter_map(|range| { + if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node { + Some(SpannedRange { + span: range.span, + node: (start, end), + }) + } else { + None } - } + }) + .collect() } fn is_unit_expr(expr: &Expr) -> bool { diff --git a/src/types.rs b/src/types.rs index e64bf0105..c5acbb41e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -673,6 +673,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option(cx: &LateContext, expr: &'a Expr) -> Option Minimum, + (&ty::TyBool, Bool(false)) | - (&ty::TyInt(IntTy::Is), Int(x)) if x == ::std::isize::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::I8), Int(x)) if x == ::std::i8::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::I16), Int(x)) if x == ::std::i16::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::I32), Int(x)) if x == ::std::i32::MIN as i64 => Minimum, - (&ty::TyInt(IntTy::I64), Int(x)) if x == ::std::i64::MIN as i64 => Minimum, + (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MIN)))) | + (&ty::TyInt(IntTy::Is), 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::TyUint(UintTy::Us), Uint(x)) if x == ::std::usize::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::U8), Uint(x)) if x == ::std::u8::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::U16), Uint(x)) if x == ::std::u16::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::U32), Uint(x)) if x == ::std::u32::MIN as u64 => Minimum, - (&ty::TyUint(UintTy::U64), Uint(x)) if x == ::std::u64::MIN as u64 => Minimum, + (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MIN)))) | + (&ty::TyUint(UintTy::Us), 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))) => Minimum, - (&ty::TyBool, Bool(true)) => Maximum, + (&ty::TyBool, Bool(true)) | - (&ty::TyInt(IntTy::Is), Int(x)) if x == ::std::isize::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::I8), Int(x)) if x == ::std::i8::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::I16), Int(x)) if x == ::std::i16::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::I32), Int(x)) if x == ::std::i32::MAX as i64 => Maximum, - (&ty::TyInt(IntTy::I64), Int(x)) if x == ::std::i64::MAX as i64 => Maximum, + (&ty::TyInt(IntTy::Is), Integral(Isize(Is32(::std::i32::MAX)))) | + (&ty::TyInt(IntTy::Is), 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::TyUint(UintTy::Us), Uint(x)) if x == ::std::usize::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::U8), Uint(x)) if x == ::std::u8::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::U16), Uint(x)) if x == ::std::u16::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::U32), Uint(x)) if x == ::std::u32::MAX as u64 => Maximum, - (&ty::TyUint(UintTy::U64), Uint(x)) if x == ::std::u64::MAX as u64 => Maximum, + (&ty::TyUint(UintTy::Us), Integral(Usize(Us32(::std::u32::MAX)))) | + (&ty::TyUint(UintTy::Us), 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))) => Maximum, _ => return None, };