mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-21 19:33:16 +00:00
Added support for isize/usize in the CastPass lint pass.
Extracted the match that determines an integer types's size in a utility function and implemented support for usize/isize. Added a needed feature to the crate root. Added some tests to cover those cases, and a test I previously forgot. Silenced two errors signaled by dogfood.sh in unicode.rs.
This commit is contained in:
parent
dbc9b7f46e
commit
ad0bc66402
@ -1,6 +1,6 @@
|
||||
#![feature(plugin_registrar, box_syntax)]
|
||||
#![feature(rustc_private, core, collections)]
|
||||
#![feature(str_split_at)]
|
||||
#![feature(str_split_at, num_bits_bytes)]
|
||||
#![allow(unknown_lints)]
|
||||
|
||||
#[macro_use]
|
||||
|
33
src/types.rs
33
src/types.rs
@ -146,6 +146,18 @@ declare_lint!(pub CAST_SIGN_LOSS, Allow,
|
||||
declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow,
|
||||
"casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`");
|
||||
|
||||
/// Returns the size in bits of an integral type.
|
||||
/// 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
|
||||
};
|
||||
// n == 4 is the usize/isize case
|
||||
if n == 4 { ::std::usize::BITS } else { n }
|
||||
}
|
||||
|
||||
impl LintPass for CastPass {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(CAST_PRECISION_LOSS,
|
||||
@ -159,18 +171,13 @@ impl LintPass for CastPass {
|
||||
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
|
||||
match (cast_from.is_integral(), cast_to.is_integral()) {
|
||||
(true, false) => {
|
||||
let from_nbits = match &cast_from.sty {
|
||||
&ty::TyInt(i) => 4 << (i as usize),
|
||||
&ty::TyUint(u) => 4 << (u as usize),
|
||||
_ => 0
|
||||
};
|
||||
let from_nbits = int_ty_to_nbits(cast_from);
|
||||
let to_nbits : usize = match &cast_to.sty {
|
||||
&ty::TyFloat(ast::TyF32) => 32,
|
||||
&ty::TyFloat(ast::TyF64) => 64,
|
||||
_ => 0
|
||||
};
|
||||
if from_nbits != 4 {
|
||||
// Handle TyIs/TyUs separately (pointer size is arch dependant)
|
||||
if from_nbits != 0 {
|
||||
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 \
|
||||
@ -192,16 +199,8 @@ impl LintPass for CastPass {
|
||||
span_lint(cx, CAST_SIGN_LOSS, expr.span,
|
||||
&format!("casting from {} to {} loses the sign of the value", cast_from, cast_to));
|
||||
}
|
||||
let from_nbits = match &cast_from.sty {
|
||||
&ty::TyInt(i) => 4 << (i as usize),
|
||||
&ty::TyUint(u) => 4 << (u as usize),
|
||||
_ => 0
|
||||
};
|
||||
let to_nbits = match &cast_to.sty {
|
||||
&ty::TyInt(i) => 4 << (i as usize),
|
||||
&ty::TyUint(u) => 4 << (u as usize),
|
||||
_ => 0
|
||||
};
|
||||
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,
|
||||
|
@ -40,6 +40,7 @@ fn check_str(cx: &Context, string: &str, span: Span) {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(cast_possible_truncation)]
|
||||
fn str_pos_lint(cx: &Context, lint: &'static Lint, span: Span, index: usize, msg: &str) {
|
||||
span_lint(cx, lint, Span { lo: span.lo + BytePos((1 + index) as u32),
|
||||
hi: span.lo + BytePos((1 + index) as u32),
|
||||
|
@ -2,6 +2,7 @@
|
||||
#![plugin(clippy)]
|
||||
|
||||
#[deny(cast_precision_loss, cast_possible_truncation, cast_sign_loss)]
|
||||
#[allow(dead_code)]
|
||||
fn main() {
|
||||
let i : i32 = 42;
|
||||
let u : u32 = 42;
|
||||
@ -16,7 +17,7 @@ fn main() {
|
||||
(u as u64) as f64; //~ERROR converting from u64 to f64, which causes a loss of precision (u64 is 64 bits wide, but f64's mantissa is only 52 bits wide)
|
||||
i as f64; // Should not trigger the lint
|
||||
u as f64; // Should not trigger the lint
|
||||
|
||||
|
||||
// Test cast_possible_truncation
|
||||
f as i32; //~ERROR casting f32 to i32 may cause truncation of the value
|
||||
f as u32; //~ERROR casting f32 to u32 may cause truncation of the value
|
||||
@ -25,7 +26,32 @@ fn main() {
|
||||
//~^ERROR casting from i32 to u8 loses the sign of the value
|
||||
(f as f64) as f32; //~ERROR casting f64 to f32 may cause truncation of the value
|
||||
i as i8; //~ERROR casting i32 to i8 may cause truncation of the value
|
||||
|
||||
u as i32; //~ERROR casting u32 to i32 may cause truncation of the value
|
||||
|
||||
// Test cast_sign_loss
|
||||
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
|
||||
}*/
|
||||
}
|
Loading…
Reference in New Issue
Block a user