Casts : work in progress handling *size separately

This commit is contained in:
R.Chavignat 2015-08-22 02:44:05 +02:00
parent 6ffe1ed337
commit f1255d5f5d
2 changed files with 35 additions and 30 deletions

View File

@ -150,14 +150,21 @@ declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow,
/// Will return 0 if the type is not an int or uint variant
fn int_ty_to_nbits(typ: &ty::TyS) -> usize {
let n = match &typ.sty {
&ty::TyInt(i) => 4 << (i as usize),
&ty::TyUint(u) => 4 << (u as usize),
_ => 0
&ty::TyInt(i) => 4 << (i as usize),
&ty::TyUint(u) => 4 << (u as usize),
_ => 0
};
// n == 4 is the usize/isize case
if n == 4 { ::std::usize::BITS } else { n }
}
fn is_isize_or_usize(typ: &ty::TyS) -> bool {
match &typ.sty {
&ty::TyInt(ast::TyIs) | &ty::TyUint(ast::TyUs) => true,
_ => false
}
}
impl LintPass for CastPass {
fn get_lints(&self) -> LintArray {
lint_array!(CAST_PRECISION_LOSS,
@ -178,7 +185,14 @@ impl LintPass for CastPass {
_ => 0
};
if from_nbits != 0 {
if from_nbits >= to_nbits {
// When casting to f32, precision loss would occur regardless of the arch
if is_isize_or_usize(cast_from) && to_nbits == 64 {
span_lint(cx, CAST_PRECISION_LOSS, expr.span,
&format!("converting from {0} to f64, which causes a loss of precision on 64-bit architectures \
({0} is 64 bits wide, but f64's mantissa is only 52 bits wide)",
cast_from));
}
else if from_nbits >= to_nbits {
span_lint(cx, CAST_PRECISION_LOSS, expr.span,
&format!("converting from {0} to {1}, which causes a loss of precision \
({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)",
@ -186,7 +200,7 @@ impl LintPass for CastPass {
}
}
},
(false, true) => {
(false, true) => { // Nothing to add there
span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span,
&format!("casting {} to {} may cause truncation of the value", cast_from, cast_to));
if !cast_to.is_signed() {
@ -201,10 +215,15 @@ impl LintPass for CastPass {
}
let from_nbits = int_ty_to_nbits(cast_from);
let to_nbits = int_ty_to_nbits(cast_to);
if to_nbits < from_nbits ||
(!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) {
span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span,
&format!("casting {} to {} may cause truncation of the value", cast_from, cast_to));
match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
(true, true) | (false, false) =>
if to_nbits < from_nbits ||
(!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) {
span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span,
&format!("casting {} to {} may cause truncation of the value", cast_from, cast_to));
},
(true, false) => (), // TODO
(false, true) => () // TODO
}
}
(false, false) => {

View File

@ -32,26 +32,12 @@ fn main() {
i as u32; //~ERROR casting from i32 to u32 loses the sign of the value
// Extra checks for usize/isize
let is : isize = -42;
is as usize; //~ERROR casting from isize to usize loses the sign of the value
is as i8; //~ERROR casting isize to i8 may cause truncation of the value
// FIXME : enable these checks when we figure out a way to make compiletest deal with conditional compilation
/*
#[cfg(target_pointer_width = "64")]
fn check_64() {
let is : isize = -42;
let us : usize = 42;
is as f32; //ERROR converting from isize to f32, which causes a loss of precision (isize is 64 bits wide, but f32's mantissa is only 23 bits wide)
us as u32; //ERROR casting usize to u32 may cause truncation of the value
us as u64; // Should not trigger any lint
}
#[cfg(target_pointer_width = "32")]
fn check_32() {
let is : isize = -42;
let us : usize = 42;
is as f32; //ERROR converting from isize to f32, which causes a loss of precision (isize is 32 bits wide, but f32's mantissa is only 23 bits wide)
us as u32; // Should not trigger any lint
us as u64; // Should not trigger any lint
}*/
let is : isize = -42;
let us : usize = 42;
is as usize; //ERROR casting from isize to usize loses the sign of the value
is as i8; //ERROR casting isize to i8 may cause truncation of the value
is as f64; //ERROR converting from isize to f64, which causes a loss of precision on 64-bit architectures (isize is 64 bits wide, but f64's mantissa is only 52 bits wide)
us as f64; //ERROR converting from usize to f64, which causes a loss of precision on 64-bit architectures (usize is 64 bits wide, but f64's mantissa is only 52 bits wide)
*/
}