mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 05:33:27 +00:00
rustup const eval changes
This commit is contained in:
parent
20123eef98
commit
d65953330b
7 changed files with 66 additions and 99 deletions
|
@ -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<Option<ConstVal>>,
|
||||
end: Option<Option<ConstVal>>,
|
||||
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))
|
||||
|
|
|
@ -271,7 +271,7 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> {
|
|||
}
|
||||
}
|
||||
.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,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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<T> {
|
|||
pub node: (T, T),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum TypedRanges {
|
||||
IntRanges(Vec<SpannedRange<i64>>),
|
||||
UintRanges(Vec<SpannedRange<u64>>),
|
||||
None,
|
||||
}
|
||||
type TypedRanges = Vec<SpannedRange<ConstInt>>;
|
||||
|
||||
/// 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<ConstVal>]) -> 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 {
|
||||
|
|
49
src/types.rs
49
src/types.rs
|
@ -673,6 +673,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
|
|||
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||
use types::ExtremeType::*;
|
||||
use rustc::middle::const_eval::ConstVal::*;
|
||||
use rustc_const_eval::*;
|
||||
|
||||
let ty = &cx.tcx.expr_ty(expr).sty;
|
||||
|
||||
|
@ -687,33 +688,37 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
|
|||
};
|
||||
|
||||
let which = match (ty, cv) {
|
||||
(&ty::TyBool, Bool(false)) => 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,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue