Skip to content

WIP: rustup #1373

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Dec 17, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Change Log
All notable changes to this project will be documented in this file.

## 0.0.104 — 2016-12-15
* Update to *rustc 1.15.0-nightly (8f02c429a 2016-12-15)*

## 0.0.103 — 2016-11-25
* Update to *rustc 1.15.0-nightly (d5814b03e 2016-11-23)*

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "clippy"
version = "0.0.103"
version = "0.0.104"
authors = [
"Manish Goregaokar <[email protected]>",
"Andre Bogus <[email protected]>",
@@ -25,7 +25,7 @@ test = false

[dependencies]
# begin automatic update
clippy_lints = { version = "0.0.103", path = "clippy_lints" }
clippy_lints = { version = "0.0.104", path = "clippy_lints" }
# end automatic update

[dev-dependencies]
2 changes: 1 addition & 1 deletion clippy_lints/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "clippy_lints"
# begin automatic update
version = "0.0.103"
version = "0.0.104"
# end automatic update
authors = [
"Manish Goregaokar <[email protected]>",
4 changes: 2 additions & 2 deletions clippy_lints/src/approx_const.rs
Original file line number Diff line number Diff line change
@@ -59,8 +59,8 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprLit(ref lit) = e.node {
check_lit(cx, lit, e);
}
6 changes: 3 additions & 3 deletions clippy_lints/src/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -47,8 +47,8 @@ impl LintPass for Arithmetic {
}
}

impl LateLintPass for Arithmetic {
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
if self.span.is_some() {
return;
}
@@ -82,7 +82,7 @@ impl LateLintPass for Arithmetic {
}
}

fn check_expr_post(&mut self, _: &LateContext, expr: &hir::Expr) {
fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
if Some(expr.span) == self.span {
self.span = None;
}
4 changes: 2 additions & 2 deletions clippy_lints/src/array_indexing.rs
Original file line number Diff line number Diff line change
@@ -55,8 +55,8 @@ impl LintPass for ArrayIndexing {
}
}

impl LateLintPass for ArrayIndexing {
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
if let hir::ExprIndex(ref array, ref index) = e.node {
// Array with known size can be checked statically
let ty = cx.tcx.tables().expr_ty(array);
4 changes: 2 additions & 2 deletions clippy_lints/src/assign_ops.rs
Original file line number Diff line number Diff line change
@@ -66,8 +66,8 @@ impl LintPass for AssignOps {
}
}

impl LateLintPass for AssignOps {
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
match expr.node {
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
26 changes: 13 additions & 13 deletions clippy_lints/src/attrs.rs
Original file line number Diff line number Diff line change
@@ -81,8 +81,8 @@ impl LintPass for AttrPass {
}
}

impl LateLintPass for AttrPass {
fn check_attribute(&mut self, cx: &LateContext, attr: &Attribute) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) {
if let MetaItemKind::List(ref items) = attr.value.node {
if items.is_empty() || attr.name() != "deprecated" {
return;
@@ -99,21 +99,21 @@ impl LateLintPass for AttrPass {
}
}

fn check_item(&mut self, cx: &LateContext, item: &Item) {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if is_relevant_item(cx, item) {
check_attrs(cx, item.span, &item.name, &item.attrs)
}
match item.node {
ItemExternCrate(_) |
ItemUse(_) => {
ItemUse(_, _) => {
for attr in &item.attrs {
if let MetaItemKind::List(ref lint_list) = attr.value.node {
match &*attr.name().as_str() {
"allow" | "warn" | "deny" | "forbid" => {
// whitelist `unused_imports`
for lint in lint_list {
if is_word(lint, "unused_imports") {
if let ItemUse(_) = item.node {
if let ItemUse(_, _) = item.node {
return;
}
}
@@ -138,38 +138,38 @@ impl LateLintPass for AttrPass {
}
}

fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
if is_relevant_impl(cx, item) {
check_attrs(cx, item.span, &item.name, &item.attrs)
}
}

fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
if is_relevant_trait(cx, item) {
check_attrs(cx, item.span, &item.name, &item.attrs)
}
}
}

fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
if let ItemFn(_, _, _, _, _, ref expr) = item.node {
is_relevant_expr(cx, expr)
if let ItemFn(_, _, _, _, _, eid) = item.node {
is_relevant_expr(cx, cx.tcx.map.expr(eid))
} else {
false
}
}

fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
match item.node {
ImplItemKind::Method(_, ref expr) => is_relevant_expr(cx, expr),
ImplItemKind::Method(_, eid) => is_relevant_expr(cx, cx.tcx.map.expr(eid)),
_ => false,
}
}

fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool {
match item.node {
MethodTraitItem(_, None) => true,
MethodTraitItem(_, Some(ref expr)) => is_relevant_expr(cx, expr),
MethodTraitItem(_, Some(eid)) => is_relevant_expr(cx, cx.tcx.map.expr(eid)),
_ => false,
}
}
@@ -193,8 +193,8 @@ fn is_relevant_expr(cx: &LateContext, expr: &Expr) -> bool {
ExprRet(Some(ref e)) => is_relevant_expr(cx, e),
ExprRet(None) | ExprBreak(_, None) => false,
ExprCall(ref path_expr, _) => {
if let ExprPath(..) = path_expr.node {
let fun_id = resolve_node(cx, path_expr.id).expect("function should be resolved").def_id();
if let ExprPath(ref qpath) = path_expr.node {
let fun_id = resolve_node(cx, qpath, path_expr.id).def_id();
!match_def_path(cx, fun_id, &paths::BEGIN_PANIC)
} else {
true
23 changes: 9 additions & 14 deletions clippy_lints/src/bit_mask.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc::hir::*;
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def::Def;
use rustc::lint::*;
use rustc_const_eval::lookup_const_by_id;
use syntax::ast::LitKind;
@@ -79,8 +79,8 @@ impl LintPass for BitMask {
}
}

impl LateLintPass for BitMask {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BitMask {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
if cmp.node.is_comparison() {
if let Some(cmp_opt) = fetch_int_literal(cx, right) {
@@ -245,18 +245,13 @@ fn fetch_int_literal(cx: &LateContext, lit: &Expr) -> Option<u64> {
None
}
}
ExprPath(_, _) => {
{
// Important to let the borrow expire before the const lookup to avoid double
// borrowing.
let def_map = cx.tcx.def_map.borrow();
match def_map.get(&lit.id) {
Some(&PathResolution { base_def: Def::Const(def_id), .. }) => Some(def_id),
_ => None,
}
ExprPath(ref qpath) => {
let def = cx.tcx.tables().qpath_def(qpath, lit.id);
if let Def::Const(def_id) = def {
lookup_const_by_id(cx.tcx, def_id, None).and_then(|(l, _ty)| fetch_int_literal(cx, l))
} else {
None
}
.and_then(|def_id| lookup_const_by_id(cx.tcx, def_id, None))
.and_then(|(l, _ty)| fetch_int_literal(cx, l))
}
_ => None,
}
6 changes: 3 additions & 3 deletions clippy_lints/src/blacklisted_name.rs
Original file line number Diff line number Diff line change
@@ -37,9 +37,9 @@ impl LintPass for BlackListedName {
}
}

impl LateLintPass for BlackListedName {
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
if let PatKind::Binding(_, ref ident, _) = pat.node {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName {
fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
if let PatKind::Binding(_, _, ref ident, _) = pat.node {
if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) {
span_lint(cx,
BLACKLISTED_NAME,
23 changes: 14 additions & 9 deletions clippy_lints/src/block_in_if_condition.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass};
use rustc::hir::*;
use rustc::hir::intravisit::{Visitor, walk_expr};
use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap};
use utils::*;

/// **What it does:** Checks for `if` conditions that use blocks to contain an
@@ -49,28 +49,33 @@ impl LintPass for BlockInIfCondition {
}
}

struct ExVisitor<'v> {
found_block: Option<&'v Expr>,
struct ExVisitor<'a, 'tcx: 'a> {
found_block: Option<&'tcx Expr>,
cx: &'a LateContext<'a, 'tcx>,
}

impl<'v> Visitor<'v> for ExVisitor<'v> {
fn visit_expr(&mut self, expr: &'v Expr) {
if let ExprClosure(_, _, ref expr, _) = expr.node {
impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr) {
if let ExprClosure(_, _, eid, _) = expr.node {
let expr = self.cx.tcx.map.expr(eid);
if matches!(expr.node, ExprBlock(_)) {
self.found_block = Some(expr);
return;
}
}
walk_expr(self, expr);
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::All(&self.cx.tcx.map)
}
}

const BRACED_EXPR_MESSAGE: &'static str = "omit braces around single expression condition";
const COMPLEX_BLOCK_MESSAGE: &'static str = "in an 'if' condition, avoid complex blocks or closures with blocks; \
instead, move the block or closure higher and bind it with a 'let'";

impl LateLintPass for BlockInIfCondition {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprIf(ref check, ref then, _) = expr.node {
if let ExprBlock(ref block) = check.node {
if block.rules == DefaultBlock {
@@ -105,7 +110,7 @@ impl LateLintPass for BlockInIfCondition {
}
}
} else {
let mut visitor = ExVisitor { found_block: None };
let mut visitor = ExVisitor { found_block: None, cx: cx };
walk_expr(&mut visitor, check);
if let Some(block) = visitor.found_block {
span_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE);
31 changes: 18 additions & 13 deletions clippy_lints/src/booleans.rs
Original file line number Diff line number Diff line change
@@ -53,13 +53,15 @@ impl LintPass for NonminimalBool {
}
}

impl LateLintPass for NonminimalBool {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
NonminimalBoolVisitor(cx).visit_item(item)
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonminimalBool {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
NonminimalBoolVisitor { cx: cx }.visit_item(item)
}
}

struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);
struct NonminimalBoolVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>,
}

use quine_mc_cluskey::Bool;
struct Hir2Qmm<'a, 'tcx: 'a, 'v> {
@@ -308,7 +310,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
fn bool_expr(&self, e: &Expr) {
let mut h2q = Hir2Qmm {
terminals: Vec::new(),
cx: self.0,
cx: self.cx,
};
if let Ok(expr) = h2q.run(e) {

@@ -343,7 +345,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
continue 'simplified;
}
if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 {
span_lint_and_then(self.0,
span_lint_and_then(self.cx,
LOGIC_BUG,
e.span,
"this boolean expression contains a logic bug",
@@ -353,7 +355,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
outer expression");
db.span_suggestion(e.span,
"it would look like the following",
suggest(self.0, suggestion, &h2q.terminals));
suggest(self.cx, suggestion, &h2q.terminals));
});
// don't also lint `NONMINIMAL_BOOL`
return;
@@ -370,29 +372,29 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
}
}
if !improvements.is_empty() {
span_lint_and_then(self.0,
span_lint_and_then(self.cx,
NONMINIMAL_BOOL,
e.span,
"this boolean expression can be simplified",
|db| {
for suggestion in &improvements {
db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals));
db.span_suggestion(e.span, "try", suggest(self.cx, suggestion, &h2q.terminals));
}
});
}
}
}
}

impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'v Expr) {
if in_macro(self.0, e.span) {
impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr) {
if in_macro(self.cx, e.span) {
return;
}
match e.node {
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
ExprUnary(UnNot, ref inner) => {
if self.0.tcx.tables.borrow().node_types[&inner.id].is_bool() {
if self.cx.tcx.tables.borrow().node_types[&inner.id].is_bool() {
self.bool_expr(e);
} else {
walk_expr(self, e);
@@ -401,4 +403,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
_ => walk_expr(self, e),
}
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::All(&self.cx.tcx.map)
}
}
33 changes: 17 additions & 16 deletions clippy_lints/src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(cast_possible_truncation)]

use rustc::lint::LateContext;
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def::Def;
use rustc_const_eval::lookup_const_by_id;
use rustc_const_math::{ConstInt, ConstUsize, ConstIsize};
use rustc::hir::*;
@@ -10,7 +10,7 @@ use std::cmp::PartialOrd;
use std::hash::{Hash, Hasher};
use std::mem;
use std::rc::Rc;
use syntax::ast::{FloatTy, LitIntType, LitKind, StrStyle, UintTy, IntTy};
use syntax::ast::{FloatTy, LitIntType, LitKind, StrStyle, UintTy, IntTy, NodeId};
use syntax::ptr::P;

#[derive(Debug, Copy, Clone)]
@@ -252,7 +252,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
/// simple constant folding: Insert an expression, get a constant or none.
fn expr(&mut self, e: &Expr) -> Option<Constant> {
match e.node {
ExprPath(_, _) => self.fetch_path(e),
ExprPath(ref qpath) => self.fetch_path(qpath, e.id),
ExprBlock(ref block) => self.block(block),
ExprIf(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, otherwise),
ExprLit(ref lit) => Some(lit_to_constant(&lit.node)),
@@ -285,21 +285,22 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
}

/// lookup a possibly constant expression from a ExprPath
fn fetch_path(&mut self, e: &Expr) -> Option<Constant> {
fn fetch_path(&mut self, qpath: &QPath, id: NodeId) -> Option<Constant> {
if let Some(lcx) = self.lcx {
let mut maybe_id = None;
if let Some(&PathResolution { base_def: Def::Const(id), .. }) = lcx.tcx.def_map.borrow().get(&e.id) {
maybe_id = Some(id);
}
// separate if lets to avoid double borrowing the def_map
if let Some(id) = maybe_id {
if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, id, None) {
let ret = self.expr(const_expr);
if ret.is_some() {
self.needed_resolution = true;
let def = lcx.tcx.tables().qpath_def(qpath, id);
match def {
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
let substs = Some(lcx.tcx.tables().node_id_item_substs(id)
.unwrap_or_else(|| lcx.tcx.intern_substs(&[])));
if let Some((const_expr, _ty)) = lookup_const_by_id(lcx.tcx, def_id, substs) {
let ret = self.expr(const_expr);
if ret.is_some() {
self.needed_resolution = true;
}
return ret;
}
return ret;
}
},
_ => {},
}
}
None
6 changes: 3 additions & 3 deletions clippy_lints/src/copies.rs
Original file line number Diff line number Diff line change
@@ -109,8 +109,8 @@ impl LintPass for CopyAndPaste {
}
}

impl LateLintPass for CopyAndPaste {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if !in_macro(cx, expr.span) {
// skip ifs directly in else, it will be checked in the parent if
if let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) {
@@ -254,7 +254,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> HashMap<Interned
bindings_impl(cx, pat, map);
}
}
PatKind::Binding(_, ref ident, ref as_pat) => {
PatKind::Binding(_, _, ref ident, ref as_pat) => {
if let Entry::Vacant(v) = map.entry(ident.node.as_str()) {
v.insert(cx.tcx.tables().pat_ty(pat));
}
45 changes: 24 additions & 21 deletions clippy_lints/src/cyclomatic_complexity.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ use rustc::cfg::CFG;
use rustc::lint::*;
use rustc::ty;
use rustc::hir::*;
use rustc::hir::intravisit::{Visitor, walk_expr};
use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap};
use syntax::ast::Attribute;
use syntax::attr;
use syntax::codemap::Span;
@@ -42,7 +42,7 @@ impl LintPass for CyclomaticComplexity {
}

impl CyclomaticComplexity {
fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, expr: &Expr, span: Span) {
fn check<'a, 'tcx: 'a>(&mut self, cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr, span: Span) {
if in_macro(cx, span) {
return;
}
@@ -60,7 +60,7 @@ impl CyclomaticComplexity {
divergence: 0,
short_circuits: 0,
returns: 0,
tcx: &cx.tcx,
cx: cx,
};
helper.visit_expr(expr);
let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper;
@@ -90,45 +90,45 @@ impl CyclomaticComplexity {
}
}

impl LateLintPass for CyclomaticComplexity {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
if let ItemFn(_, _, _, _, _, ref expr) = item.node {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CyclomaticComplexity {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(_, _, _, _, _, eid) = item.node {
if !attr::contains_name(&item.attrs, "test") {
self.check(cx, expr, item.span);
self.check(cx, cx.tcx.map.expr(eid), item.span);
}
}
}

fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
if let ImplItemKind::Method(_, ref expr) = item.node {
self.check(cx, expr, item.span);
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
if let ImplItemKind::Method(_, eid) = item.node {
self.check(cx, cx.tcx.map.expr(eid), item.span);
}
}

fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
if let MethodTraitItem(_, Some(ref expr)) = item.node {
self.check(cx, expr, item.span);
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
if let MethodTraitItem(_, Some(eid)) = item.node {
self.check(cx, cx.tcx.map.expr(eid), item.span);
}
}

fn enter_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) {
fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) {
self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity");
}
fn exit_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) {
fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) {
self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity");
}
}

struct CCHelper<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
struct CCHelper<'a, 'tcx: 'a> {
match_arms: u64,
divergence: u64,
returns: u64,
short_circuits: u64, // && and ||
tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>,
cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> {
fn visit_expr(&mut self, e: &'a Expr) {
impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprMatch(_, ref arms, _) => {
walk_expr(self, e);
@@ -139,10 +139,10 @@ impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> {
}
ExprCall(ref callee, _) => {
walk_expr(self, e);
let ty = self.tcx.tables().node_id_to_type(callee.id);
let ty = self.cx.tcx.tables().node_id_to_type(callee.id);
match ty.sty {
ty::TyFnDef(_, _, ty) |
ty::TyFnPtr(ty) if ty.sig.skip_binder().output.sty == ty::TyNever => {
ty::TyFnPtr(ty) if ty.sig.skip_binder().output().sty == ty::TyNever => {
self.divergence += 1;
}
_ => (),
@@ -160,6 +160,9 @@ impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> {
_ => walk_expr(self, e),
}
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}
}

#[cfg(feature="debugging")]
12 changes: 6 additions & 6 deletions clippy_lints/src/derive.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ use rustc::ty;
use rustc::hir::*;
use syntax::codemap::Span;
use utils::paths;
use utils::{is_automatically_derived, match_path, span_lint_and_then};
use utils::{is_automatically_derived, span_lint_and_then, match_path_old};

/// **What it does:** Checks for deriving `Hash` but implementing `PartialEq`
/// explicitly.
@@ -70,8 +70,8 @@ impl LintPass for Derive {
}
}

impl LateLintPass for Derive {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Derive {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
let ty = cx.tcx.item_type(cx.tcx.map.local_def_id(item.id));
let is_automatically_derived = is_automatically_derived(&*item.attrs);
@@ -86,10 +86,10 @@ impl LateLintPass for Derive {
}

/// Implementation of the `DERIVE_HASH_XOR_EQ` lint.
fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>,
fn check_hash_peq<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, trait_ref: &TraitRef, ty: ty::Ty<'tcx>,
hash_is_automatically_derived: bool) {
if_let_chain! {[
match_path(&trait_ref.path, &paths::HASH),
match_path_old(&trait_ref.path, &paths::HASH),
let Some(peq_trait_def_id) = cx.tcx.lang_items.eq_trait()
], {
let peq_trait_def = cx.tcx.lookup_trait_def(peq_trait_def_id);
@@ -131,7 +131,7 @@ fn check_hash_peq<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, span: Span, trait_re

/// Implementation of the `EXPL_IMPL_CLONE_ON_COPY` lint.
fn check_copy_clone<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, item: &Item, trait_ref: &TraitRef, ty: ty::Ty<'tcx>) {
if match_path(&trait_ref.path, &paths::CLONE_TRAIT) {
if match_path_old(&trait_ref.path, &paths::CLONE_TRAIT) {
let parameter_environment = ty::ParameterEnvironment::for_item(cx.tcx, item.id);
let subst_ty = ty.subst(cx.tcx, parameter_environment.free_substs);

8 changes: 4 additions & 4 deletions clippy_lints/src/drop_ref.rs
Original file line number Diff line number Diff line change
@@ -35,11 +35,11 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprCall(ref path, ref args) = expr.node {
if let ExprPath(None, _) = path.node {
let def_id = cx.tcx.expect_def(path.id).def_id();
if let ExprPath(ref qpath) = path.node {
let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();
if match_def_path(cx, def_id, &paths::DROP) {
if args.len() != 1 {
return;
13 changes: 8 additions & 5 deletions clippy_lints/src/entry.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc::hir::*;
use rustc::hir::intravisit::{Visitor, walk_expr, walk_block};
use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, NestedVisitorMap};
use rustc::lint::*;
use syntax::codemap::Span;
use utils::SpanlessEq;
@@ -39,8 +39,8 @@ impl LintPass for HashMapLint {
}
}

impl LateLintPass for HashMapLint {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprIf(ref check, ref then_block, ref else_block) = expr.node {
if let ExprUnary(UnOp::UnNot, ref check) = check.node {
if let Some((ty, map, key)) = check_cond(cx, check) {
@@ -111,8 +111,8 @@ struct InsertVisitor<'a, 'tcx: 'a, 'b> {
sole_expr: bool,
}

impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> {
fn visit_expr(&mut self, expr: &'v Expr) {
impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
fn visit_expr(&mut self, expr: &'tcx Expr) {
if_let_chain! {[
let ExprMethodCall(ref name, _, ref params) = expr.node,
params.len() == 3,
@@ -144,4 +144,7 @@ impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> {
walk_expr(self, expr);
}
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::All(&self.cx.tcx.map)
}
}
4 changes: 2 additions & 2 deletions clippy_lints/src/enum_clike.rs
Original file line number Diff line number Diff line change
@@ -36,9 +36,9 @@ impl LintPass for UnportableVariant {
}
}

impl LateLintPass for UnportableVariant {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant {
#[allow(cast_possible_truncation, cast_sign_loss)]
fn check_item(&mut self, cx: &LateContext, item: &Item) {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemEnum(ref def, _) = item.node {
for var in &def.variants {
let variant = &var.node;
32 changes: 9 additions & 23 deletions clippy_lints/src/enum_glob_use.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
//! lint on `use`ing all variants of an enum
use rustc::hir::*;
use rustc::hir::def::Def;
use rustc::hir::map::Node::NodeItem;
use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray, LintContext};
use rustc::lint::{LateLintPass, LintPass, LateContext, LintArray};
use syntax::ast::NodeId;
use syntax::codemap::Span;
use utils::span_lint;
@@ -34,8 +32,8 @@ impl LintPass for EnumGlobUse {
}
}

impl LateLintPass for EnumGlobUse {
fn check_mod(&mut self, cx: &LateContext, m: &Mod, _: Span, _: NodeId) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse {
fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: NodeId) {
// only check top level `use` statements
for item in &m.item_ids {
self.lint_item(cx, cx.krate.item(item.id));
@@ -48,24 +46,12 @@ impl EnumGlobUse {
if item.vis == Visibility::Public {
return; // re-exports are fine
}
if let ItemUse(ref item_use) = item.node {
if let ViewPath_::ViewPathGlob(_) = item_use.node {
if let Some(def) = cx.tcx.def_map.borrow().get(&item.id) {
if let Some(node_id) = cx.tcx.map.as_local_node_id(def.full_def().def_id()) {
if let Some(NodeItem(it)) = cx.tcx.map.find(node_id) {
if let ItemEnum(..) = it.node {
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
}
}
} else {
let child = cx.sess().cstore.item_children(def.full_def().def_id());
if let Some(child) = child.first() {
if let Def::Variant(..) = child.def {
span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
}
}
}
}
if let ItemUse(ref path, UseKind::Glob) = item.node {
// FIXME: ask jseyfried why the qpath.def for `use std::cmp::Ordering::*;`
// extracted through `ItemUse(ref qpath, UseKind::Glob)` is a `Mod` and not an `Enum`
//if let Def::Enum(_) = path.def {
if path.segments.last().and_then(|seg| seg.name.as_str().chars().next()).map_or(false, char::is_uppercase) {
Copy link
Member

@mcarton mcarton Dec 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you had an answer for that?

span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants");
}
}
}
4 changes: 2 additions & 2 deletions clippy_lints/src/eq_op.rs
Original file line number Diff line number Diff line change
@@ -32,8 +32,8 @@ impl LintPass for EqOp {
}
}

impl LateLintPass for EqOp {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprBinary(ref op, ref left, ref right) = e.node {
if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) {
span_lint(cx,
12 changes: 10 additions & 2 deletions clippy_lints/src/escape.rs
Original file line number Diff line number Diff line change
@@ -60,8 +60,16 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Expr, _: Span, id: NodeId) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_fn(
&mut self,
cx: &LateContext<'a, 'tcx>,
_: visit::FnKind<'tcx>,
decl: &'tcx FnDecl,
body: &'tcx Expr,
_: Span,
id: NodeId,
) {
let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id);

let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env);
13 changes: 7 additions & 6 deletions clippy_lints/src/eta_reduction.rs
Original file line number Diff line number Diff line change
@@ -33,8 +33,8 @@ impl LintPass for EtaPass {
}
}

impl LateLintPass for EtaPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
match expr.node {
ExprCall(_, ref args) |
ExprMethodCall(_, _, ref args) => {
@@ -48,7 +48,8 @@ impl LateLintPass for EtaPass {
}

fn check_closure(cx: &LateContext, expr: &Expr) {
if let ExprClosure(_, ref decl, ref ex, _) = expr.node {
if let ExprClosure(_, ref decl, eid, _) = expr.node {
let ex = cx.tcx.map.expr(eid);
if let ExprCall(ref caller, ref args) = ex.node {
if args.len() != decl.inputs.len() {
// Not the same number of arguments, there
@@ -65,16 +66,16 @@ fn check_closure(cx: &LateContext, expr: &Expr) {
ty::TyFnDef(_, _, fn_ty) |
ty::TyFnPtr(fn_ty) => {
if fn_ty.unsafety == Unsafety::Unsafe ||
fn_ty.sig.skip_binder().output.sty == ty::TyNever {
fn_ty.sig.skip_binder().output().sty == ty::TyNever {
return;
}
}
_ => (),
}
for (a1, a2) in decl.inputs.iter().zip(args) {
if let PatKind::Binding(_, ident, _) = a1.pat.node {
if let PatKind::Binding(_, _, ident, _) = a1.pat.node {
// XXXManishearth Should I be checking the binding mode here?
if let ExprPath(None, ref p) = a2.node {
if let ExprPath(QPath::Resolved(None, ref p)) = a2.node {
if p.segments.len() != 1 {
// If it's a proper path, it can't be a local variable
return;
106 changes: 59 additions & 47 deletions clippy_lints/src/eval_order_dependence.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{Visitor, walk_expr};
use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap};
use rustc::hir::*;
use rustc::ty;
use rustc::lint::*;
@@ -56,45 +56,49 @@ impl LintPass for EvalOrderDependence {
}
}

impl LateLintPass for EvalOrderDependence {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EvalOrderDependence {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
// Find a write to a local variable.
match expr.node {
ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => {
if let ExprPath(None, ref path) = lhs.node {
if path.segments.len() == 1 {
let var = cx.tcx.expect_def(lhs.id).def_id();
let mut visitor = ReadVisitor {
cx: cx,
var: var,
write_expr: expr,
last_expr: expr,
};
check_for_unsequenced_reads(&mut visitor);
if let ExprPath(ref qpath) = lhs.node {
if let QPath::Resolved(_, ref path) = *qpath {
if path.segments.len() == 1 {
let var = cx.tcx.tables().qpath_def(qpath, lhs.id).def_id();
let mut visitor = ReadVisitor {
cx: cx,
var: var,
write_expr: expr,
last_expr: expr,
};
check_for_unsequenced_reads(&mut visitor);
}
}
}
}
_ => {}
}
}
fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) {
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
match stmt.node {
StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor(cx).maybe_walk_expr(e),
StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor { cx: cx }.maybe_walk_expr(e),
StmtDecl(ref d, _) => {
if let DeclLocal(ref local) = d.node {
if let Local { init: Some(ref e), .. } = **local {
DivergenceVisitor(cx).visit_expr(e);
DivergenceVisitor { cx: cx }.visit_expr(e);
}
}
},
}
}
}

struct DivergenceVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);
struct DivergenceVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
fn maybe_walk_expr(&mut self, e: &Expr) {
fn maybe_walk_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprClosure(..) => {},
ExprMatch(ref e, ref arms, _) => {
@@ -112,33 +116,33 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
}
fn report_diverging_sub_expr(&mut self, e: &Expr) {
span_lint(
self.0,
self.cx,
DIVERGING_SUB_EXPRESSION,
e.span,
"sub-expression diverges",
);
}
}

impl<'a, 'tcx, 'v> Visitor<'v> for DivergenceVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'v Expr) {
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprAgain(_) |
ExprBreak(_, _) |
ExprRet(_) => self.report_diverging_sub_expr(e),
ExprCall(ref func, _) => match self.0.tcx.tables().expr_ty(func).sty {
ExprCall(ref func, _) => match self.cx.tcx.tables().expr_ty(func).sty {
ty::TyFnDef(_, _, fn_ty) |
ty::TyFnPtr(fn_ty) => if let ty::TyNever = self.0.tcx.erase_late_bound_regions(&fn_ty.sig).output.sty {
ty::TyFnPtr(fn_ty) => if let ty::TyNever = self.cx.tcx.erase_late_bound_regions(&fn_ty.sig).output().sty {
self.report_diverging_sub_expr(e);
},
_ => {},
},
ExprMethodCall(..) => {
let method_call = ty::MethodCall::expr(e.id);
let borrowed_table = self.0.tcx.tables.borrow();
let borrowed_table = self.cx.tcx.tables.borrow();
let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen.");
let result_ty = method_type.ty.fn_ret();
if let ty::TyNever = self.0.tcx.erase_late_bound_regions(&result_ty).sty {
if let ty::TyNever = self.cx.tcx.erase_late_bound_regions(&result_ty).sty {
self.report_diverging_sub_expr(e);
}
},
@@ -148,9 +152,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DivergenceVisitor<'a, 'tcx> {
}
self.maybe_walk_expr(e);
}
fn visit_block(&mut self, _: &'v Block) {
fn visit_block(&mut self, _: &'tcx Block) {
// don't continue over blocks, LateLintPass already does that
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::All(&self.cx.tcx.map)
}
}

/// Walks up the AST from the the given write expression (`vis.write_expr`)
@@ -207,7 +214,7 @@ enum StopEarly {
Stop,
}

fn check_expr<'v, 't>(vis: & mut ReadVisitor<'v, 't>, expr: &'v Expr) -> StopEarly {
fn check_expr<'a, 'tcx>(vis: & mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> StopEarly {
if expr.id == vis.last_expr.id {
return StopEarly::KeepGoing;
}
@@ -256,7 +263,7 @@ fn check_expr<'v, 't>(vis: & mut ReadVisitor<'v, 't>, expr: &'v Expr) -> StopEar
StopEarly::KeepGoing
}

fn check_stmt<'v, 't>(vis: &mut ReadVisitor<'v, 't>, stmt: &'v Stmt) -> StopEarly {
fn check_stmt<'a, 'tcx>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> StopEarly {
match stmt.node {
StmtExpr(ref expr, _) |
StmtSemi(ref expr, _) => check_expr(vis, expr),
@@ -274,38 +281,40 @@ fn check_stmt<'v, 't>(vis: &mut ReadVisitor<'v, 't>, stmt: &'v Stmt) -> StopEarl
}

/// A visitor that looks for reads from a variable.
struct ReadVisitor<'v, 't: 'v> {
cx: &'v LateContext<'v, 't>,
struct ReadVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>,
/// The id of the variable we're looking for.
var: DefId,
/// The expressions where the write to the variable occurred (for reporting
/// in the lint).
write_expr: &'v Expr,
write_expr: &'tcx Expr,
/// The last (highest in the AST) expression we've checked, so we know not
/// to recheck it.
last_expr: &'v Expr,
last_expr: &'tcx Expr,
}

impl<'v, 't> Visitor<'v> for ReadVisitor<'v, 't> {
fn visit_expr(&mut self, expr: &'v Expr) {
impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx Expr) {
if expr.id == self.last_expr.id {
return;
}

match expr.node {
ExprPath(None, ref path) => {
if path.segments.len() == 1 && self.cx.tcx.expect_def(expr.id).def_id() == self.var {
if is_in_assignment_position(self.cx, expr) {
// This is a write, not a read.
} else {
span_note_and_lint(
self.cx,
EVAL_ORDER_DEPENDENCE,
expr.span,
"unsequenced read of a variable",
self.write_expr.span,
"whether read occurs before this write depends on evaluation order"
);
ExprPath(ref qpath) => {
if let QPath::Resolved(None, ref path) = *qpath {
if path.segments.len() == 1 && self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id() == self.var {
if is_in_assignment_position(self.cx, expr) {
// This is a write, not a read.
} else {
span_note_and_lint(
self.cx,
EVAL_ORDER_DEPENDENCE,
expr.span,
"unsequenced read of a variable",
self.write_expr.span,
"whether read occurs before this write depends on evaluation order"
);
}
}
}
}
@@ -332,6 +341,9 @@ impl<'v, 't> Visitor<'v> for ReadVisitor<'v, 't> {

walk_expr(self, expr);
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::All(&self.cx.tcx.map)
}
}

/// Returns true if `expr` is the LHS of an assignment, like `expr = ...`.
14 changes: 6 additions & 8 deletions clippy_lints/src/format.rs
Original file line number Diff line number Diff line change
@@ -38,17 +38,16 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let Some(span) = is_expn_of(cx, expr.span, "format") {
match expr.node {
// `format!("{}", foo)` expansion
ExprCall(ref fun, ref args) => {
if_let_chain!{[
let ExprPath(..) = fun.node,
let ExprPath(ref qpath) = fun.node,
args.len() == 2,
let Some(fun) = resolve_node(cx, fun.id),
match_def_path(cx, fun.def_id(), &paths::FMT_ARGUMENTS_NEWV1),
match_def_path(cx, resolve_node(cx, qpath, fun.id).def_id(), &paths::FMT_ARGUMENTS_NEWV1),
// ensure the format string is `"{..}"` with only one argument and no text
check_static_str(cx, &args[0]),
// ensure the format argument is `{}` ie. Display with no fancy option
@@ -129,9 +128,8 @@ fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
exprs.len() == 1,
let ExprCall(_, ref args) = exprs[0].node,
args.len() == 2,
let ExprPath(None, _) = args[1].node,
let Some(fun) = resolve_node(cx, args[1].id),
match_def_path(cx, fun.def_id(), &paths::DISPLAY_FMT_METHOD),
let ExprPath(ref qpath) = args[1].node,
match_def_path(cx, resolve_node(cx, qpath, args[1].id).def_id(), &paths::DISPLAY_FMT_METHOD),
], {
let ty = walk_ptrs_ty(cx.tcx.tables().pat_ty(&pat[0]));

48 changes: 34 additions & 14 deletions clippy_lints/src/functions.rs
Original file line number Diff line number Diff line change
@@ -68,8 +68,16 @@ impl LintPass for Functions {
}
}

impl LateLintPass for Functions {
fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, expr: &hir::Expr, span: Span, nodeid: ast::NodeId) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
fn check_fn(
&mut self,
cx: &LateContext<'a, 'tcx>,
kind: intravisit::FnKind<'tcx>,
decl: &'tcx hir::FnDecl,
expr: &'tcx hir::Expr,
span: Span,
nodeid: ast::NodeId,
) {
use rustc::hir::map::Node::*;

let is_impl = if let Some(NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
@@ -97,21 +105,22 @@ impl LateLintPass for Functions {
self.check_raw_ptr(cx, unsafety, decl, expr, nodeid);
}

fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
if let hir::MethodTraitItem(ref sig, ref expr) = item.node {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
if let hir::MethodTraitItem(ref sig, eid) = item.node {
// don't lint extern functions decls, it's not their fault
if sig.abi == Abi::Rust {
self.check_arg_number(cx, &sig.decl, item.span);
}

if let Some(ref expr) = *expr {
if let Some(eid) = eid {
let expr = cx.tcx.map.expr(eid);
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, expr, item.id);
}
}
}
}

impl Functions {
impl<'a, 'tcx> Functions {
fn check_arg_number(&self, cx: &LateContext, decl: &hir::FnDecl, span: Span) {
let args = decl.inputs.len() as u64;
if args > self.threshold {
@@ -122,7 +131,14 @@ impl Functions {
}
}

fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, expr: &hir::Expr, nodeid: ast::NodeId) {
fn check_raw_ptr(
&self,
cx: &LateContext<'a, 'tcx>,
unsafety: hir::Unsafety,
decl: &'tcx hir::FnDecl,
expr: &'tcx hir::Expr,
nodeid: ast::NodeId,
) {
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) {
let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>();

@@ -138,9 +154,9 @@ impl Functions {
}
}

fn raw_ptr_arg(cx: &LateContext, arg: &hir::Arg) -> Option<hir::def_id::DefId> {
if let (&hir::PatKind::Binding(_, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) {
cx.tcx.def_map.borrow().get(&arg.pat.id).map(|pr| pr.full_def().def_id())
fn raw_ptr_arg(_cx: &LateContext, arg: &hir::Arg) -> Option<hir::def_id::DefId> {
if let (&hir::PatKind::Binding(_, def_id, _, _), &hir::TyPtr(_)) = (&arg.pat.node, &arg.ty.node) {
Some(def_id)
} else {
None
}
@@ -151,8 +167,8 @@ struct DerefVisitor<'a, 'tcx: 'a> {
ptrs: HashSet<hir::def_id::DefId>,
}

impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'v hir::Expr) {
impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
match expr.node {
hir::ExprCall(ref f, ref args) => {
let ty = self.cx.tcx.tables().expr_ty(f);
@@ -179,12 +195,16 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {

hir::intravisit::walk_expr(self, expr);
}
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
intravisit::NestedVisitorMap::All(&self.cx.tcx.map)
}
}

impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
fn check_arg(&self, ptr: &hir::Expr) {
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) {
if self.ptrs.contains(&def.full_def().def_id()) {
if let hir::ExprPath(ref qpath) = ptr.node {
let def = self.cx.tcx.tables().qpath_def(qpath, ptr.id);
if self.ptrs.contains(&def.def_id()) {
span_lint(self.cx,
NOT_UNSAFE_PTR_ARG_DEREF,
ptr.span,
4 changes: 2 additions & 2 deletions clippy_lints/src/identity_op.rs
Original file line number Diff line number Diff line change
@@ -31,8 +31,8 @@ impl LintPass for IdentityOp {
}
}

impl LateLintPass for IdentityOp {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if in_macro(cx, e.span) {
return;
}
6 changes: 3 additions & 3 deletions clippy_lints/src/if_let_redundant_pattern_matching.rs
Original file line number Diff line number Diff line change
@@ -42,8 +42,8 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {

if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar{..}) = expr.node {

@@ -63,7 +63,7 @@ impl LateLintPass for Pass {
}
}

PatKind::Path(_, ref path) if match_path(path, &paths::OPTION_NONE) => {
PatKind::Path(ref path) if match_path(path, &paths::OPTION_NONE) => {
"is_none()"
}

10 changes: 5 additions & 5 deletions clippy_lints/src/len_zero.rs
Original file line number Diff line number Diff line change
@@ -59,8 +59,8 @@ impl LintPass for LenZero {
}
}

impl LateLintPass for LenZero {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if in_macro(cx, item.span) {
return;
}
@@ -72,7 +72,7 @@ impl LateLintPass for LenZero {
}
}

fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if in_macro(cx, expr.span) {
return;
}
@@ -188,7 +188,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
if let ty::AssociatedKind::Method = item.kind {
if &*item.name.as_str() == "is_empty" {
let ty = cx.tcx.item_type(item.def_id).fn_sig().skip_binder();
ty.inputs.len() == 1
ty.inputs().len() == 1
} else {
false
}
@@ -208,7 +208,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {

let ty = &walk_ptrs_ty(cx.tcx.tables().expr_ty(expr));
match ty.sty {
ty::TyTrait(_) => {
ty::TyDynamic(..) => {
cx.tcx
.associated_items(ty.ty_to_def_id().expect("trait impl not found"))
.any(|item| is_is_empty(cx, &item))
44 changes: 26 additions & 18 deletions clippy_lints/src/let_if_seq.rs
Original file line number Diff line number Diff line change
@@ -57,27 +57,26 @@ impl LintPass for LetIfSeq {
}
}

impl LateLintPass for LetIfSeq {
fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) {
let mut it = block.stmts.iter().peekable();
while let Some(stmt) = it.next() {
if_let_chain! {[
let Some(expr) = it.peek(),
let hir::StmtDecl(ref decl, _) = stmt.node,
let hir::DeclLocal(ref decl) = decl.node,
let hir::PatKind::Binding(mode, ref name, None) = decl.pat.node,
let Some(def) = cx.tcx.def_map.borrow().get(&decl.pat.id),
let hir::PatKind::Binding(mode, def_id, ref name, None) = decl.pat.node,
let hir::StmtExpr(ref if_, _) = expr.node,
let hir::ExprIf(ref cond, ref then, ref else_) = if_.node,
!used_in_expr(cx, def.full_def().def_id(), cond),
let Some(value) = check_assign(cx, def.full_def().def_id(), then),
!used_in_expr(cx, def.full_def().def_id(), value),
!used_in_expr(cx, def_id, cond),
let Some(value) = check_assign(cx, def_id, then),
!used_in_expr(cx, def_id, value),
], {
let span = codemap::mk_sp(stmt.span.lo, if_.span.hi);

let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
if let hir::ExprBlock(ref else_) = else_.node {
if let Some(default) = check_assign(cx, def.full_def().def_id(), else_) {
if let Some(default) = check_assign(cx, def_id, else_) {
(else_.stmts.len() > 1, default)
} else if let Some(ref default) = decl.init {
(true, &**default)
@@ -134,29 +133,34 @@ struct UsedVisitor<'a, 'tcx: 'a> {
used: bool,
}

impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'v hir::Expr) {
impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if_let_chain! {[
let hir::ExprPath(None, _) = expr.node,
let Some(def) = self.cx.tcx.def_map.borrow().get(&expr.id),
self.id == def.full_def().def_id(),
let hir::ExprPath(ref qpath) = expr.node,
self.id == self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id(),
], {
self.used = true;
return;
}}
hir::intravisit::walk_expr(self, expr);
}
fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'tcx> {
hir::intravisit::NestedVisitorMap::All(&self.cx.tcx.map)
}
}

fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::Block) -> Option<&'e hir::Expr> {
fn check_assign<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
decl: hir::def_id::DefId,
block: &'tcx hir::Block,
) -> Option<&'tcx hir::Expr> {
if_let_chain! {[
block.expr.is_none(),
let Some(expr) = block.stmts.iter().last(),
let hir::StmtSemi(ref expr, _) = expr.node,
let hir::ExprAssign(ref var, ref value) = expr.node,
let hir::ExprPath(None, _) = var.node,
let Some(def) = cx.tcx.def_map.borrow().get(&var.id),
decl == def.full_def().def_id(),
let hir::ExprPath(ref qpath) = var.node,
decl == cx.tcx.tables().qpath_def(qpath, var.id).def_id(),
], {
let mut v = UsedVisitor {
cx: cx,
@@ -178,7 +182,11 @@ fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::
None
}

fn used_in_expr(cx: &LateContext, id: hir::def_id::DefId, expr: &hir::Expr) -> bool {
fn used_in_expr<'a, 'tcx: 'a>(
cx: &LateContext<'a, 'tcx>,
id: hir::def_id::DefId,
expr: &'tcx hir::Expr,
) -> bool {
let mut v = UsedVisitor {
cx: cx,
id: id,
3 changes: 2 additions & 1 deletion clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
#![feature(repeat_str)]

#![allow(indexing_slicing, shadow_reuse, unknown_lints, missing_docs_in_private_items)]
#![allow(needless_lifetimes)]

#[macro_use]
extern crate syntax;
@@ -256,7 +257,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold));
reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents));
reg.register_late_lint_pass(box neg_multiply::NegMultiply);
reg.register_late_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval);
reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval);
reg.register_late_lint_pass(box mem_forget::MemForget);
reg.register_late_lint_pass(box arithmetic::Arithmetic::default());
reg.register_late_lint_pass(box assign_ops::AssignOps);
102 changes: 60 additions & 42 deletions clippy_lints/src/lifetimes.rs
Original file line number Diff line number Diff line change
@@ -2,10 +2,10 @@ use reexport::*;
use rustc::lint::*;
use rustc::hir::def::Def;
use rustc::hir::*;
use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics};
use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics, NestedVisitorMap};
use std::collections::{HashSet, HashMap};
use syntax::codemap::Span;
use utils::{in_external_macro, span_lint};
use utils::{in_external_macro, span_lint, last_path_segment};

/// **What it does:** Checks for lifetime annotations which can be removed by
/// relying on lifetime elision.
@@ -56,20 +56,20 @@ impl LintPass for LifetimePass {
}
}

impl LateLintPass for LifetimePass {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node {
check_fn_inner(cx, decl, generics, item.span);
}
}

fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
if let ImplItemKind::Method(ref sig, _) = item.node {
check_fn_inner(cx, &sig.decl, &sig.generics, item.span);
}
}

fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
if let MethodTraitItem(ref sig, _) = item.node {
check_fn_inner(cx, &sig.decl, &sig.generics, item.span);
}
@@ -98,7 +98,12 @@ fn bound_lifetimes(bound: &TyParamBound) -> HirVec<&Lifetime> {
}
}

fn check_fn_inner(cx: &LateContext, decl: &FnDecl, generics: &Generics, span: Span) {
fn check_fn_inner<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
decl: &'tcx FnDecl,
generics: &'tcx Generics,
span: Span,
) {
if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) {
return;
}
@@ -116,9 +121,16 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, generics: &Generics, span: Sp
report_extra_lifetimes(cx, decl, generics);
}

fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, func: &FnDecl,
named_lts: &[LifetimeDef], bounds_lts: T)
-> bool {
fn could_use_elision<
'a,
'tcx: 'a,
T: Iterator<Item = &'tcx Lifetime>
>(
cx: &LateContext<'a, 'tcx>,
func: &'tcx FnDecl,
named_lts: &'tcx [LifetimeDef],
bounds_lts: T,
) -> bool {
// There are two scenarios where elision works:
// * no output references, all input references have different LT
// * output references, exactly one input reference with same LT
@@ -210,8 +222,8 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize {
}

/// A visitor usable for `rustc_front::visit::walk_ty()`.
struct RefVisitor<'v, 't: 'v> {
cx: &'v LateContext<'v, 't>,
struct RefVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>,
lts: Vec<RefLt>,
}

@@ -239,56 +251,57 @@ impl<'v, 't> RefVisitor<'v, 't> {
self.lts
}

fn collect_anonymous_lifetimes(&mut self, path: &Path, ty: &Ty) {
let last_path_segment = path.segments.last().map(|s| &s.parameters);
if let Some(&AngleBracketedParameters(ref params)) = last_path_segment {
fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) {
let last_path_segment = &last_path_segment(qpath).parameters;
if let AngleBracketedParameters(ref params) = *last_path_segment {
if params.lifetimes.is_empty() {
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ty.id).map(|r| r.full_def()) {
match def {
Def::TyAlias(def_id) |
Def::Struct(def_id) => {
let generics = self.cx.tcx.item_generics(def_id);
for _ in generics.regions.as_slice() {
self.record(&None);
}
match self.cx.tcx.tables().qpath_def(qpath, ty.id) {
Def::TyAlias(def_id) |
Def::Struct(def_id) => {
let generics = self.cx.tcx.item_generics(def_id);
for _ in generics.regions.as_slice() {
self.record(&None);
}
Def::Trait(def_id) => {
let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id];
for _ in &trait_def.generics.regions {
self.record(&None);
}
}
Def::Trait(def_id) => {
let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id];
for _ in &self.cx.tcx.item_generics(trait_def.def_id).regions {
self.record(&None);
}
_ => (),
}
_ => (),
}
}
}
}
}

impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> {
impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
self.record(&Some(*lifetime));
}

fn visit_ty(&mut self, ty: &'v Ty) {
fn visit_ty(&mut self, ty: &'tcx Ty) {
match ty.node {
TyRptr(None, _) => {
self.record(&None);
}
TyPath(_, ref path) => {
TyPath(ref path) => {
self.collect_anonymous_lifetimes(path, ty);
}
_ => (),
}
walk_ty(self, ty);
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}
}

/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to
/// reason about elision.
fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool {
fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: &'tcx WhereClause) -> bool {
for predicate in &where_clause.predicates {
match *predicate {
WherePredicate::RegionPredicate(..) => return true,
@@ -325,34 +338,39 @@ fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool {
false
}

struct LifetimeChecker(HashMap<Name, Span>);
struct LifetimeChecker {
map: HashMap<Name, Span>,
}

impl<'v> Visitor<'v> for LifetimeChecker {
impl<'tcx> Visitor<'tcx> for LifetimeChecker {
// for lifetimes as parameters of generics
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
self.0.remove(&lifetime.name);
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
self.map.remove(&lifetime.name);
}

fn visit_lifetime_def(&mut self, _: &'v LifetimeDef) {
fn visit_lifetime_def(&mut self, _: &'tcx LifetimeDef) {
// don't actually visit `<'a>` or `<'a: 'b>`
// we've already visited the `'a` declarations and
// don't want to spuriously remove them
// `'b` in `'a: 'b` is useless unless used elsewhere in
// a non-lifetime bound
}
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
NestedVisitorMap::None
}
}

fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics) {
fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) {
let hs = generics.lifetimes
.iter()
.map(|lt| (lt.lifetime.name, lt.lifetime.span))
.collect();
let mut checker = LifetimeChecker(hs);
let mut checker = LifetimeChecker { map: hs };

walk_generics(&mut checker, generics);
walk_fn_decl(&mut checker, func);

for &v in checker.0.values() {
for &v in checker.map.values() {
span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition");
}
}
203 changes: 124 additions & 79 deletions clippy_lints/src/loops.rs

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions clippy_lints/src/map_clone.rs
Original file line number Diff line number Diff line change
@@ -24,14 +24,14 @@ declare_lint! {
#[derive(Copy, Clone)]
pub struct Pass;

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
// call to .map()
if let ExprMethodCall(name, _, ref args) = expr.node {
if &*name.node.as_str() == "map" && args.len() == 2 {
match args[1].node {
ExprClosure(_, ref decl, ref closure_expr, _) => {
let closure_expr = remove_blocks(closure_expr);
ExprClosure(_, ref decl, closure_eid, _) => {
let closure_expr = remove_blocks(cx.tcx.map.expr(closure_eid));
if_let_chain! {[
// nothing special in the argument, besides reference bindings
// (e.g. .map(|&x| x) )
@@ -64,7 +64,7 @@ impl LateLintPass for Pass {
}
}}
}
ExprPath(_, ref path) => {
ExprPath(ref path) => {
if match_path(path, &paths::CLONE) {
let type_name = get_type_name(cx, expr, &args[0]).unwrap_or("_");
span_help_and_lint(cx,
@@ -85,7 +85,7 @@ impl LateLintPass for Pass {

fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
match expr.node {
ExprPath(None, ref path) => {
ExprPath(QPath::Resolved(None, ref path)) => {
let arg_segment = [PathSegment {
name: id,
parameters: PathParameters::none(),
@@ -108,7 +108,7 @@ fn get_type_name(cx: &LateContext, expr: &Expr, arg: &Expr) -> Option<&'static s

fn get_arg_name(pat: &Pat) -> Option<ast::Name> {
match pat.node {
PatKind::Binding(_, name, None) => Some(name.node),
PatKind::Binding(_, _, name, None) => Some(name.node),
PatKind::Ref(ref subpat, _) => get_arg_name(subpat),
_ => None,
}
8 changes: 4 additions & 4 deletions clippy_lints/src/matches.rs
Original file line number Diff line number Diff line change
@@ -129,8 +129,8 @@ impl LintPass for MatchPass {
}
}

impl LateLintPass for MatchPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if in_external_macro(cx, expr.span) {
return;
}
@@ -210,8 +210,8 @@ fn check_single_match_opt_like(cx: &LateContext, ex: &Expr, arms: &[Arm], expr:
}
path.to_string()
}
PatKind::Binding(BindByValue(MutImmutable), ident, None) => ident.node.to_string(),
PatKind::Path(None, ref path) => path.to_string(),
PatKind::Binding(BindByValue(MutImmutable), _, ident, None) => ident.node.to_string(),
PatKind::Path(ref path) => path.to_string(),
_ => return,
};

8 changes: 4 additions & 4 deletions clippy_lints/src/mem_forget.rs
Original file line number Diff line number Diff line change
@@ -27,11 +27,11 @@ impl LintPass for MemForget {
}
}

impl LateLintPass for MemForget {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemForget {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprCall(ref path_expr, ref args) = e.node {
if let ExprPath(None, _) = path_expr.node {
let def_id = cx.tcx.expect_def(path_expr.id).def_id();
if let ExprPath(ref qpath) = path_expr.node {
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
if match_def_path(cx, def_id, &paths::MEM_FORGET) {
let forgot_ty = cx.tcx.tables().expr_ty(&args[0]);

30 changes: 15 additions & 15 deletions clippy_lints/src/methods.rs
Original file line number Diff line number Diff line change
@@ -3,14 +3,16 @@ use rustc::lint::*;
use rustc::middle::const_val::ConstVal;
use rustc::middle::const_qualif::ConstQualif;
use rustc::ty;
use rustc::hir::def::Def;
use rustc_const_eval::EvalHint::ExprTypeChecked;
use rustc_const_eval::eval_const_expr_partial;
use std::borrow::Cow;
use std::fmt;
use syntax::codemap::Span;
use utils::{get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, match_path,
match_trait_method, match_type, method_chain_args, return_ty, same_tys, snippet,
span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
span_lint, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth,
last_path_segment, single_segment_path, match_def_path};
use utils::paths;
use utils::sugg;

@@ -547,11 +549,11 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
#[allow(unused_attributes)]
// ^ required because `cyclomatic_complexity` attribute shows up as unused
#[cyclomatic_complexity = "30"]
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
if in_macro(cx, expr.span) {
return;
}
@@ -627,7 +629,7 @@ impl LateLintPass for Pass {
}
}

fn check_impl_item(&mut self, cx: &LateContext, implitem: &hir::ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, implitem: &'tcx hir::ImplItem) {
if in_external_macro(cx, implitem.span) {
return;
}
@@ -701,12 +703,8 @@ fn lint_or_fun_call(cx: &LateContext, expr: &hir::Expr, name: &str, args: &[hir:
}

if name == "unwrap_or" {
if let hir::ExprPath(_, ref path) = fun.node {
let path: &str = &path.segments
.last()
.expect("A path must have at least one segment")
.name
.as_str();
if let hir::ExprPath(ref qpath) = fun.node {
let path: &str = &*last_path_segment(qpath).name.as_str();

if ["default", "new"].contains(&path) {
let arg_ty = cx.tcx.tables().expr_ty(arg);
@@ -877,8 +875,9 @@ fn lint_cstring_as_ptr(cx: &LateContext, expr: &hir::Expr, new: &hir::Expr, unwr
if_let_chain!{[
let hir::ExprCall(ref fun, ref args) = new.node,
args.len() == 1,
let hir::ExprPath(None, ref path) = fun.node,
match_path(path, &paths::CSTRING_NEW),
let hir::ExprPath(ref path) = fun.node,
let Def::Method(did) = cx.tcx.tables().qpath_def(path, fun.id),
match_def_path(cx, did, &paths::CSTRING_NEW)
], {
span_lint_and_then(cx, TEMPORARY_CSTRING_AS_PTR, expr.span,
"you are getting the inner pointer of a temporary `CString`",
@@ -1188,8 +1187,9 @@ fn lint_chars_next(cx: &LateContext, expr: &hir::Expr, chain: &hir::Expr, other:
let Some(args) = method_chain_args(chain, &["chars", "next"]),
let hir::ExprCall(ref fun, ref arg_char) = other.node,
arg_char.len() == 1,
let hir::ExprPath(None, ref path) = fun.node,
path.segments.len() == 1 && &*path.segments[0].name.as_str() == "Some"
let hir::ExprPath(ref qpath) = fun.node,
let Some(segment) = single_segment_path(qpath),
&*segment.name.as_str() == "Some"
], {
let self_ty = walk_ptrs_ty(cx.tcx.tables().expr_ty_adjusted(&args[0][0]));

@@ -1408,7 +1408,7 @@ impl OutType {
}

fn is_bool(ty: &hir::Ty) -> bool {
if let hir::TyPath(None, ref p) = ty.node {
if let hir::TyPath(ref p) = ty.node {
match_path(p, &["bool"])
} else {
false
8 changes: 4 additions & 4 deletions clippy_lints/src/minmax.rs
Original file line number Diff line number Diff line change
@@ -33,8 +33,8 @@ impl LintPass for MinMaxPass {
}
}

impl LateLintPass for MinMaxPass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MinMaxPass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) {
if let Some((inner_max, inner_c, _)) = min_max(cx, oe) {
if outer_max == inner_max {
@@ -61,8 +61,8 @@ enum MinMax {

fn min_max<'a>(cx: &LateContext, expr: &'a Expr) -> Option<(MinMax, Constant, &'a Expr)> {
if let ExprCall(ref path, ref args) = expr.node {
if let ExprPath(None, _) = path.node {
let def_id = cx.tcx.expect_def(path.id).def_id();
if let ExprPath(ref qpath) = path.node {
let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();

if match_def_path(cx, def_id, &paths::CMP_MIN) {
fetch_const(args, MinMax::Min)
38 changes: 16 additions & 22 deletions clippy_lints/src/misc.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ use rustc_const_math::ConstFloat;
use syntax::codemap::{Span, Spanned, ExpnFormat};
use utils::{
get_item_name, get_parent_expr, implements_trait, in_macro, is_integer_literal, match_path,
snippet, span_lint, span_lint_and_then, walk_ptrs_ty
snippet, span_lint, span_lint_and_then, walk_ptrs_ty, last_path_segment
};
use utils::sugg::Sugg;

@@ -166,14 +166,14 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Expr, _: Span, _: NodeId) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_fn(&mut self, cx: &LateContext<'a, 'tcx>, k: FnKind<'tcx>, decl: &'tcx FnDecl, _: &'tcx Expr, _: Span, _: NodeId) {
if let FnKind::Closure(_) = k {
// Does not apply to closures
return;
}
for arg in &decl.inputs {
if let PatKind::Binding(BindByRef(_), _, _) = arg.pat.node {
if let PatKind::Binding(BindByRef(_), _, _, _) = arg.pat.node {
span_lint(cx,
TOPLEVEL_REF_ARG,
arg.pat.span,
@@ -182,11 +182,11 @@ impl LateLintPass for Pass {
}
}

fn check_stmt(&mut self, cx: &LateContext, s: &Stmt) {
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) {
if_let_chain! {[
let StmtDecl(ref d, _) = s.node,
let DeclLocal(ref l) = d.node,
let PatKind::Binding(BindByRef(mt), i, None) = l.pat.node,
let PatKind::Binding(BindByRef(mt), _, i, None) = l.pat.node,
let Some(ref init) = l.init
], {
let init = Sugg::hir(cx, init, "..");
@@ -216,14 +216,14 @@ impl LateLintPass for Pass {
}}
}

fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
let op = cmp.node;
if op.is_comparison() {
if let ExprPath(_, ref path) = left.node {
if let ExprPath(QPath::Resolved(_, ref path)) = left.node {
check_nan(cx, path, expr.span);
}
if let ExprPath(_, ref path) = right.node {
if let ExprPath(QPath::Resolved(_, ref path)) = right.node {
check_nan(cx, path, expr.span);
}
check_to_owned(cx, left, right, true, cmp.span);
@@ -262,18 +262,14 @@ impl LateLintPass for Pass {
return;
}
let binding = match expr.node {
ExprPath(_, ref path) => {
let binding = path.segments
.last()
.expect("path should always have at least one segment")
.name
.as_str();
ExprPath(ref qpath) => {
let binding = last_path_segment(qpath).name.as_str();
if binding.starts_with('_') &&
!binding.starts_with("__") &&
&*binding != "_result" && // FIXME: #944
is_used(cx, expr) &&
// don't lint if the declaration is in a macro
non_macro_local(cx, &cx.tcx.expect_def(expr.id)) {
non_macro_local(cx, &cx.tcx.tables().qpath_def(qpath, expr.id)) {
Some(binding)
} else {
None
@@ -298,8 +294,8 @@ impl LateLintPass for Pass {
}
}

fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
if let PatKind::Binding(_, ref ident, Some(ref right)) = pat.node {
fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
if let PatKind::Binding(_, _, ref ident, Some(ref right)) = pat.node {
if right.node == PatKind::Wild {
span_lint(cx,
REDUNDANT_PATTERN,
@@ -366,7 +362,7 @@ fn check_to_owned(cx: &LateContext, expr: &Expr, other: &Expr, left: bool, op: S
}
}
ExprCall(ref path, ref v) if v.len() == 1 => {
if let ExprPath(None, ref path) = path.node {
if let ExprPath(ref path) = path.node {
if match_path(path, &["String", "from_str"]) || match_path(path, &["String", "from"]) {
(cx.tcx.tables().expr_ty(&v[0]), snippet(cx, v[0].span, ".."))
} else {
@@ -444,9 +440,7 @@ fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool {
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
match *def {
def::Def::Local(id) | def::Def::Upvar(id, _, _) => {
let id = cx.tcx.map.as_local_node_id(id).expect("That DefId should be valid");

if let Some(span) = cx.tcx.map.opt_span(id) {
if let Some(span) = cx.tcx.map.span_if_local(id) {
!in_macro(cx, span)
} else {
true
18 changes: 9 additions & 9 deletions clippy_lints/src/missing_doc.rs
Original file line number Diff line number Diff line change
@@ -94,8 +94,8 @@ impl LintPass for MissingDoc {
}
}

impl LateLintPass for MissingDoc {
fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
fn enter_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) {
let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
attr.check_name("doc") && match attr.meta_item_list() {
None => false,
@@ -105,15 +105,15 @@ impl LateLintPass for MissingDoc {
self.doc_hidden_stack.push(doc_hidden);
}

fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) {
fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) {
self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
}

fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
fn check_crate(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate) {
self.check_missing_docs_attrs(cx, &krate.attrs, krate.span, "crate");
}

fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) {
let desc = match it.node {
hir::ItemConst(..) => "a constant",
hir::ItemEnum(..) => "an enum",
@@ -134,7 +134,7 @@ impl LateLintPass for MissingDoc {
self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
}

fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem) {
let desc = match trait_item.node {
hir::ConstTraitItem(..) => "an associated constant",
hir::MethodTraitItem(..) => "a trait method",
@@ -144,7 +144,7 @@ impl LateLintPass for MissingDoc {
self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc);
}

fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) {
// If the method is an impl for a trait, don't doc.
let def_id = cx.tcx.map.local_def_id(impl_item.id);
match cx.tcx.associated_item(def_id).container {
@@ -164,13 +164,13 @@ impl LateLintPass for MissingDoc {
self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
}

fn check_struct_field(&mut self, cx: &LateContext, sf: &hir::StructField) {
fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, sf: &'tcx hir::StructField) {
if !sf.is_positional() {
self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a struct field");
}
}

fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, v: &'tcx hir::Variant, _: &hir::Generics) {
self.check_missing_docs_attrs(cx, &v.node.attrs, v.span, "a variant");
}
}
15 changes: 9 additions & 6 deletions clippy_lints/src/mut_mut.rs
Original file line number Diff line number Diff line change
@@ -31,12 +31,12 @@ impl LintPass for MutMut {
}
}

impl LateLintPass for MutMut {
fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutMut {
fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) {
intravisit::walk_block(&mut MutVisitor { cx: cx }, block);
}

fn check_ty(&mut self, cx: &LateContext, ty: &hir::Ty) {
fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx hir::Ty) {
use rustc::hir::intravisit::Visitor;

MutVisitor { cx: cx }.visit_ty(ty);
@@ -47,8 +47,8 @@ pub struct MutVisitor<'a, 'tcx: 'a> {
cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'v hir::Expr) {
impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
if in_external_macro(self.cx, expr.span) {
return;
}
@@ -74,7 +74,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {
}
}

fn visit_ty(&mut self, ty: &hir::Ty) {
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
if let hir::TyRptr(_, hir::MutTy { ty: ref pty, mutbl: hir::MutMutable }) = ty.node {
if let hir::TyRptr(_, hir::MutTy { mutbl: hir::MutMutable, .. }) = pty.node {
span_lint(self.cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible");
@@ -84,4 +84,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {

intravisit::walk_ty(self, ty);
}
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
intravisit::NestedVisitorMap::All(&self.cx.tcx.map)
}
}
8 changes: 4 additions & 4 deletions clippy_lints/src/mut_reference.rs
Original file line number Diff line number Diff line change
@@ -32,8 +32,8 @@ impl LintPass for UnnecessaryMutPassed {
}
}

impl LateLintPass for UnnecessaryMutPassed {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
let borrowed_table = cx.tcx.tables.borrow();
match e.node {
ExprCall(ref fn_expr, ref arguments) => {
@@ -42,7 +42,7 @@ impl LateLintPass for UnnecessaryMutPassed {
.expect("A function with an unknown type is called. \
If this happened, the compiler would have \
aborted the compilation long ago");
if let ExprPath(_, ref path) = fn_expr.node {
if let ExprPath(ref path) = fn_expr.node {
check_arguments(cx, arguments, function_type, &path.to_string());
}
}
@@ -60,7 +60,7 @@ fn check_arguments(cx: &LateContext, arguments: &[Expr], type_definition: &TyS,
match type_definition.sty {
TypeVariants::TyFnDef(_, _, fn_type) |
TypeVariants::TyFnPtr(fn_type) => {
let parameters = &fn_type.sig.skip_binder().inputs;
let parameters = fn_type.sig.skip_binder().inputs();
for (argument, parameter) in arguments.iter().zip(parameters.iter()) {
match parameter.sty {
TypeVariants::TyRef(_, TypeAndMut { mutbl: MutImmutable, .. }) |
4 changes: 2 additions & 2 deletions clippy_lints/src/mutex_atomic.rs
Original file line number Diff line number Diff line change
@@ -54,8 +54,8 @@ impl LintPass for MutexAtomic {

pub struct MutexAtomic;

impl LateLintPass for MutexAtomic {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutexAtomic {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
let ty = cx.tcx.tables().expr_ty(expr);
if let ty::TyAdt(_, subst) = ty.sty {
if match_type(cx, ty, &paths::MUTEX) {
8 changes: 4 additions & 4 deletions clippy_lints/src/needless_bool.rs
Original file line number Diff line number Diff line change
@@ -56,8 +56,8 @@ impl LintPass for NeedlessBool {
}
}

impl LateLintPass for NeedlessBool {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
use self::Expression::*;
if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node {
let reduce = |ret, not| {
@@ -116,8 +116,8 @@ impl LintPass for BoolComparison {
}
}

impl LateLintPass for BoolComparison {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
use self::Expression::*;
if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node {
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
8 changes: 4 additions & 4 deletions clippy_lints/src/needless_borrow.rs
Original file line number Diff line number Diff line change
@@ -34,8 +34,8 @@ impl LintPass for NeedlessBorrow {
}
}

impl LateLintPass for NeedlessBorrow {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if in_macro(cx, e.span) {
return;
}
@@ -53,11 +53,11 @@ impl LateLintPass for NeedlessBorrow {
}
}
}
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
if in_macro(cx, pat.span) {
return;
}
if let PatKind::Binding(BindingMode::BindByRef(MutImmutable), _, _) = pat.node {
if let PatKind::Binding(BindingMode::BindByRef(MutImmutable), _, _, _) = pat.node {
if let ty::TyRef(_, ref tam) = cx.tcx.tables().pat_ty(pat).sty {
if tam.mutbl == MutImmutable {
if let ty::TyRef(..) = tam.ty.sty {
4 changes: 2 additions & 2 deletions clippy_lints/src/needless_update.rs
Original file line number Diff line number Diff line change
@@ -30,8 +30,8 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
let ty = cx.tcx.tables().expr_ty(expr);
if let TyAdt(def, _) = ty.sty {
4 changes: 2 additions & 2 deletions clippy_lints/src/neg_multiply.rs
Original file line number Diff line number Diff line change
@@ -31,8 +31,8 @@ impl LintPass for NegMultiply {
}

#[allow(match_same_arms)]
impl LateLintPass for NegMultiply {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NegMultiply {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node {
match (&l.node, &r.node) {
(&ExprUnary(..), &ExprUnary(..)) => (),
12 changes: 10 additions & 2 deletions clippy_lints/src/new_without_default.rs
Original file line number Diff line number Diff line change
@@ -89,8 +89,16 @@ impl LintPass for NewWithoutDefault {
}
}

impl LateLintPass for NewWithoutDefault {
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Expr, span: Span, id: ast::NodeId) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
fn check_fn(
&mut self,
cx: &LateContext<'a, 'tcx>,
kind: FnKind<'tcx>,
decl: &'tcx hir::FnDecl,
_: &'tcx hir::Expr,
span: Span,
id: ast::NodeId,
) {
if in_external_macro(cx, span) {
return;
}
41 changes: 25 additions & 16 deletions clippy_lints/src/no_effect.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def::Def;
use rustc::hir::{Expr, Expr_, Stmt, StmtSemi, BlockCheckMode, UnsafeSource};
use utils::{in_macro, span_lint, snippet_opt, span_lint_and_then};
use std::ops::Deref;
@@ -68,13 +68,17 @@ fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool {
}
}
Expr_::ExprCall(ref callee, ref args) => {
let def = cx.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
match def {
Some(Def::Struct(..)) |
Some(Def::Variant(..)) |
Some(Def::StructCtor(..)) |
Some(Def::VariantCtor(..)) => args.iter().all(|arg| has_no_effect(cx, arg)),
_ => false,
if let Expr_::ExprPath(ref qpath) = callee.node {
let def = cx.tcx.tables().qpath_def(qpath, callee.id);
match def {
Def::Struct(..) |
Def::Variant(..) |
Def::StructCtor(..) |
Def::VariantCtor(..) => args.iter().all(|arg| has_no_effect(cx, arg)),
_ => false,
}
} else {
false
}
}
Expr_::ExprBlock(ref block) => {
@@ -98,8 +102,8 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
if let StmtSemi(ref expr, _) = stmt.node {
if has_no_effect(cx, expr) {
span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect");
@@ -146,12 +150,17 @@ fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Exp
Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
}
Expr_::ExprCall(ref callee, ref args) => {
match cx.tcx.def_map.borrow().get(&callee.id).map(PathResolution::full_def) {
Some(Def::Struct(..)) |
Some(Def::Variant(..)) |
Some(Def::StructCtor(..)) |
Some(Def::VariantCtor(..)) => Some(args.iter().collect()),
_ => None,
if let Expr_::ExprPath(ref qpath) = callee.node {
let def = cx.tcx.tables().qpath_def(qpath, callee.id);
match def {
Def::Struct(..) |
Def::Variant(..) |
Def::StructCtor(..) |
Def::VariantCtor(..) => Some(args.iter().collect()),
_ => None,
}
} else {
None
}
}
Expr_::ExprBlock(ref block) => {
20 changes: 10 additions & 10 deletions clippy_lints/src/non_expressive_names.rs
Original file line number Diff line number Diff line change
@@ -59,9 +59,9 @@ struct ExistingName {
whitelist: &'static [&'static str],
}

struct SimilarNamesLocalVisitor<'a, 'b: 'a> {
struct SimilarNamesLocalVisitor<'a, 'tcx: 'a> {
names: Vec<ExistingName>,
cx: &'a EarlyContext<'b>,
cx: &'a EarlyContext<'tcx>,
lint: &'a NonExpressiveNames,
single_char_names: Vec<char>,
}
@@ -76,10 +76,10 @@ const WHITELIST: &'static [&'static [&'static str]] = &[
&["set", "get"],
];

struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>);
struct SimilarNamesNameVisitor<'a: 'b, 'tcx: 'a, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>);

impl<'a, 'b, 'c> Visitor for SimilarNamesNameVisitor<'a, 'b, 'c> {
fn visit_pat(&mut self, pat: &Pat) {
impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> {
fn visit_pat(&mut self, pat: &'tcx Pat) {
match pat.node {
PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name),
PatKind::Struct(_, ref fields, _) => {
@@ -120,7 +120,7 @@ fn whitelisted(interned_name: &str, list: &[&str]) -> bool {
false
}

impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> {
impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
fn check_short_name(&mut self, c: char, span: Span) {
// make sure we ignore shadowing
if self.0.single_char_names.contains(&c) {
@@ -236,18 +236,18 @@ impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> {
}
}

impl<'a, 'b> Visitor for SimilarNamesLocalVisitor<'a, 'b> {
fn visit_local(&mut self, local: &Local) {
impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
fn visit_local(&mut self, local: &'tcx Local) {
if let Some(ref init) = local.init {
self.apply(|this| walk_expr(this, &**init));
}
// add the pattern after the expression because the bindings aren't available yet in the init expression
SimilarNamesNameVisitor(self).visit_pat(&*local.pat);
}
fn visit_block(&mut self, blk: &Block) {
fn visit_block(&mut self, blk: &'tcx Block) {
self.apply(|this| walk_block(this, blk));
}
fn visit_arm(&mut self, arm: &Arm) {
fn visit_arm(&mut self, arm: &'tcx Arm) {
self.apply(|this| {
// just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier
SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]);
6 changes: 3 additions & 3 deletions clippy_lints/src/ok_if_let.rs
Original file line number Diff line number Diff line change
@@ -40,13 +40,13 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_let_chain! {[ //begin checking variables
let ExprMatch(ref op, ref body, ref source) = expr.node, //test if expr is a match
let MatchSource::IfLetDesugar { .. } = *source, //test if it is an If Let
let ExprMethodCall(_, _, ref result_types) = op.node, //check is expr.ok() has type Result<T,E>.ok()
let PatKind::TupleStruct(ref x, ref y, _) = body[0].pats[0].node, //get operation
let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pats[0].node, //get operation
method_chain_args(op, &["ok"]).is_some() //test to see if using ok() methoduse std::marker::Sized;

], {
4 changes: 2 additions & 2 deletions clippy_lints/src/open_options.rs
Original file line number Diff line number Diff line change
@@ -32,8 +32,8 @@ impl LintPass for NonSensical {
}
}

impl LateLintPass for NonSensical {
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSensical {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
if let ExprMethodCall(ref name, _, ref arguments) = e.node {
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&arguments[0]));
if &*name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
16 changes: 8 additions & 8 deletions clippy_lints/src/overflow_check_conditional.rs
Original file line number Diff line number Diff line change
@@ -29,15 +29,15 @@ impl LintPass for OverflowCheckConditional {
}
}

impl LateLintPass for OverflowCheckConditional {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OverflowCheckConditional {
// a + b < a, a > a + b, a < a - b, a - b > a
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_let_chain! {[
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node,
let Expr_::ExprPath(_,ref path1) = ident1.node,
let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = second.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = second.node,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.tables().expr_ty(ident1).is_integral(),
cx.tcx.tables().expr_ty(ident2).is_integral()
@@ -57,9 +57,9 @@ impl LateLintPass for OverflowCheckConditional {
if_let_chain! {[
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = second.node,
let Expr_::ExprPath(_,ref path1) = ident1.node,
let Expr_::ExprPath(_, ref path2) = ident2.node,
let Expr_::ExprPath(_, ref path3) = first.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path1)) = ident1.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path2)) = ident2.node,
let Expr_::ExprPath(QPath::Resolved(_, ref path3)) = first.node,
&path1.segments[0] == &path3.segments[0] || &path2.segments[0] == &path3.segments[0],
cx.tcx.tables().expr_ty(ident1).is_integral(),
cx.tcx.tables().expr_ty(ident2).is_integral()
9 changes: 4 additions & 5 deletions clippy_lints/src/panic.rs
Original file line number Diff line number Diff line change
@@ -32,16 +32,15 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_let_chain! {[
let ExprBlock(ref block) = expr.node,
let Some(ref ex) = block.expr,
let ExprCall(ref fun, ref params) = ex.node,
params.len() == 2,
let ExprPath(None, _) = fun.node,
let Some(fun) = resolve_node(cx, fun.id),
match_def_path(cx, fun.def_id(), &paths::BEGIN_PANIC),
let ExprPath(ref qpath) = fun.node,
match_def_path(cx, resolve_node(cx, qpath, fun.id).def_id(), &paths::BEGIN_PANIC),
let ExprLit(ref lit) = params[0].node,
is_direct_expn_of(cx, params[0].span, "panic").is_some(),
let LitKind::Str(ref string, _) = lit.node,
6 changes: 3 additions & 3 deletions clippy_lints/src/partialeq_ne_impl.rs
Original file line number Diff line number Diff line change
@@ -35,12 +35,12 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if_let_chain! {[
let ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) = item.node,
!is_automatically_derived(&*item.attrs),
cx.tcx.expect_def(trait_ref.ref_id).def_id() == cx.tcx.lang_items.eq_trait().unwrap(),
trait_ref.path.def.def_id() == cx.tcx.lang_items.eq_trait().unwrap(),
], {
for impl_item in impl_items {
if &*impl_item.name.as_str() == "ne" {
21 changes: 10 additions & 11 deletions clippy_lints/src/print.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ use rustc::hir::*;
use rustc::hir::map::Node::{NodeItem, NodeImplItem};
use rustc::lint::*;
use utils::paths;
use utils::{is_expn_of, match_path, match_def_path, resolve_node, span_lint};
use utils::{is_expn_of, match_def_path, resolve_node, span_lint, match_path_old};
use format::get_argument_fmtstr_parts;

/// **What it does:** This lint warns when you using `print!()` with a format string that
@@ -65,13 +65,13 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_let_chain! {[
let ExprCall(ref fun, ref args) = expr.node,
let ExprPath(..) = fun.node,
let Some(fun) = resolve_node(cx, fun.id),
let ExprPath(ref qpath) = fun.node,
], {
let fun = resolve_node(cx, qpath, fun.id);
let fun_id = fun.def_id();

// Search for `std::io::_print(..)` which is unique in a
@@ -93,9 +93,8 @@ impl LateLintPass for Pass {
// ensure we're calling Arguments::new_v1
args.len() == 1,
let ExprCall(ref args_fun, ref args_args) = args[0].node,
let ExprPath(..) = args_fun.node,
let Some(def) = resolve_node(cx, args_fun.id),
match_def_path(cx, def.def_id(), &paths::FMT_ARGUMENTS_NEWV1),
let ExprPath(ref qpath) = args_fun.node,
match_def_path(cx, resolve_node(cx, qpath, args_fun.id).def_id(), &paths::FMT_ARGUMENTS_NEWV1),
args_args.len() == 2,
let ExprAddrOf(_, ref match_expr) = args_args[1].node,
let ExprMatch(ref args, _, _) = match_expr.node,
@@ -121,8 +120,8 @@ impl LateLintPass for Pass {
// Search for something like
// `::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Debug::fmt)`
else if args.len() == 2 && match_def_path(cx, fun_id, &paths::FMT_ARGUMENTV1_NEW) {
if let ExprPath(None, _) = args[1].node {
let def_id = resolve_node(cx, args[1].id).unwrap().def_id();
if let ExprPath(ref qpath) = args[1].node {
let def_id = cx.tcx.tables().qpath_def(qpath, args[1].id).def_id();
if match_def_path(cx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) &&
is_expn_of(cx, expr.span, "panic").is_none() {
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
@@ -141,7 +140,7 @@ fn is_in_debug_impl(cx: &LateContext, expr: &Expr) -> bool {
// `Debug` impl
if let Some(NodeItem(item)) = map.find(map.get_parent(item.id)) {
if let ItemImpl(_, _, _, Some(ref tr), _, _) = item.node {
return match_path(&tr.path, &["Debug"]);
return match_path_old(&tr.path, &["Debug"]);
}
}
}
16 changes: 8 additions & 8 deletions clippy_lints/src/ptr.rs
Original file line number Diff line number Diff line change
@@ -54,14 +54,14 @@ impl LintPass for PointerPass {
}
}

impl LateLintPass for PointerPass {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(ref decl, _, _, _, _, _) = item.node {
check_fn(cx, decl, item.id);
}
}

fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
if let ImplItemKind::Method(ref sig, _) = item.node {
if let Some(NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) {
if let ItemImpl(_, _, _, Some(_), _, _) = it.node {
@@ -72,13 +72,13 @@ impl LateLintPass for PointerPass {
}
}

fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
if let MethodTraitItem(ref sig, _) = item.node {
check_fn(cx, &sig.decl, item.id);
}
}
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {

fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprBinary(ref op, ref l, ref r) = expr.node {
if (op.node == BiEq || op.node == BiNe) && (is_null_path(l) || is_null_path(r)) {
span_lint(cx,
@@ -94,7 +94,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) {
let fn_def_id = cx.tcx.map.local_def_id(fn_id);
let fn_ty = cx.tcx.item_type(fn_def_id).fn_sig().skip_binder();

for (arg, ty) in decl.inputs.iter().zip(&fn_ty.inputs) {
for (arg, ty) in decl.inputs.iter().zip(fn_ty.inputs()) {
if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = ty.sty {
if match_type(cx, ty, &paths::VEC) {
span_lint(cx,
@@ -116,7 +116,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId) {
fn is_null_path(expr: &Expr) -> bool {
if let ExprCall(ref pathexp, ref args) = expr.node {
if args.is_empty() {
if let ExprPath(_, ref path) = pathexp.node {
if let ExprPath(ref path) = pathexp.node {
return match_path(path, &paths::PTR_NULL) || match_path(path, &paths::PTR_NULL_MUT)
}
}
20 changes: 10 additions & 10 deletions clippy_lints/src/ranges.rs
Original file line number Diff line number Diff line change
@@ -46,8 +46,8 @@ impl LintPass for StepByZero {
}
}

impl LateLintPass for StepByZero {
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node {
let name = &*name.as_str();

@@ -73,15 +73,15 @@ impl LateLintPass for StepByZero {
let ExprMethodCall(Spanned { node: ref len_name, .. }, _, ref len_args) = end.node,
&*len_name.as_str() == "len" && len_args.len() == 1,
// .iter() and .len() called on same Path
let ExprPath(_, Path { segments: ref iter_path, .. }) = iter_args[0].node,
let ExprPath(_, Path { segments: ref len_path, .. }) = len_args[0].node,
iter_path == len_path
let ExprPath(QPath::Resolved(_, ref iter_path)) = iter_args[0].node,
let ExprPath(QPath::Resolved(_, ref len_path)) = len_args[0].node,
iter_path.segments == len_path.segments
], {
span_lint(cx,
RANGE_ZIP_WITH_LEN,
expr.span,
&format!("It is more idiomatic to use {}.iter().enumerate()",
snippet(cx, iter_args[0].span, "_")));
span_lint(cx,
RANGE_ZIP_WITH_LEN,
expr.span,
&format!("It is more idiomatic to use {}.iter().enumerate()",
snippet(cx, iter_args[0].span, "_")));
}}
}
}
14 changes: 7 additions & 7 deletions clippy_lints/src/regex.rs
Original file line number Diff line number Diff line change
@@ -82,12 +82,12 @@ impl LintPass for Pass {
}
}

impl LateLintPass for Pass {
fn check_crate(&mut self, _: &LateContext, _: &Crate) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_crate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx Crate) {
self.spans.clear();
}

fn check_block(&mut self, cx: &LateContext, block: &Block) {
fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block) {
if_let_chain!{[
self.last.is_none(),
let Some(ref expr) = block.expr,
@@ -106,19 +106,19 @@ impl LateLintPass for Pass {
}}
}

fn check_block_post(&mut self, _: &LateContext, block: &Block) {
fn check_block_post(&mut self, _: &LateContext<'a, 'tcx>, block: &'tcx Block) {
if self.last.map_or(false, |id| block.id == id) {
self.last = None;
}
}

fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_let_chain!{[
let ExprCall(ref fun, ref args) = expr.node,
let ExprPath(ref qpath) = fun.node,
args.len() == 1,
let Some(def) = cx.tcx.def_map.borrow().get(&fun.id),
], {
let def_id = def.full_def().def_id();
let def_id = cx.tcx.tables().qpath_def(qpath, fun.id).def_id();
if match_def_path(cx, def_id, &paths::REGEX_NEW) ||
match_def_path(cx, def_id, &paths::REGEX_BUILDER_NEW) {
check_regex(cx, &args[0], true);
6 changes: 3 additions & 3 deletions clippy_lints/src/serde.rs
Original file line number Diff line number Diff line change
@@ -26,10 +26,10 @@ impl LintPass for Serde {
}
}

impl LateLintPass for Serde {
fn check_item(&mut self, cx: &LateContext, item: &Item) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Serde {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemImpl(_, _, _, Some(ref trait_ref), _, ref items) = item.node {
let did = cx.tcx.expect_def(trait_ref.ref_id).def_id();
let did = trait_ref.path.def.def_id();
if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
if did == visit_did {
let mut seen_str = None;
Loading