From 9ebcd0bf29b00226d83a1bb8b48ee9872cb67848 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 27 Aug 2015 04:01:35 +0530 Subject: [PATCH 1/2] More macro checks --- src/identity_op.rs | 3 ++- src/matches.rs | 4 +++- src/returns.rs | 4 +++- src/types.rs | 11 ++++------- src/utils.rs | 11 ++++++++++- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/identity_op.rs b/src/identity_op.rs index cd7d6351c80..bcdd527e407 100644 --- a/src/identity_op.rs +++ b/src/identity_op.rs @@ -4,7 +4,7 @@ use consts::{constant, is_negative}; use consts::Constant::ConstantInt; -use utils::{span_lint, snippet}; +use utils::{span_lint, snippet, in_external_macro}; declare_lint! { pub IDENTITY_OP, Warn, "using identity operations, e.g. `x + 0` or `y / 1`" } @@ -53,6 +53,7 @@ fn check(cx: &Context, e: &Expr, m: i8, span: Span, arg: Span) { 1 => !is_negative(ty) && v == 1, _ => unreachable!(), } { + if in_external_macro(cx, e.span) {return;} span_lint(cx, IDENTITY_OP, span, &format!( "the operation is ineffective. Consider reducing it to `{}`", snippet(cx, arg, ".."))); diff --git a/src/matches.rs b/src/matches.rs index d1c74daf2cd..1afb61e9b9e 100644 --- a/src/matches.rs +++ b/src/matches.rs @@ -3,7 +3,8 @@ use syntax::ast::*; use std::borrow::Cow; -use utils::{snippet, snippet_block, span_lint, span_help_and_lint}; +use utils::{snippet, snippet_block}; +use utils::{span_lint, span_help_and_lint, in_external_macro}; declare_lint!(pub SINGLE_MATCH, Warn, "a match statement with a single nontrivial arm (i.e, where the other arm \ @@ -36,6 +37,7 @@ fn check_expr(&mut self, cx: &Context, expr: &Expr) { // finally, we don't want any content in the second arm (unit or empty block) is_unit_expr(&arms[1].body) { + if in_external_macro(cx, expr.span) {return;} let body_code = snippet_block(cx, arms[0].body.span, ".."); let body_code = if let ExprBlock(_) = arms[0].body.node { body_code diff --git a/src/returns.rs b/src/returns.rs index e4b14c22115..29749b29435 100644 --- a/src/returns.rs +++ b/src/returns.rs @@ -3,7 +3,7 @@ use syntax::codemap::{Span, Spanned}; use syntax::visit::FnKind; -use utils::{span_lint, snippet, match_path}; +use utils::{span_lint, snippet, match_path, in_external_macro}; declare_lint!(pub NEEDLESS_RETURN, Warn, "using a return statement like `return expr;` where an expression would suffice"); @@ -58,6 +58,7 @@ fn check_final_expr(&mut self, cx: &Context, expr: &Expr) { } fn emit_return_lint(&mut self, cx: &Context, spans: (Span, Span)) { + if in_external_macro(cx, spans.1) {return;} span_lint(cx, NEEDLESS_RETURN, spans.0, &format!( "unneeded return statement. Consider using `{}` \ without the return and trailing semicolon", @@ -84,6 +85,7 @@ fn check_let_return(&mut self, cx: &Context, block: &Block) { } fn emit_let_lint(&mut self, cx: &Context, lint_span: Span, note_span: Span) { + if in_external_macro(cx, note_span) {return;} span_lint(cx, LET_AND_RETURN, lint_span, "returning the result of a let binding. \ Consider returning the expression directly."); diff --git a/src/types.rs b/src/types.rs index 700666d0542..12f31ae89dd 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,9 +5,8 @@ use syntax::codemap::Span; use syntax::visit::{FnKind, Visitor, walk_ty}; use rustc::middle::ty; -use syntax::codemap::ExpnInfo; -use utils::{in_macro, match_type, snippet, span_lint, span_help_and_lint, in_external_macro}; +use utils::{match_type, snippet, span_lint, span_help_and_lint, in_external_macro}; use utils::{LL_PATH, VEC_PATH}; /// Handles all the linting of funky types @@ -55,11 +54,11 @@ fn check_ty(&mut self, cx: &Context, ast_ty: &ast::Ty) { "creating a let binding to a value of unit type, which usually can't be used afterwards"); -fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) { - if in_macro(cx, info) { return; } +fn check_let_unit(cx: &Context, decl: &Decl) { if let DeclLocal(ref local) = decl.node { let bindtype = &cx.tcx.pat_ty(&local.pat).sty; if *bindtype == ty::TyTuple(vec![]) { + if in_external_macro(cx, decl.span) { return; } span_lint(cx, LET_UNIT_VALUE, decl.span, &format!( "this let-binding has unit value. Consider omitting `let {} =`", snippet(cx, local.pat.span, ".."))); @@ -73,9 +72,7 @@ fn get_lints(&self) -> LintArray { } fn check_decl(&mut self, cx: &Context, decl: &Decl) { - cx.sess().codemap().with_expn_info( - decl.span.expn_id, - |info| check_let_unit(cx, decl, info)); + check_let_unit(cx, decl) } } diff --git a/src/utils.rs b/src/utils.rs index b7bb14bd2f0..ece1eee9050 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,6 @@ use rustc::lint::*; use syntax::ast::*; -use syntax::codemap::{ExpnInfo, Span}; +use syntax::codemap::{ExpnInfo, Span, ExpnFormat}; use rustc::ast_map::Node::NodeExpr; use rustc::middle::def_id::DefId; use rustc::middle::ty; @@ -18,6 +18,14 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { // no ExpnInfo = no macro opt_info.map_or(false, |info| { + if info.callee.format == ExpnFormat::CompilerExpansion { + if info.callee.name == "closure expansion" { + return false; + } + } else if info.callee.format == ExpnFormat::MacroAttribute { + // these are all plugins + return true; + } // no span for the callee = external macro info.callee.span.map_or(true, |span| { // no snippet = external macro or compiler-builtin expansion @@ -31,6 +39,7 @@ pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool { } /// invokes in_macro with the expansion info of the given span +/// slightly heavy, try to use this after other checks have already happened pub fn in_external_macro(cx: &Context, span: Span) -> bool { cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro(cx, info)) From 5159e034a67587bfecfd3368a9cb9691ab20e440 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 27 Aug 2015 04:40:01 +0530 Subject: [PATCH 2/2] appease the dogfood gods --- src/consts.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/consts.rs b/src/consts.rs index 1a828317fc2..29b96146db2 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,3 +1,5 @@ +#![allow(cast_possible_truncation)] + use rustc::lint::Context; use rustc::middle::const_eval::lookup_const_by_id; use rustc::middle::def::PathResolution;