rustup const eval changes
This commit is contained in:
@@ -3,6 +3,7 @@ use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
|||||||
use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal};
|
use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal};
|
||||||
use rustc::middle::ty::TyArray;
|
use rustc::middle::ty::TyArray;
|
||||||
use rustc_front::hir::*;
|
use rustc_front::hir::*;
|
||||||
|
use rustc_const_eval::ConstInt;
|
||||||
use syntax::ast::RangeLimits;
|
use syntax::ast::RangeLimits;
|
||||||
use utils;
|
use utils;
|
||||||
|
|
||||||
@@ -62,11 +63,11 @@ impl LateLintPass for ArrayIndexing {
|
|||||||
// Array with known size can be checked statically
|
// Array with known size can be checked statically
|
||||||
let ty = cx.tcx.expr_ty(array);
|
let ty = cx.tcx.expr_ty(array);
|
||||||
if let TyArray(_, size) = ty.sty {
|
if let TyArray(_, size) = ty.sty {
|
||||||
let size = size as u64;
|
let size = ConstInt::Infer(size as u64);
|
||||||
|
|
||||||
// Index is a constant uint
|
// Index is a constant uint
|
||||||
let const_index = eval_const_expr_partial(cx.tcx, &index, ExprTypeChecked, None);
|
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 {
|
if size <= const_index {
|
||||||
utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds");
|
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>>,
|
fn to_const_range(start: Option<Option<ConstVal>>,
|
||||||
end: Option<Option<ConstVal>>,
|
end: Option<Option<ConstVal>>,
|
||||||
limits: RangeLimits,
|
limits: RangeLimits,
|
||||||
array_size: u64)
|
array_size: ConstInt)
|
||||||
-> Option<(u64, u64)> {
|
-> Option<(ConstInt, ConstInt)> {
|
||||||
let start = match start {
|
let start = match start {
|
||||||
Some(Some(ConstVal::Uint(x))) => x,
|
Some(Some(ConstVal::Integral(x))) => x,
|
||||||
Some(_) => return None,
|
Some(_) => return None,
|
||||||
None => 0,
|
None => ConstInt::Infer(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
let end = match end {
|
let end = match end {
|
||||||
Some(Some(ConstVal::Uint(x))) => {
|
Some(Some(ConstVal::Integral(x))) => {
|
||||||
if limits == RangeLimits::Closed {
|
if limits == RangeLimits::Closed {
|
||||||
x
|
x
|
||||||
} else {
|
} else {
|
||||||
x - 1
|
(x - ConstInt::Infer(1)).expect("x > 0")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(_) => return None,
|
Some(_) => return None,
|
||||||
None => array_size - 1,
|
None => (array_size - ConstInt::Infer(1)).expect("array_size > 0"),
|
||||||
};
|
};
|
||||||
|
|
||||||
Some((start, end))
|
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(|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,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
|||||||
}
|
}
|
||||||
// separate if lets to avoid double borrowing the def_map
|
// separate if lets to avoid double borrowing the def_map
|
||||||
if let Some(id) = maybe_id {
|
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);
|
let ret = self.expr(const_expr);
|
||||||
if ret.is_some() {
|
if ret.is_some() {
|
||||||
self.needed_resolution = true;
|
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`
|
//! lint on C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`
|
||||||
|
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use syntax::ast::{IntTy, UintTy};
|
|
||||||
use syntax::attr::*;
|
use syntax::attr::*;
|
||||||
use rustc_front::hir::*;
|
use rustc_front::hir::*;
|
||||||
use rustc::middle::const_eval::{ConstVal, EvalHint, eval_const_expr_partial};
|
use rustc::middle::const_eval::{ConstVal, EvalHint, eval_const_expr_partial};
|
||||||
use rustc::middle::ty;
|
|
||||||
use utils::span_lint;
|
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`.
|
/// **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 {
|
for var in &def.variants {
|
||||||
let variant = &var.node;
|
let variant = &var.node;
|
||||||
if let Some(ref disr) = variant.disr_expr {
|
if let Some(ref disr) = variant.disr_expr {
|
||||||
let cv = eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None);
|
use rustc_const_eval::*;
|
||||||
let bad = match (cv, &cx.tcx.expr_ty(&**disr).sty) {
|
let bad = match eval_const_expr_partial(cx.tcx, &**disr, EvalHint::ExprTypeChecked, None) {
|
||||||
(Ok(ConstVal::Int(i)), &ty::TyInt(IntTy::Is)) => i as i32 as i64 != i,
|
Ok(ConstVal::Integral(Usize(Us64(i)))) => i as u32 as u64 != i,
|
||||||
(Ok(ConstVal::Uint(i)), &ty::TyInt(IntTy::Is)) => i as i32 as u64 != i,
|
Ok(ConstVal::Integral(Isize(Is64(i)))) => i as i32 as i64 != 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,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if bad {
|
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
|
// who think that this will iterate from the larger value to the
|
||||||
// smaller value.
|
// smaller value.
|
||||||
let (sup, eq) = match (start_idx, end_idx) {
|
let (sup, eq) = match (start_idx, end_idx) {
|
||||||
(ConstVal::Int(start_idx), ConstVal::Int(end_idx)) => {
|
(ConstVal::Integral(start_idx), ConstVal::Integral(end_idx)) => {
|
||||||
(start_idx > end_idx, start_idx == end_idx)
|
|
||||||
}
|
|
||||||
(ConstVal::Uint(start_idx), ConstVal::Uint(end_idx)) => {
|
|
||||||
(start_idx > end_idx, start_idx == end_idx)
|
(start_idx > end_idx, start_idx == end_idx)
|
||||||
}
|
}
|
||||||
_ => (false, false),
|
_ => (false, false),
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::middle::const_eval::ConstVal::{Int, Uint};
|
|
||||||
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
use rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||||
use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal};
|
use rustc::middle::const_eval::{eval_const_expr_partial, ConstVal};
|
||||||
use rustc::middle::ty;
|
use rustc::middle::ty;
|
||||||
use rustc_front::hir::*;
|
use rustc_front::hir::*;
|
||||||
|
use rustc_const_eval::ConstInt;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use syntax::ast::LitKind;
|
use syntax::ast::LitKind;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
@@ -288,21 +288,18 @@ fn check_match_bool(cx: &LateContext, ex: &Expr, arms: &[Arm], expr: &Expr) {
|
|||||||
fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
|
fn check_overlapping_arms(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
|
||||||
if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() {
|
if arms.len() >= 2 && cx.tcx.expr_ty(ex).is_integral() {
|
||||||
let ranges = all_ranges(cx, arms);
|
let ranges = all_ranges(cx, arms);
|
||||||
let overlap = match type_ranges(&ranges) {
|
let type_ranges = type_ranges(&ranges);
|
||||||
TypedRanges::IntRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)),
|
if !type_ranges.is_empty() {
|
||||||
TypedRanges::UintRanges(ranges) => overlapping(&ranges).map(|(start, end)| (start.span, end.span)),
|
if let Some((start, end)) = overlapping(&type_ranges) {
|
||||||
TypedRanges::None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some((start, end)) = overlap {
|
|
||||||
span_note_and_lint(cx,
|
span_note_and_lint(cx,
|
||||||
MATCH_OVERLAPPING_ARM,
|
MATCH_OVERLAPPING_ARM,
|
||||||
start,
|
start.span,
|
||||||
"some ranges overlap",
|
"some ranges overlap",
|
||||||
end,
|
end.span,
|
||||||
"overlaps with this");
|
"overlaps with this");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) {
|
fn check_match_ref_pats(cx: &LateContext, ex: &Expr, arms: &[Arm], source: MatchSource, expr: &Expr) {
|
||||||
@@ -370,24 +367,13 @@ pub struct SpannedRange<T> {
|
|||||||
pub node: (T, T),
|
pub node: (T, T),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
type TypedRanges = Vec<SpannedRange<ConstInt>>;
|
||||||
enum TypedRanges {
|
|
||||||
IntRanges(Vec<SpannedRange<i64>>),
|
|
||||||
UintRanges(Vec<SpannedRange<u64>>),
|
|
||||||
None,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway and other types than
|
/// 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.
|
/// `Uint` and `Int` probably don't make sense.
|
||||||
fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges {
|
fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges {
|
||||||
if ranges.is_empty() {
|
ranges.iter().filter_map(|range| {
|
||||||
TypedRanges::None
|
if let (ConstVal::Integral(start), ConstVal::Integral(end)) = range.node {
|
||||||
} else {
|
|
||||||
match ranges[0].node {
|
|
||||||
(Int(_), Int(_)) => {
|
|
||||||
TypedRanges::IntRanges(ranges.iter()
|
|
||||||
.filter_map(|range| {
|
|
||||||
if let (Int(start), Int(end)) = range.node {
|
|
||||||
Some(SpannedRange {
|
Some(SpannedRange {
|
||||||
span: range.span,
|
span: range.span,
|
||||||
node: (start, end),
|
node: (start, end),
|
||||||
@@ -396,25 +382,7 @@ fn type_ranges(ranges: &[SpannedRange<ConstVal>]) -> TypedRanges {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect())
|
.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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_unit_expr(expr: &Expr) -> bool {
|
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 rustc::middle::const_eval::EvalHint::ExprTypeChecked;
|
||||||
use types::ExtremeType::*;
|
use types::ExtremeType::*;
|
||||||
use rustc::middle::const_eval::ConstVal::*;
|
use rustc::middle::const_eval::ConstVal::*;
|
||||||
|
use rustc_const_eval::*;
|
||||||
|
|
||||||
let ty = &cx.tcx.expr_ty(expr).sty;
|
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) {
|
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::Is), Integral(Isize(Is32(::std::i32::MIN)))) |
|
||||||
(&ty::TyInt(IntTy::I8), Int(x)) if x == ::std::i8::MIN as i64 => Minimum,
|
(&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MIN)))) |
|
||||||
(&ty::TyInt(IntTy::I16), Int(x)) if x == ::std::i16::MIN as i64 => Minimum,
|
(&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MIN))) |
|
||||||
(&ty::TyInt(IntTy::I32), Int(x)) if x == ::std::i32::MIN as i64 => Minimum,
|
(&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MIN))) |
|
||||||
(&ty::TyInt(IntTy::I64), Int(x)) if x == ::std::i64::MIN as i64 => Minimum,
|
(&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::Us), Integral(Usize(Us32(::std::u32::MIN)))) |
|
||||||
(&ty::TyUint(UintTy::U8), Uint(x)) if x == ::std::u8::MIN as u64 => Minimum,
|
(&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MIN)))) |
|
||||||
(&ty::TyUint(UintTy::U16), Uint(x)) if x == ::std::u16::MIN as u64 => Minimum,
|
(&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MIN))) |
|
||||||
(&ty::TyUint(UintTy::U32), Uint(x)) if x == ::std::u32::MIN as u64 => Minimum,
|
(&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MIN))) |
|
||||||
(&ty::TyUint(UintTy::U64), Uint(x)) if x == ::std::u64::MIN as u64 => Minimum,
|
(&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::Is), Integral(Isize(Is32(::std::i32::MAX)))) |
|
||||||
(&ty::TyInt(IntTy::I8), Int(x)) if x == ::std::i8::MAX as i64 => Maximum,
|
(&ty::TyInt(IntTy::Is), Integral(Isize(Is64(::std::i64::MAX)))) |
|
||||||
(&ty::TyInt(IntTy::I16), Int(x)) if x == ::std::i16::MAX as i64 => Maximum,
|
(&ty::TyInt(IntTy::I8), Integral(I8(::std::i8::MAX))) |
|
||||||
(&ty::TyInt(IntTy::I32), Int(x)) if x == ::std::i32::MAX as i64 => Maximum,
|
(&ty::TyInt(IntTy::I16), Integral(I16(::std::i16::MAX))) |
|
||||||
(&ty::TyInt(IntTy::I64), Int(x)) if x == ::std::i64::MAX as i64 => Maximum,
|
(&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::Us), Integral(Usize(Us32(::std::u32::MAX)))) |
|
||||||
(&ty::TyUint(UintTy::U8), Uint(x)) if x == ::std::u8::MAX as u64 => Maximum,
|
(&ty::TyUint(UintTy::Us), Integral(Usize(Us64(::std::u64::MAX)))) |
|
||||||
(&ty::TyUint(UintTy::U16), Uint(x)) if x == ::std::u16::MAX as u64 => Maximum,
|
(&ty::TyUint(UintTy::U8), Integral(U8(::std::u8::MAX))) |
|
||||||
(&ty::TyUint(UintTy::U32), Uint(x)) if x == ::std::u32::MAX as u64 => Maximum,
|
(&ty::TyUint(UintTy::U16), Integral(U16(::std::u16::MAX))) |
|
||||||
(&ty::TyUint(UintTy::U64), Uint(x)) if x == ::std::u64::MAX as u64 => Maximum,
|
(&ty::TyUint(UintTy::U32), Integral(U32(::std::u32::MAX))) |
|
||||||
|
(&ty::TyUint(UintTy::U64), Integral(U64(::std::u64::MAX))) => Maximum,
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user