Casts : work in progress handling *size separately
This commit is contained in:
parent
6ffe1ed337
commit
f1255d5f5d
37
src/types.rs
37
src/types.rs
@ -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) => {
|
||||
|
@ -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)
|
||||
*/
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user