From 6be2bc817bbb70ac13a1c2bb9647e01e2a156127 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 22 Dec 2013 00:07:21 +0100 Subject: [PATCH 1/2] Add lint for unnecessary casts --- src/librustc/middle/lint.rs | 45 ++++++++++++++++++- .../compile-fail/lint-unnecessary-casts.rs | 24 ++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/lint-unnecessary-casts.rs diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 666c7d84a9a90..9f4d9a5c7f56f 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -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; @@ -91,6 +95,7 @@ pub enum lint { unused_mut, unnecessary_allocation, dead_code, + unnecessary_typecast, missing_doc, unreachable_code, @@ -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, @@ -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, @@ -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 { @@ -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, ()); } diff --git a/src/test/compile-fail/lint-unnecessary-casts.rs b/src/test/compile-fail/lint-unnecessary-casts.rs new file mode 100644 index 0000000000000..9324bf110056a --- /dev/null +++ b/src/test/compile-fail/lint-unnecessary-casts.rs @@ -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 or the MIT license +// , 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 +} From 82365501043735dd8ec5eadaa5d30354cee19252 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Wed, 25 Dec 2013 00:53:05 +0100 Subject: [PATCH 2/2] Remove some unnecessary type casts Conflicts: src/librustc/middle/lint.rs --- src/libextra/bitv.rs | 2 +- src/libextra/ebml.rs | 2 +- src/libextra/test.rs | 8 ++++---- src/libextra/time.rs | 4 ++-- src/libstd/cleanup.rs | 2 +- src/libstd/io/mod.rs | 10 +++++----- src/libstd/io/net/ip.rs | 6 +++--- src/libstd/io/stdio.rs | 2 +- src/libstd/num/strconv.rs | 2 +- src/libstd/rand/distributions/normal.rs | 2 +- src/libstd/rt/global_heap.rs | 2 +- src/libstd/str.rs | 4 ++-- src/libstd/unstable/mutex.rs | 4 ++-- 13 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/libextra/bitv.rs b/src/libextra/bitv.rs index 3b44ad50ad79a..9f40507826fde 100644 --- a/src/libextra/bitv.rs +++ b/src/libextra/bitv.rs @@ -80,7 +80,7 @@ impl SmallBitv { self.bits |= 1< 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) } } @@ -1132,7 +1132,7 @@ 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; }; @@ -1140,7 +1140,7 @@ impl BenchHarness { 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; }; diff --git a/src/libextra/time.rs b/src/libextra/time.rs index 23c81c6fce529..c2948024e2801 100644 --- a/src/libextra/time.rs +++ b/src/libextra/time.rs @@ -767,13 +767,13 @@ pub fn strptime(s: &str, format: &str) -> Result { 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) { diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index fbcf7dd4e9026..fd9040423a3d9 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -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; } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index b7e185f8ed503..823ca80a8a176 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -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`. @@ -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`. @@ -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`. @@ -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`. @@ -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 } } diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index b4d14b57efca1..9fd183ca7704c 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -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 } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1e4fa7968dc42..1fcafd7d12f78 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -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 diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 8e678ab66b25e..7dcae69f70d6d 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -344,7 +344,7 @@ pub fn float_to_str_bytes_common(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(rng: &mut R, u: f64) -> f64 { diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs index 385bb0b276c49..c094344f6b926 100644 --- a/src/libstd/rt/global_heap.rs +++ b/src/libstd/rt/global_heap.rs @@ -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; diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 0d4c820e6379a..a70698d487cc2 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -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; } @@ -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)); diff --git a/src/libstd/unstable/mutex.rs b/src/libstd/unstable/mutex.rs index 36682b8541860..e11557ff337c2 100644 --- a/src/libstd/unstable/mutex.rs +++ b/src/libstd/unstable/mutex.rs @@ -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()), } }