Skip to content

Lint for unnecessary type casts #11329

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 7, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libextra/bitv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl SmallBitv {
self.bits |= 1<<i;
}
else {
self.bits &= !(1<<i as uint);
self.bits &= !(1<<i);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/libextra/ebml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ pub mod writer {
let cur_pos = self.writer.tell();
self.writer.seek(last_size_pos as i64, io::SeekSet);
let size = (cur_pos as uint - last_size_pos - 4);
write_sized_vuint(self.writer, size as uint, 4u);
write_sized_vuint(self.writer, size, 4u);
self.writer.seek(cur_pos as i64, io::SeekSet);

debug!("End tag (size = {})", size);
Expand Down
8 changes: 4 additions & 4 deletions src/libextra/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,8 +929,8 @@ fn calc_result(desc: &TestDesc, task_succeeded: bool) -> TestResult {
impl ToJson for Metric {
fn to_json(&self) -> json::Json {
let mut map = ~TreeMap::new();
map.insert(~"value", json::Number(self.value as f64));
map.insert(~"noise", json::Number(self.noise as f64));
map.insert(~"value", json::Number(self.value));
map.insert(~"noise", json::Number(self.noise));
json::Object(map)
}
}
Expand Down Expand Up @@ -1132,15 +1132,15 @@ impl BenchHarness {
let loop_start = precise_time_ns();

for p in samples.mut_iter() {
self.bench_n(n as u64, |x| f(x));
self.bench_n(n, |x| f(x));
*p = self.ns_per_iter() as f64;
};

stats::winsorize(samples, 5.0);
let summ = stats::Summary::new(samples);

for p in samples.mut_iter() {
self.bench_n(5 * n as u64, |x| f(x));
self.bench_n(5 * n, |x| f(x));
*p = self.ns_per_iter() as f64;
};

Expand Down
4 changes: 2 additions & 2 deletions src/libextra/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,13 +767,13 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {

let mut buf = [0];
let c = match rdr.read(buf) {
Some(..) => buf[0] as u8 as char,
Some(..) => buf[0] as char,
None => break
};
match c {
'%' => {
let ch = match rdr.read(buf) {
Some(..) => buf[0] as u8 as char,
Some(..) => buf[0] as char,
None => break
};
match parse_type(s, pos, ch, &mut tm) {
Expand Down
45 changes: 44 additions & 1 deletion src/librustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ use middle::typeck;
use middle::pat_util;
use metadata::csearch;
use util::ppaux::{ty_to_str};
use std::to_str::ToStr;

use middle::typeck::infer;
use middle::typeck::astconv::{ast_ty_to_ty, AstConv};

use std::cmp;
use std::hashmap::HashMap;
Expand Down Expand Up @@ -91,6 +95,7 @@ pub enum lint {
unused_mut,
unnecessary_allocation,
dead_code,
unnecessary_typecast,

missing_doc,
unreachable_code,
Expand Down Expand Up @@ -267,6 +272,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
default: warn
}),

("unnecessary_typecast",
LintSpec {
lint: unnecessary_typecast,
desc: "detects unnecessary type casts, that can be removed",
default: allow,
}),

("unused_mut",
LintSpec {
lint: unused_mut,
Expand Down Expand Up @@ -336,7 +348,6 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
desc: "unknown features found in crate-level #[feature] directives",
default: deny,
}),

("unknown_crate_type",
LintSpec {
lint: unknown_crate_type,
Expand Down Expand Up @@ -569,6 +580,37 @@ fn check_while_true_expr(cx: &Context, e: &ast::Expr) {
_ => ()
}
}
impl<'a> AstConv for Context<'a>{
fn tcx(&self) -> ty::ctxt { self.tcx }

fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
ty::lookup_item_type(self.tcx, id)
}

fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
ty::lookup_trait_def(self.tcx, id)
}

fn ty_infer(&self, _span: Span) -> ty::t {
let infcx: @infer::InferCtxt = infer::new_infer_ctxt(self.tcx);
infcx.next_ty_var()
}
}


fn check_unused_casts(cx: &Context, e: &ast::Expr) {
return match e.node {
ast::ExprCast(expr, ty) => {
let infcx: @infer::InferCtxt = infer::new_infer_ctxt(cx.tcx);
let t_t = ast_ty_to_ty(cx, &infcx, ty);
if ty::get(ty::expr_ty(cx.tcx, expr)).sty == ty::get(t_t).sty {
cx.span_lint(unnecessary_typecast, ty.span,
"unnecessary type cast");
}
}
_ => ()
};
}

fn check_type_limits(cx: &Context, e: &ast::Expr) {
return match e.node {
Expand Down Expand Up @@ -1361,6 +1403,7 @@ impl<'a> Visitor<()> for Context<'a> {
check_heap_expr(self, e);

check_type_limits(self, e);
check_unused_casts(self, e);

visit::walk_expr(self, e, ());
}
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ unsafe fn each_live_alloc(read_next_before: bool,
let next_before = (*alloc).next;
let uniq = (*alloc).ref_count == managed::RC_MANAGED_UNIQUE;

if !f(alloc as *mut raw::Box<()>, uniq) {
if !f(alloc, uniq) {
return false;
}

Expand Down
10 changes: 5 additions & 5 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ pub trait Reader {
///
/// `u64`s are 8 bytes long.
fn read_be_u64(&mut self) -> u64 {
self.read_be_uint_n(8) as u64
self.read_be_uint_n(8)
}

/// Reads a big-endian `u32`.
Expand All @@ -746,7 +746,7 @@ pub trait Reader {
///
/// `i64`s are 8 bytes long.
fn read_be_i64(&mut self) -> i64 {
self.read_be_int_n(8) as i64
self.read_be_int_n(8)
}

/// Reads a big-endian `i32`.
Expand Down Expand Up @@ -785,7 +785,7 @@ pub trait Reader {
///
/// `u64`s are 8 bytes long.
fn read_le_u64(&mut self) -> u64 {
self.read_le_uint_n(8) as u64
self.read_le_uint_n(8)
}

/// Reads a little-endian `u32`.
Expand All @@ -806,7 +806,7 @@ pub trait Reader {
///
/// `i64`s are 8 bytes long.
fn read_le_i64(&mut self) -> i64 {
self.read_le_int_n(8) as i64
self.read_le_int_n(8)
}

/// Reads a little-endian `i32`.
Expand Down Expand Up @@ -846,7 +846,7 @@ pub trait Reader {
/// `u8`s are 1 byte.
fn read_u8(&mut self) -> u8 {
match self.read_byte() {
Some(b) => b as u8,
Some(b) => b,
None => 0
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/libstd/io/net/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,11 @@ impl<'a> Parser<'a> {
let c = c as u8;
// assuming radix is either 10 or 16
if c >= '0' as u8 && c <= '9' as u8 {
Some((c - '0' as u8) as u8)
Some(c - '0' as u8)
} else if radix > 10 && c >= 'a' as u8 && c < 'a' as u8 + (radix - 10) {
Some((c - 'a' as u8 + 10) as u8)
Some(c - 'a' as u8 + 10)
} else if radix > 10 && c >= 'A' as u8 && c < 'A' as u8 + (radix - 10) {
Some((c - 'A' as u8 + 10) as u8)
Some(c - 'A' as u8 + 10)
} else {
None
}
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ impl Reader for StdReader {
io_error::cond.raise(standard_error(EndOfFile));
None
}
Ok(amt) => Some(amt as uint),
Ok(amt) => Some(amt),
Err(e) => {
io_error::cond.raise(e);
None
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/num/strconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+Round+
// round the remaining ones.
if limit_digits && dig == digit_count {
let ascii2value = |chr: u8| {
char::to_digit(chr as char, radix).unwrap() as uint
char::to_digit(chr as char, radix).unwrap()
};
let value2ascii = |val: uint| {
char::from_digit(val, radix).unwrap() as u8
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/rand/distributions/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl Rand for StandardNormal {
fn rand<R:Rng>(rng: &mut R) -> StandardNormal {
#[inline]
fn pdf(x: f64) -> f64 {
((-x*x/2.0) as f64).exp()
(-x*x/2.0).exp()
}
#[inline]
fn zero_case<R:Rng>(rng: &mut R, u: f64) -> f64 {
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/rt/global_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub unsafe fn closure_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
assert!(td.is_not_null());

let total_size = get_box_size(size, (*td).align);
let p = malloc_raw(total_size as uint);
let p = malloc_raw(total_size);

let alloc = p as *mut raw::Box<()>;
(*alloc).type_desc = td;
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ pub fn utf16_chars(v: &[u16], f: |char|) {
let mut c: u32 = (u - 0xD800_u16) as u32;
c = c << 10;
c |= (u2 - 0xDC00_u16) as u32;
c |= 0x1_0000_u32 as u32;
c |= 0x1_0000_u32;
f(unsafe { cast::transmute(c) });
i += 2u;
}
Expand Down Expand Up @@ -987,7 +987,7 @@ pub mod raw {
/// Create a Rust string from a *u8 buffer of the given length
pub unsafe fn from_buf_len(buf: *u8, len: uint) -> ~str {
let mut v: ~[u8] = vec::with_capacity(len);
ptr::copy_memory(v.as_mut_ptr(), buf as *u8, len);
ptr::copy_memory(v.as_mut_ptr(), buf, len);
v.set_len(len);

assert!(is_utf8(v));
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/unstable/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ impl Mutex {
/// Creates a new mutex, with the lock/condition variable pre-initialized
pub unsafe fn new() -> Mutex {
Mutex {
lock: atomics::AtomicUint::new(imp::init_lock() as uint),
cond: atomics::AtomicUint::new(imp::init_cond() as uint),
lock: atomics::AtomicUint::new(imp::init_lock()),
cond: atomics::AtomicUint::new(imp::init_cond()),
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/test/compile-fail/lint-unnecessary-casts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[forbid(unnecessary_typecast)];

fn foo_i32(_: i32) {}

fn foo_u64(a: u64) {
let b: i32 = a as i32;
foo_i32(b as i32); //~ ERROR: unnecessary type cast
}

fn main() {
let x: u64 = 1;
let y: u64 = x as u64; //~ ERROR: unnecessary type cast
foo_u64(y as u64); //~ ERROR: unnecessary type cast
}