about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2013-12-22 00:07:21 +0100
committerFlorian Hahn <flo@fhahn.com>2014-01-06 21:28:49 +0100
commit6be2bc817bbb70ac13a1c2bb9647e01e2a156127 (patch)
tree5374b72989d88627c111eec0b68f0b487172b538
parent1d9e66c0ebfb16686ca4f57cbc7af1343ad08251 (diff)
downloadrust-6be2bc817bbb70ac13a1c2bb9647e01e2a156127.tar.gz
rust-6be2bc817bbb70ac13a1c2bb9647e01e2a156127.zip
Add lint for unnecessary casts
-rw-r--r--src/librustc/middle/lint.rs45
-rw-r--r--src/test/compile-fail/lint-unnecessary-casts.rs24
2 files changed, 68 insertions, 1 deletions
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 666c7d84a9a..9f4d9a5c7f5 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 00000000000..9324bf11005
--- /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 <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
+}