Add lint for unnecessary casts

This commit is contained in:
Florian Hahn 2013-12-22 00:07:21 +01:00
parent 1d9e66c0eb
commit 6be2bc817b
2 changed files with 68 additions and 1 deletions

View file

@ -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, ());
}

View file

@ -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
}