From 6be2bc817bbb70ac13a1c2bb9647e01e2a156127 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 22 Dec 2013 00:07:21 +0100 Subject: [PATCH] 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 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 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 +}