2015-10-28 16:50:00 +00:00
use rustc ::lint ::{ LateContext , LateLintPass , LintArray , LintPass } ;
2016-04-07 15:46:48 +00:00
use rustc ::hir ::def ::Def ;
use rustc ::hir ::{ Expr , Expr_ , Stmt , StmtSemi } ;
2016-02-24 16:38:57 +00:00
use utils ::{ in_macro , span_lint } ;
2015-10-28 16:50:00 +00:00
2016-02-05 23:41:54 +00:00
/// **What it does:** This lint checks for statements which have no effect.
2015-12-14 21:16:56 +00:00
///
/// **Why is this bad?** Similar to dead code, these statements are actually executed. However, as they have no effect, all they do is make the code less readable.
///
/// **Known problems:** None.
///
/// **Example:** `0;`
2015-10-28 16:50:00 +00:00
declare_lint! {
pub NO_EFFECT ,
Warn ,
" statements with no effect "
}
fn has_no_effect ( cx : & LateContext , expr : & Expr ) -> bool {
if in_macro ( cx , expr . span ) {
return false ;
}
match expr . node {
2016-02-11 12:50:41 +00:00
Expr_ ::ExprLit ( .. ) |
Expr_ ::ExprClosure ( .. ) |
Expr_ ::ExprPath ( .. ) = > true ,
Expr_ ::ExprIndex ( ref a , ref b ) |
Expr_ ::ExprBinary ( _ , ref a , ref b ) = > has_no_effect ( cx , a ) & & has_no_effect ( cx , b ) ,
Expr_ ::ExprVec ( ref v ) |
Expr_ ::ExprTup ( ref v ) = > v . iter ( ) . all ( | val | has_no_effect ( cx , val ) ) ,
Expr_ ::ExprRepeat ( ref inner , _ ) |
Expr_ ::ExprCast ( ref inner , _ ) |
Expr_ ::ExprType ( ref inner , _ ) |
Expr_ ::ExprUnary ( _ , ref inner ) |
Expr_ ::ExprField ( ref inner , _ ) |
Expr_ ::ExprTupField ( ref inner , _ ) |
Expr_ ::ExprAddrOf ( _ , ref inner ) |
Expr_ ::ExprBox ( ref inner ) = > has_no_effect ( cx , inner ) ,
Expr_ ::ExprStruct ( _ , ref fields , ref base ) = > {
2015-10-28 16:50:00 +00:00
fields . iter ( ) . all ( | field | has_no_effect ( cx , & field . expr ) ) & &
match * base {
Some ( ref base ) = > has_no_effect ( cx , base ) ,
None = > true ,
}
}
2016-02-11 12:50:41 +00:00
Expr_ ::ExprCall ( ref callee , ref args ) = > {
2015-10-28 16:50:00 +00:00
let def = cx . tcx . def_map . borrow ( ) . get ( & callee . id ) . map ( | d | d . full_def ( ) ) ;
match def {
2016-01-22 12:24:44 +00:00
Some ( Def ::Struct ( .. ) ) |
Some ( Def ::Variant ( .. ) ) = > args . iter ( ) . all ( | arg | has_no_effect ( cx , arg ) ) ,
2015-10-28 16:50:00 +00:00
_ = > false ,
}
}
2016-03-07 15:31:38 +00:00
Expr_ ::ExprBlock ( ref block ) = > {
2016-04-14 18:14:03 +00:00
block . stmts . is_empty ( ) & &
if let Some ( ref expr ) = block . expr {
2016-03-07 15:31:38 +00:00
has_no_effect ( cx , expr )
} else {
false
}
}
2015-10-28 16:50:00 +00:00
_ = > false ,
}
}
#[ derive(Copy, Clone) ]
pub struct NoEffectPass ;
impl LintPass for NoEffectPass {
fn get_lints ( & self ) -> LintArray {
lint_array! ( NO_EFFECT )
}
}
impl LateLintPass for NoEffectPass {
fn check_stmt ( & mut self , cx : & LateContext , stmt : & Stmt ) {
if let StmtSemi ( ref expr , _ ) = stmt . node {
if has_no_effect ( cx , expr ) {
2016-01-04 04:26:12 +00:00
span_lint ( cx , NO_EFFECT , stmt . span , " statement with no effect " ) ;
2015-10-28 16:50:00 +00:00
}
}
}
}